Search code examples
phpxpathsimplexml

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


Solution

  • 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.