PHPDOM:如何以优雅的方式通过标记名获取子元素?

PHPDOM:如何以优雅的方式通过标记名获取子元素?,php,xml,dom,Php,Xml,Dom,我正在用PHPDOM扩展解析一些XML,以便以其他形式存储数据。毫不奇怪,当我解析一个元素时,我经常需要获取某个名称的所有子元素。有一个方法DomeElement::getElementsByTagName($name),但它返回所有具有该名称的子代,而不仅仅是直接子代。还有属性DOMNode::$childNodes,但是(1)它包含节点列表,而不是元素列表,即使我设法将列表项转换为元素(2),我仍然需要检查所有这些项的名称。是否真的没有优雅的解决方案来只获取某个特定名称的子对象,或者我在文档

我正在用PHPDOM扩展解析一些XML,以便以其他形式存储数据。毫不奇怪,当我解析一个元素时,我经常需要获取某个名称的所有子元素。有一个方法
DomeElement::getElementsByTagName($name)
,但它返回所有具有该名称的子代,而不仅仅是直接子代。还有属性
DOMNode::$childNodes
,但是(1)它包含节点列表,而不是元素列表,即使我设法将列表项转换为元素(2),我仍然需要检查所有这些项的名称。是否真的没有优雅的解决方案来只获取某个特定名称的子对象,或者我在文档中遗漏了什么

一些例子:

<?php

DOMDocument();
$document->loadXML(<<<EndOfXML
<a>
  <b>1</b>
  <b>2</b>
  <c>
    <b>3</b>
    <b>4</b>
  </c>
</a>
EndOfXML
);

$bs = $document
    ->getElementsByTagName('a')
    ->item(0)
    ->getElementsByTagName('b');

foreach($bs as $b){
    echo $b->nodeValue . "\n";
}

// Returns:
//   1
//   2
//   3
//   4
// I'd like to obtain only:
//   1
//   2

?>

我能想象的一种优雅的方式是使用适合该工作的
过滤器。能够处理所述
DOMNodeList
并(可选)接受标记名作为迭代器花园中的示例性
DOMElementFilter
进行筛选的示例性标记名:

这将给出您想要的结果:

1
2
你现在可以找到了。允许任何标记名使用
*
,这可能是值得的,因为
getElementsByTagName(“*”
也可以。但这只是一些评论


Hier是一个在线工作使用示例:

我可以想象一种优雅的方式是使用适合该工作的
过滤器。能够处理所述
DOMNodeList
并(可选)接受标记名作为迭代器花园中的示例性
DOMElementFilter
进行筛选的示例性标记名:

这将给出您想要的结果:

1
2
你现在可以找到了。允许任何标记名使用
*
,这可能是值得的,因为
getElementsByTagName(“*”
也可以。但这只是一些评论


Hier是一个在线工作使用示例:

简单迭代过程

$parent = $p->parentNode;

foreach ( $parent->childNodes as $pp ) {

    if ( $pp->nodeName == 'p' ) {

        if ( strlen( $pp->nodeValue ) ) {
            echo "{$pp->nodeValue}\n";
        }

    }

}

简单迭代过程

$parent = $p->parentNode;

foreach ( $parent->childNodes as $pp ) {

    if ( $pp->nodeName == 'p' ) {

        if ( strlen( $pp->nodeValue ) ) {
            echo "{$pp->nodeValue}\n";
        }

    }

}

我在生产中使用的解决方案:

大海捞针(DOM)

用法:

$countryNode = getAttachableNodeByAttributeName($countriesNode, 'country', 'iso', 'NL');
使用国家/地区iso代码“NL”,通过指定属性
iso
从父国家/地区节点返回DOM元素,基本上与实际搜索类似。通过数组/对象中的名称查找某个国家

另一个使用示例:

$productNode = getAttachableNodeByAttributeName($products, 'partner-products');
返回仅包含单个(根)节点的DOM节点元素,不按任何属性进行搜索。
注意:为此,您必须确保根节点根据元素的标记名是唯一的,例如,
国家->国家[ISO]
-
国家
节点此处是唯一的,并且是所有子节点的父节点。

生产中使用的我的解决方案:

大海捞针(DOM)

用法:

$countryNode = getAttachableNodeByAttributeName($countriesNode, 'country', 'iso', 'NL');
使用国家/地区iso代码“NL”,通过指定属性
iso
从父国家/地区节点返回DOM元素,基本上与实际搜索类似。通过数组/对象中的名称查找某个国家

另一个使用示例:

$productNode = getAttachableNodeByAttributeName($products, 'partner-products');
返回仅包含单个(根)节点的DOM节点元素,不按任何属性进行搜索。
注意:为此,您必须确保根节点根据元素的标记名是唯一的,例如
国家->国家[ISO]
-
国家
节点是唯一的,并且是所有子节点的父节点。

oth,只需使用上下文节点运行
DOMXPath::query
。(或者添加整个文档,并查询
/a[1]/b
)在现实生活中,我解析相当大的文件,所以我使用
DOMReader
expand()
方法逐块解析它们。不幸的是,副作用是我没有
DOMDocument
,只有
DOMElement
的许多实例,我无法为它们优雅地构造
DOMXPAth
。。。为什么这一切都考虑得这么糟糕!?!我想避免将
DOMElment
s再次转换为
SimpleXML
,但我离这个决定越来越近了……哦,只需使用上下文节点运行
DOMXPath::query
。(或者添加整个文档,并查询
/a[1]/b
)在现实生活中,我解析相当大的文件,所以我使用
DOMReader
expand()
方法逐块解析它们。不幸的是,副作用是我没有
DOMDocument
,只有
DOMElement
的许多实例,我无法为它们优雅地构造
DOMXPAth
。。。为什么这一切都考虑得这么糟糕!?!我想避免将
DOMElment
s再次转换为
SimpleXML
,但我离这个决定越来越近了。。。