Reputation: 22988
In the following XML file I'm trying to print all TestItem
nodes, but get only the 4 outer
nodes.
Does anybody please know, how to print every node having that name, regardless of their position?
data.xml:
<?xml version="1.0"?>
<Tests>
<TestItem Name="UpdateBootProfile" Result="PASS" />
<TestItem Name="NRB Boot" Result="PASS">
<TestItem Name="Boot Test" Result="PASS">
<TestItem Name="PreparePowerSupply" Result="PASS" />
<TestItem Name="ApplyBatteryVoltage" Result="PASS" />
<TestItem Name="Shelf Mode test" Result="PASS">
</TestItem>
<TestItem Name="ApplyUSBVoltage" Result="PASS" />
<TestItem Name="DetectBoard" Result="PASS" />
<TestItem Name="Device Current Profile" Result="PASS" />
<TestItem Name="Device Connection" Result="PASS">
</TestItem>
</TestItem>
</TestItem>
<TestItem Name="Check device Type" Result="PASS" />
<TestItem Name="Assign BSN and Erase EFS" Result="PASS">
</TestItem>
</Tests>
parse.php:
<?php
$tmp = 'data.xml';
$str = file_get_contents($tmp);
$xml = new SimpleXMLElement($str);
$items = $xml->xpath('TestItem');
while(list( , $test) = each($items)) {
printf("%s %s\n", $test['Name'], $test['Result']);
}
?>
php -f parse.php output (why does it list only 4 TestItems?):
UpdateBootProfile PASS
NRB Boot PASS
Check device Type PASS
Assign BSN and Erase EFS PASS
Using PHP 5.3.5 on CentOS 6.3 command line.
UPDATE:
The suggested //TestItem
works for my simple test case above, thank you.
But it still fails for my real data (which I can't paste here):
# grep -w TestItem my_real_file_May_2013_09_35_38.xml |wc -l
143
# php -f parse.php |wc -l
86
Does anybody please have an idea, which would //TestItem
miss some nodes?
UPDATE 2:
Actually it works! The grep commando above counted more lines because of some </TestItem>
closing tags :-)
Upvotes: 4
Views: 9406
Reputation: 157967
Use the following xpath to select nodes regardless from their position in tree:
$items = $xml->xpath('//TestItem');
Or
$items = $xml->xpath('//TestItem/TestItem');
If you only need the leaf nodes.
Output (from second one):
UpdateBootProfile PASS
NRB Boot PASS
Boot Test PASS
PreparePowerSupply PASS
ApplyBatteryVoltage PASS
Shelf Mode test PASS
ApplyUSBVoltage PASS
DetectBoard PASS
Device Current Profile PASS
Device Connection PASS
Check device Type PASS
Assign BSN and Erase EFS PASS
Note the //
. Learn more about in the W3schools XPath tutorial.
Upvotes: 2
Reputation: 2790
function printxml($xml,$deep = 4){
if($xml instanceOf SimpleXMLElement)
$xml = (array)$xml;
foreach($xml->TestItem as $t){
if(is_array($t) && $deep > 0)
printxml($t, $deep-1);
else
echo $t['Name'].' '.$t['Result'];
}
}
Try it, just have to do counter to get the deep of xml, in your case 4 levels.
Upvotes: -1
Reputation: 2758
You can simply do this
$testitems = simplexml_load_file("testitem.xml");
if(count($testitems)):
$result = $testitems->xpath("//TestItem");
//echo "<pre>";print_r($result);die;
foreach ($result as $item):
echo "Name ".$item['Name'] ." and result ". $item['Result'];
echo "<hr>";
endforeach;
endif;
By doing above you will get all elements haveing <TestItem>
elements.
Upvotes: 5