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

Is there a way to get simple XML child elements by node name?

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

例如,这是我的 XML:

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

我正在寻找一种 returns 类似的方法: 大批( [0] => 'Jan', [1] => 'Kees' )

通过调用类似的东西:

$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

您可以通过多种复杂的方式使用 $xml->xpath() 到 select 节点:

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

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

不过他没有解释原因。当您使用

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

$xml中元素的所有children名为“grandchild”。但是该元素没有任何具有该名称的 child-elements 。它只有一个名为“child”的 child 元素。这就是它不起作用的原因。

相反,您还想更深入地遍历 grand-children 和 grand-grand-children。 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

这个迭代器有点方便,但是,这里还有一种更直接的方法,没有任何新功能,它在所有 children 中查找,直到找到名为“grandchild”的元素:

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

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

        echo $object, "\n";
    }
}

输出相同。

希望这两个例子能说明/解释一下为什么 children() 不足以完成您想要使用它的工作,因为它 return children of child仁.

完整示例:

<?php
/**
 * 
 */

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