EDIT: The reason I used json_decode is to get it from XML to an array.
So here is my dilemma:
I access an API that returns xml, I then convert it to an array as follows:
public function convertXMLtoJSON($xml){
return json_decode(json_encode(simplexml_load_string($xml), true), true);
}
When I have a single item (for example:) [SINGLE ITEM XML]
<LineItem>
<field>hello</field>
</LineItem>
It gets displayed like: [SINGLE ITEM ARRAY]
[LineItem] => Array(
[field] => hello
)
now if I have: [MULTI ITEM XML]
<LineItem>
<field>hello</field>
</LineItem>
<LineItem>
<field>hello part 2</field>
</LineItem>
I get: [MULTI ITEM ARRAY]
[LineItem] => Array(
[0] => Array (
[field] => hello
)
[1] => Array (
[field] => hello part 2
)
)
I need the first example to be in an array, not just by itself because differentiating between the two is just going to be way too time consuming.
As I understand your specific question, you want everything to be formatted like the multi array, even if there is only a single result.
I would handle this by checking the array for a count of 1 after it is returned. Let us suppose that you have an array called $xmlArray that has a single result in the format you describe.
if (count($xmlArray) == 1) {
$multiArray['LineItem'][] = $xmlArray['LineItem'];
}
This will convert the $xmlArray with a single element into the multi-line array format you have described in your question.
Related
I have an array list of tags from xml file and im using xml file to add some posts to wordpress. So i need to convert xml array to comma separated list for tags to import in my posts.
This is an xml file example
<tags>
<tag>tag1</tag>
<tag>tag2</tag>
<tag>tag3</tag>
</tags>
So when i call this file in my .php file and use print_r to get the output i get this
SimpleXMLElement Object (
[tag] => Array (
[0] => SimpleXMLElement Object ( )
[1] => SimpleXMLElement Object ( )
[2] => SimpleXMLElement Object ( )
[3] => SimpleXMLElement Object ( )
)
)
So 0 1 2 3 are tags and values are stored in SimpleXMLElement Object ( ) i read it's normal to not get values when using print_r but i know the values are there.
Now i need to convert this as a list at the end to get this result
$post_tags = tag1, tag2, tag3;
so that i can use $post_tags in my function.
Assuming your object (the one on which you called print_r() is $xml), you would loop over $xml->tag and append each child object's contents to an array. Finally, implode the array to a string.
// An array to hold it temporarily
$post_tags_arr = array();
foreach ($xml->tag as $t) {
// Cast it to a string to get the text value back
$post_tags_arr[] = (string)$t;
}
// Implode the array to a string
$post_tags = implode(', ', $post_tags_arr);
echo $post_tags;
You indicate that you need a list for $post_tags, but your syntax above is ambiguous as to whether you wanted a string or an array. If you wanted an array, you have it in $post_tags_arr prior to the implode().
If you feel like being clever, and the <tag> nodes reside at the same level and have no children, you can simply cast them as a regular array, which will result in their string values.
// Cast it to an array in one go:
$post_tags_arr = (array)$xml->tag;
print_r($post_tags_arr);
Array
(
[0] => tag1
[1] => tag2
[2] => tag3
)
I am pretty new to PHP an XML and hope you can help me with this.
Searching the forum didn't help me yet to find an answer to my specific issue.
I have a PHP page with a simplexml array that looks like the following, just longer:
SimpleXMLElement Object
(
[textID] => Array
(
[0] => SimpleXMLElement Object
(
[textID] => 1
[content] => Text1
)
[1] => SimpleXMLElement Object
(
[textID] => 2
[content] => Text2
)
[2] => SimpleXMLElement Object
(
[textID] => 3
[content] => Text3
)
)
)
Now I am trying to echo out a specific value from this array by referring to its ID which is an integer.
The only way I get this working is the following but this just goes by the order within the array, not by the actual ID:
<?php echo $objTexts->textID[1]->content; ?>
Can someone tell me what I am missing here ?
Thanks, Tim
SimpleXML has no way of knowing that the textID identifies which node is which - it is just another element in the XML.
Based on your sample output, your XML is a little confusing as you have multiple elements called textID which each have a single child, also called textID, which has a different meaning. Nonetheless, what you want to do can be achieved either by looping through all the outer textID elements and testing the value of their inner textID element:
foreach ( $objTexts->textID as $item )
{
if ( $item->textID == '2' )
{
...
}
}
Or, you could use XPath, which is a fairly simple query language for XML, and is supported within SimpleXML in the form of the ->xpath() method. In your case, you want to find a textID node which contains a textID child with a particular value, so the code would look something like this:
// ->xpath always returns a plain PHP array - not a SimpleXML object
$xpath_results = $objTexts->xpath('//textID[textID=2]');
// If you're certain you only want the first result:
echo $xpath_results[0]->content;
// If you might want multiple matches
foreach ( $xpath_results as $item )
{
...
}
I've searched a lot for this, and found several similar questions, but none quite address what I'm trying to accomplish.
I'm trying to write a code that will search a PHP (multi)multidimensional array to see which subarray contains the unique key value that I have. Then I would like it to return the value of a different key in that same object subarray.
$Arraytosearch = Array(
.
//various other subarrays
.
[fields] => Array (
.
.
.
//I don't know the number of the object subarray
[x] => PodioTextItemField Object (
[__attributes] => Array (
[field_id] => 37325091
[type] => text
[external_id] => id
[label] => ID
[values] => Array (
[0] => Array (
[value] => REF100019 ) )
[config] => Array (
[description] => [settings] => Array (
[size] => small )
[required] => [mapping] => [label] => ID [visible] => 1 [delta] => 2 ) )
.
.
.
//(and so on)
I'd like to write a function that will return "REF100019" by supplying the value of the field_id => 37325091.
Some things I have tried that I couldn't get to work:
foreach
and new RecursiveIterator although the tutorials I read weren't useful for my case here.
Even though the array looks complicated, I think it will be easy since I already have the field id of the parent array.
Thank you in advance for any guidance or sample codes that will work!
Background: This is a part of the response I get from Podio after submitting a request to their API. I just don't know how to take that response and get the piece I need (the ID) so that I can echo it for users).
EDIT: Thank you Orangepill and Barmar for the support. I tried your code. But was getting an error, which made me realize I hadn't given you the full array. I figured out how to get the Podio response to display in a more readable format (I was reading the full JSON response before from the Podio debug file which was super confusing), and figured out the full array is actually structured as I have shown below.
I then took your code and was able to figure out how to make it work for my scenario (see below). Very proud of myself considering I have never written any code before, but I couldn't have done it without your help! Thanks again!
$Arraytosearch = Array(
[items] => Array(
[0] => PodioItem Object(
[_attributes] => Array(
[fields] => Array (
[x] => PodioTextItemField Object (
[__attributes] => Array(
[field_id] => 37325091
[values] => Array(
[0] => Array(
[value] => REF100019 ) )
Note: For anyone who is new to programming like myself and wants the Podio response (or any JSON string) to display in a "pretty" readable format like above, use the code (from Display an array in a readable/hierarchical format thanks to Phenex):
print "<pre>";
print_r($Arraytoformat);
print "</pre>";
And finally, the full code I used (using Orangepill's answer below) which searches the objects and arrays and gives me what I have been searching for for days now is as follows:
$Arraytosearch = PodioItem::filter(APP_ID, $filterParams);
$fieldID = 37325091;
function getFirstValueByFieldId($fieldId, $Arraytosearch){
foreach($Arraytosearch["items"][0]->__attributes["fields"] as $textitem){
if ($textitem->__attributes["field_id"] == $fieldId){
return $textitem->__attributes["values"][0]["value"];
}}}
$refID = getFirstValueByFieldId($fieldID, $Arraytosearch);
The podio-php library has built-in methods that handle all this for you. There's no need to mess with the __attributes property yourself.
You can see a bunch of examples at https://github.com/podio/podio-php/blob/master/examples/items.php
In your case:
// Get item collection
$itemCollection = PodioItem::filter(APP_ID, $filterParams);
$fieldID = 37325091;
foreach ($itemCollection['items'] as $item) {
// Get the field from the item
$field = $item->field($fieldID);
// Now you can print the value of that field
print $field->humanized_value;
// Or if you don't want to have the content sanitized:
print $field->values[0]['value'];
}
There is a lot of ways to skin this cat... this is probably the most straight forward
function getFirstValueByFieldId($fieldId, $Arraytosearch){
foreach($Arraytosearch["fields"] as $textitem){
if ($textitem->__attributes["field_id"] == $fieldId){
return $textitems->__attributes["values"][0]["value"];
}
}
}
to Use in your case would be
echo getFirstValueByFieldId("37325091", $Arraytosearch);
Basically it walks the elements in the fields array and returns the value in the first associated value in the values array where field_id is equal to the parameter of the function.
I'm getting stumped by simply trying to get the key/value of a certain tier inside an array I have created from an XML file. The part of the array from Print_R() is:
SimpleXMLElement Object
(
Array
(
[category] => SimpleXMLElement Object
(
[#attributes] => Array
(
[settings] => maximum
)
[cat_1] => 5.21
[cat_2] => 5.05
[cat_3] => 19.36
[cat_4] => 21.97
[cat_5] => 12.17
)
)
)
I am trying to get the "cat_1, cat_2, cat_3 .." keys so that I can put them in their own array and use them for other things. I can do print_r($array) and it works, but when I try and do this:
foreach ($array->category as $key => $val) {
$new_array[$key]= "$val";
}
$array->category doesn't seem to target that list. The "SimpleXMLElement Object" from the XML file seems to be in the way of how I normally use arrays. Does anyone know how I can get to those cat_1 ets. lists?
Notice that $array->category is an object, not an array and cat_* are properties. Since they are all public just use:
$new_array = get_object_vars($array->category);
You should convert simpleXML object to array using
$array = json_decode(json_encode((array) $simplexmlob)), 1);
Then use $array['category'] for other things. There is no need to use foreach loop.
I'm a bit struggling with the associative arrays in associative arrays. Point is that I always have to drill deeper in an array and I just don't get this right.
$array['sections']['items'][] = array (
'ident' => $item->attributes()->ident,
'type' => $questionType,
'title' => $item->attributes()->title,
'objective' => (string) $item->objectives->material->mattext,
'question' => (string) $item->presentation->material->mattext,
'possibilities' => array (
// is this even neccesary to tell an empty array will come here??
//(string) $item->presentation->response_lid->render_choice->flow_label->response_label->attributes()->ident => (string) $item->presentation->response_lid->render_choice->flow_label->response_label->material->mattext
)
);
foreach ($item->presentation->response_lid->render_choice->children() as $flow_label) {
$array['sections']['items']['possibilities'][] = array (
(string) $flow_label->response_label->attributes()->ident => (string) $flow_label->response_label->material->mattext
);
}
So 'possibilities' => array() contains an array and if I put a value in it like the comment illustrates I get what I need. But an array contains multiple values so I am trying to put multiple values on the position $array['sections']['items']['possibilities'][]
But this outputs that the values are stores on a different level.
...
[items] => Array
(
[0] => Array
(
[ident] => SimpleXMLElement Object
(
[0] => QTIEDIT:SCQ:1000015312
)
[type] => SCQ
...
[possibilities] => Array
(
)
)
[possibilities] => Array
(
[0] => Array
(
[1000015317] => 500 bytes
)
[1] => Array
...
What am trying to accomplish is with my foreach code above is the first [possibilities] => Array is containing the information of the second. And of course that the second will disappear.
Your $array['sections']['items'] is an array of items, so you need to specify which item to add the possibilities to:
$array['sections']['items'][$i]['possibilities'][]
Where $i is a counter in your loop.
Right now you are appending the Arrays to [items]. But you want to append them to a child element of [items]:
You do:
$array['sections']['items']['possibilities'][] = ...
But it should be something like:
$array['sections']['items'][0]['possibilities'][] = ...
$array['sections']['items'] is an array of items, and as per the way you populate the possibilities key, each item will have it's own possibilities. So, to access the possibilities of the item that is being looped over, you need to specify which one from $array['sections']['items'] by passing the index as explained in the first answer.
OR
To make things simpler, you can try
Save the item array (RHS of the first =) to a separate variable instead of defining and appending to the main array at the same time.
Set the possibilities of that variable.
Append that variable to the main $array['sections']['items']
I have:
array[{IsChecked: true, SEC: 0, STP: 0},
{IsChecked: ture ,SEC: 0, STP: 1},
{IsChecked: false, SEC: 1 ,STP: 0}]
How to get each SEC where IsCheked value is true?