add to associative array - php

I have some xml that looks like this:
<?xml version="1.0"?>
<data>
<items>
<item><timestamp>2011-07-11T09:01:42Z</timestamp><title><![CDATA[ some data here ]]></title><link>http://twitter.com/aurl</link></item>
<item><timestamp>2011-05-11T09:01:42Z</timestamp><title><![CDATA[ some data here ]]></title><link>http://twitter.com/aurlhere</link></item>
</items>
and I'm trying to loop over it and add it to an array:
foreach($xml->items->item as $e) {
$feedData['timestamp'] = $e->timestamp;
$feedData['title'] = $e->title;
$feedData['link'] = $e->link;
$feedData['type'] = $e->type;
}
print_r($feedData);
The xml is there and if I put an echo in the foreach I get back 10 responses (whcih are how many items I have) but when I print the array out all I get is one line (which is the last entry in the xml doc).
Array ( [timestamp] => SimpleXMLElement Object ( [0] => 2011-07-08T08:05:19Z ) [title] => SimpleXMLElement Object ( ) [link] => SimpleXMLElement Object ( [0] => http://twitter.com.aurl ) [type] => SimpleXMLElement Object ( ) )
I suspoect I'm overwriting the array on each loop. But why ? It should be adding to the array. Sorry my php isn't great...hence what Is suspect is a bit of a stupid question.

$i = 0;
foreach($xml->items->item as $e) {
$feedData[$i]['timestamp'] = $e->timestamp;
$feedData[$i]['title'] = $e->title;
$feedData[$i]['link'] = $e->link;
$feedData[$i]['type'] = $e->type;
$i++;
}
print_r($feedData);

Well, there is only one $feedData array and you are always setting the value for some specific keys, e.g. $feedData['timestamp']. How do you think this should add to the array? Keys are unique, the same key cannot appear twice, so yes, you are just overwriting the values.
It seems you want an array of arrays:
$feedData = array();
foreach($xml->items->item as $e) {
$feedData[] = array(
'timestamp' => $e->timestamp;
'title' => $e->title;
'link' => $e->link;
'type' => $e->type;
);
}
Have a look at the array manual [docs] for more information about arrays.

Related

selecting value of particular index with PHP foreach

I have the following loop that creates an array
while($row1 = mysqli_fetch_assoc($result1))
{
$aliens[] = array(
'username'=> $row1['username'],
'personal_id'=> $row1['personal_id']
);
}
It produces the following result
Array (
[0] =>
Array ( [username] => nimmy [personal_id] => 21564865 )
[1] =>
Array ( [username] => aiswarya [personal_id] => 21564866 )
[2] =>
Array ( [username] => anna [personal_id] => 21564867 )
Then I have another loop as follows, inside which, I need to fetch the personal_id from the above array. I fetch it as follows.
foreach($aliens as $x=>$x_value)
{
echo $aliens['personal_id'];
//some big operations using the
$aliens['personal_id']; variable
}
However, I can't get the values if personal_ids. I get it as null. What seems to be the problem? How can I solve it?
You have an array of "aliens", each alien is an array with personal_id and username keys.
foreach ($aliens as $index => $alien) {
echo $alien['personal_id'], PHP_EOL;
}
The foreach loop iterates its items (aliens). The $alien variable represents the current iteration's item, i.e. the alien array.
foreach($aliens as $x=>$x_value)
{
echo $x_value['personal_id'];
//some big operations using the
$x_value['personal_id']; variable
}

Storing XML Document with XPath and PHP, tag info isn't storing in array like needed

So, I want to iterate through the XML by the attributes of and then print the tags from within the coordinating tag. This is the structure:
<emp salesid="1">
<report>07-14-2015_DPLOH_SalesID_1.pdf</report>
<report>07-17-2015_DPLOH_SalesID_1.pdf</report>
<report>07-14-2015_DTE_SalesID_1.pdf</report>
<report>07-14-2015_IDT_SalesID_1.pdf</report>
<report>07-14-2015_Kratos_SalesID_1.pdf</report>
<report>07-14-2015_Spark_SalesID_1.pdf</report>
</emp>
Here is the my code:
$xml = new SimpleXMLElement($xmlStr);
foreach($xml->xpath("//emp/report") as $node) {
//For all found nodes retrieve its ID from parent <emp> and store in $arr
$id = $node->xpath("../#salesid");
$id = (int)$id[0];
if(!isset($arr[$id])) {
$arr[$id] = array();
}
//Then we iterate through all nodes and store <report> in $arr
foreach($node as $report) {
$arr[$id][] = (string)$report;
}
}
echo "<pre>";
print_r($arr);
echo "</pre>";
However, this is what I get for output:
Array
(
[1] => Array
(
)
[10] => Array
(
)
... and it continues to iterate through all of the attributes of tags, but never fills the array with any information.
If anyone could help tell me what I'm missing, I would GREATLY appreciate it. I feel like I'm losing my mind over what seems like should be rather simple.
Thanks!
You're very close. The code isn't working because of the second for loop. The outer loop will iterate through all of the report elements. So, node is a report element. When you try to iterate through the children of report, there's nothing there.
Instead of the second (inner) loop, simply do this:
$arr[$id][] = (string)$node;
When I did, I got the following result:
<pre>
Array
(
[1] => Array
(
[0] => 07-14-2015_DPLOH_SalesID_1.pdf
[1] => 07-17-2015_DPLOH_SalesID_1.pdf
[2] => 07-14-2015_DTE_SalesID_1.pdf
[3] => 07-14-2015_IDT_SalesID_1.pdf
[4] => 07-14-2015_Kratos_SalesID_1.pdf
[5] => 07-14-2015_Spark_SalesID_1.pdf
)
)
I updated your script to work slightly differently:
$emp = new SimpleXMLElement($xmlStr);
$id = intval($emp['salesid']);
$arr = array(
$id => array(),
);
$lst = $emp->xpath('/emp/report');
while (list(, $text) = each($lst))
{
$arr[$id][] = (string) $text;
}
echo "<pre>";
print_r($arr);
echo "</pre>";
Cheers

How to get PHP SimpleXML Child Nodes into an array within an array

Background of Problem
I have a large XML file I am trying to parse it into a PHP array.
The structure of my file is as such
<orders>
<order>
<value1></value1>
<value2></value3>
<value2></value3>
<items>
<item></item>
<price></price>
</items>
</order>
</orders>
And so on for many more values.
My PHP function looks like this
public function outputNodes() {
// this function creates/returns an array of all the XML nodes and child nodes
// we do not know how many custom attributes there may be for orders, so this
// handles them programmatically with count
if (file_exists($this->getFilePath())) { // this checks to make sure there is a file
$orders = array(); //create blank array for orders
$obj = $this->getXML($this->getFilePath()); // start by getting XML object
$order = $obj->children();
$oCount = count($order); //How many orders are there?
$topNodes = $obj->order->children();
$topNodesCount = count($topNodes); //How many nodes does each order have?
//begin looping through orders
for($i=0;$i<$oCount;$i++) {
$vals = array(); //for each order create the array to store the values of items node
foreach($topNodes as $key => $value) { //for each top level nodes do something
if((string)$key == "items"){ //checks to see if this top level node is the items node
$cobj = $obj->order->items->children(); //if it is create object of the children of node
foreach($cobj as $k =>$v) { //for each child of items node do something
$v[(string)$k] = (string)$v; //creates a temporary array of the child names/values of items node
}
$vals[] = $v; //places them into $vals array
$ord[(string)$key] = $vals; //places entire $vals array into temp ord array for output
}
else {
$ord[(string)$key] = (string)$value;
}
}
$orders[] = $ord;
}
return $orders;
}
else {
return "Error";
}
}
Now to be clear, this code works fine in theory, it does put $vals[] array into the $orders[] array, however it does so like this:
[items] => Array ( [0] => SimpleXMLElement Object ( [#attributes] => Array ( [item] => ) [item_name] => Nameof Product [item_price] => $8.00 [item_quantity] => 12 ) ) )
Questions
So then I have two questions. Firstly how can I stop it from putting Array ( [0] => SimpleXMLElement Object ( [#attributes] this erroneous information in?
Secondly, and more to the point, how can I modify the code so rather than having to call the items node by name, I can rather have it check to see if any given node has more children that it automatically pulls them out into an array?
I'd prefer to not have to write new code every time there is more subnodes and simply have it check: Is there subnodes? If yes, get them and display them in a nested array
Thanks in advance
One way to achieve this, is to iterate over all the elements in the document and then build the array based on the data-flow:
$builder = new StructureBuilder();
foreach ($xml->xpath('//*') as $element) {
$depth = count($element->xpath("./ancestor::*"));
$builder->add($depth, $element->getName(), trim($element));
}
print_r($builder->getStructure());
With the example data of yours this is:
Array
(
[orders] => Array
(
[order] => Array
(
[value1] =>
[value2] =>
[value3] =>
[items] => Array
(
[item] =>
[price] =>
)
)
)
)
How does it work? The StructureBuilder keeps track on which element in the structure is ready for $depth. You can find the full example code as gist.
You can also see this previous answer PHP Parse XML response with many namespaces which asked also about how to convert. The example there is more verbose regarding the indenting.

Through an array with other array in php

I have a question for you, I need to through an array with other arrays in php but i through only the last array, my array is:
Array
(
[0] => Array
(
[syn_id] => 17070
[syn_label] => fd+dfd
)
[1] => Array
(
[syn_id] => 17068
[syn_label] => fds+dsfds
)
[2] => Array
(
[syn_id] => 17069
[syn_label] => klk+stw
)
)
My php:
$a_ddata = json_decode(method(), true);
foreach ($a_ddata as $a_data)
{
$a_data['syn_label'] = urldecode(utf8_decode($a_data['syn_label']));
}
With this code I through only the last array [2], but how to through array?please help me
I need to get the array:
Array
(
[0] => Array
(
[syn_id] => 17070
[syn_label] => fd dfd
)
[1] => Array
(
[syn_id] => 17068
[syn_label] => fds dsfds
)
[2] => Array
(
[syn_id] => 17069
[syn_label] => klk stw
)
)
$a_ddata = json_decode(method(), true); $i=0;
foreach ($a_ddata as $a_data)
{
$a_data_f[$i]['syn_id'] = $a_data['syn_id'];
$a_data_f[$i]['syn_label'] = urldecode(utf8_decode($a_data['syn_label']));
$i++;
}
This should be your answer..
When you iterate through something using foreach, by default PHP makes a copy of each element for you to use within the loop. So in your code,
$a_ddata = json_decode(method(), true);
foreach ($a_ddata as $a_data)
{
// $a_data is a separate copy of one of the child arrays in $a_ddata
// this next line will modify the copy
$a_data['syn_label'] = urldecode(utf8_decode($a_data['syn_label']));
// but at the end of the loop the copy is discarded and replaced with a new one
}
Fortunately the manual page for foreach gives us a way to override this behavior with the reference operator &. If you place it between the as keyword and your loop variable, you're able to update the source array within your loop.
$a_ddata = json_decode(method(), true);
foreach ($a_ddata as &$a_data)
{
// $a_data is now a reference to one of the elements to $a_ddata
// so, this next line will update $a_ddata's individual records
$a_data['syn_label'] = urldecode(utf8_decode($a_data['syn_label']));
}
// and you should now have the result you want in $a_ddata
This should help:
$a_data['syn_label'][] = urldecode(utf8_decode($a_data['syn_label']));
For each iteration you are only replacing $a_data['syn_label']. By adding [] you are making it a multi dimension array which increments for every iteration.

query xpath with php

I wrote following php code to extract nodes information from this xml:
<sioctBoardPost rdfabout="http//boards.ie/vbulletin/showpost.php?p=67075">
<rdftype rdfresource="http//rdfs.org/sioc/ns#Post" />
<dctitle>hib team</dctitle>
<siochas_creator>
<siocUser rdfabout="http//boards.ie/vbulletin/member.php?u=497#user">
<rdfsseeAlso rdfresource="http//boards.ie/vbulletin/sioc.php?sioc_type=user&sioc_id=497" />
</siocUser>
</siochas_creator>
<dctermscreated>1998-04-25T213200Z</dctermscreated>
<sioccontent>zero, those players that are trialing 300 -400 pingers? umm..mager lagg and even worse/</sioccontent>
</sioctBoardPost>
<?php
$xml = simplexml_load_file("boards.xml");
$products[0] = $xml->xpath("/sioctBoardPost/sioccontent");
$products[1] = $xml->xpath("/sioctBoardPost/dctermscreated");
$products[2] = $xml->xpath("/sioctBoardPost/#rdfabout");
print_r($products);
?>
This gives following output:
Array (
[0] => Array ( [0] => SimpleXMLElement Object ( [0] => zero, those players that are trialing for hib team, (hpb's) most of them are like 300 -400 pingers? umm..mager lagg and even worse when they play on uk server's i bet/ ) ) [1] => Array ( [0] => SimpleXMLElement Object ( [0] => 1998-04-25T213200Z ) ) [2] => Array ( [0] => SimpleXMLElement Object ( [#attributes] => Array ( [rdfabout] => http//boards.ie/vbulletin/showpost.php?p=67075 ) ) )
)
But I need only nodes content as an output i.e without Array([0] => Array etc.
Output should be like this:
zero, those players that are trialing for hib team, (hpb's) most of them are like 300 -400 pingers? umm..mager lagg and even worse when they play on uk server's i bet
1998-04-25T213200Z
http//boards.ie/vbulletin/showpost.php?p=67075
Thanks in advance
You can use current() to only get the first element of each XPath result (which is an array) and then use a (string) cast to get the node contents:
$products[0] = (string)current($xml->xpath("/sioctBoardPost/sioccontent"));
$products[1] = (string)current($xml->xpath("/sioctBoardPost/dctermscreated"));
$products[2] = (string)current($xml->xpath("/sioctBoardPost/#rdfabout"));
print_r($products);
As you have observed, the xpath() method returns an array of matched nodes, so you need to deal with the elements of the returned arrays. I believe this should work in this case:
$xml = simplexml_load_file("boards.xml");
$products[0] = $xml->xpath("/sioctBoardPost/sioccontent")[0];
$products[1] = $xml->xpath("/sioctBoardPost/dctermscreated")[0];
$products[2] = $xml->xpath("/sioctBoardPost/#rdfabout")[0];
print_r($products);
This should get you what you need...
foreach ($products as $product) { // iterate through the $products array
print $product[0]->nodeValue // output the node value of the SimpleXMLElement Object
}

Categories