有没有办法按节点名称获取简单的XML子元素?

时间:2015-01-02 11:24:17

标签: php xml xpath simplexml

在PHP中,是否存在按节点名称(递归)获取一个或多个子元素的现有方法,或者您是否必须自己编写一个函数?

例如,这是我的XML:

<parent>
    <child>
        <grandchild>Jan</grandchild>
        <grandchild>Kees</grandchild>
    </child>
</parent>

我正在寻找一种返回类似的方法:     阵列(        [0] =&gt; &#39;扬&#39 ;,        [1] =&gt; &#39;基斯&#39;     )

通过调用类似的方式:

$grandchildren = $xml->children('grandchild');

以上确实根据文档存在,但仅适用于名称空间。

e:下面接受的答案有效。这就是我跑来测试它。

$xml = '
    <parent>
        <child>
            <grandchild>Jan</grandchild>
            <grandchild>Kees</grandchild>
        </child>
    </parent>';

$L_o_xml = new SimpleXMLElement($xml);

$L_o_child = $L_o_xml->xpath('//grandchild');

foreach( $L_o_child as $hi ){
   print "\n".(string)$hi;
}

简单打印:

Jan
Kees

2 个答案:

答案 0 :(得分:3)

您可以使用$xml->xpath()以各种复杂的方式选择节点:

$xml->xpath('//grandchild');   // select all  grandchild  elements in the document

答案 1 :(得分:0)

JLRishe已经给出了使用xpath查询的最方便的答案。

然而,他并没有解释为什么。当你使用

$grandchildren = $xml->children('grandchild');

所有孩子都会被命名为&#34; grandchild&#34; $xml中的元素。但该元素没有任何具有该名称的子元素。它只有一个名为&#34; child&#34;的子元素。这就是为什么它不起作用。

相反,你想要更深入地走进​​幼儿和曾孙子女。 Xpath在这里非常有帮助。但是,还有一个更专业的 SimpleXMLElement 名为 SimpleXMLIterator ,它允许递归遍历相当容易:

$xml       = new SimpleXMLIterator($buffer);
$recursive = new RecursiveIteratorIterator($xml);

foreach ($recursive as $tag => $object) {
    if ($tag !== 'grandchild') {
        continue;
    }

    echo $object, "\n";
}

输出:

Jan
Kees

这个迭代器有点方便,但是,在找到名为&#34; grandchild&#34;的元素之前,这里有一个更直接的方法,没有任何新功能可以查找所有孩子:

$stack = [new SimpleXMLElement($buffer)];

while ($has = array_pop($stack)) {
    foreach ($has as $tag => $object) {
        if ($tag !== 'grandchild') {
            $stack[] = $object;
            continue;
        }

        echo $object, "\n";
    }
}

输出相同。

希望这两个例子能够说明/解释为什么children()不足以满足您想要使用它的工作,因为它不会返回给孩子的孩子。

完整示例:

<?php
/**
 * http://stackoverflow.com/questions/27741380/is-there-a-way-to-get-simple-xml-child-elements-by-node-name
 */

$buffer = <<<'XML'
<parent>
    <child>
        <grandchild>Jan</grandchild>
        <grandchild>Kees</grandchild>
    </child>
</parent>
XML;

$xml       = new SimpleXMLIterator($buffer);
$recursive = new RecursiveIteratorIterator($xml);

foreach ($recursive as $tag => $object) {
    if ($tag !== 'grandchild') {
        continue;
    }

    echo $object, "\n";
}

$stack = [new SimpleXMLElement($buffer)];

while ($has = array_pop($stack)) {
    foreach ($has as $tag => $object) {
        if ($tag !== 'grandchild') {
            $stack[] = $object;
            continue;
        }

        echo $object, "\n";
    }
}