使用PHP SimpleXML选择具有特定名称的所有节点 - 附加源代码

时间:2013-05-08 11:46:21

标签: php xpath simplexml

在以下XML文件中,我尝试打印所有TestItem个节点,但只获取4个outer个节点。

有人知道,如何打印具有该名称的每个节点,无论其位置如何?

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 输出(为什么它只列出4个TestItems?):

UpdateBootProfile PASS
NRB Boot PASS
Check device Type PASS
Assign BSN and Erase EFS PASS

在CentOS 6.3命令行上使用PHP 5.3.5。

更新

建议的//TestItem适用于我上面的简单测试用例,谢谢。

但是我的真实数据(我无法在此处粘贴)仍然失败:

# grep -w TestItem my_real_file_May_2013_09_35_38.xml |wc -l
143

# php -f parse.php |wc -l
86

请有人知道,//TestItem会错过某些节点吗?

更新2:

实际上它有效!由于一些</TestItem>结束标记,上面的grep突击队员计算了更多行: - )

3 个答案:

答案 0 :(得分:4)

你可以简单地这样做

$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;

通过上面的操作,您将获得所有元素包含<TestItem>个元素。

答案 1 :(得分:1)

使用以下xpath选择节点,无论它们在树中的位置如何:

$items = $xml->xpath('//TestItem');

或者

$items = $xml->xpath('//TestItem/TestItem');

如果您只需要叶节点。

输出(来自第二个):

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

请注意//。详情了解W3schools XPath tutorial.

答案 2 :(得分:-1)

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'];
    }
}

尝试一下,只需要做反击以获得xml的深度,在你的情况下为4级。