Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select all nodes with a certain name by using PHP SimpleXML - source code attached

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 :-)

like image 464
Alexander Farber Avatar asked Oct 20 '25 01:10

Alexander Farber


2 Answers

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.

like image 132
NullPointer Avatar answered Oct 21 '25 16:10

NullPointer


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.

like image 38
hek2mgl Avatar answered Oct 21 '25 16:10

hek2mgl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!