如果你想递归遍历 DOM,这可能会有所帮助
<?php
/**
* PHP 的 DOM 类是递归的,但没有提供 RecursiveIterator 的实现。这个类为 DOMNodeList 提供了一个 RecursiveIterator。
(PHP 5、PHP 7、PHP 8)
列表中节点的数量。有效的子节点索引范围是 0 到 length - 1
(包含)。
版本 | 描述 |
---|---|
8.0.0 | DOMNodeList 现在实现了 IteratorAggregate。以前,实现的是 Traversable。 |
7.2.0 | 实现了 Countable 接口,并返回 length 属性的值。 |
如果你想递归遍历 DOM,这可能会有所帮助
<?php
/**
* PHP 的 DOM 类是递归的,但没有提供 RecursiveIterator 的实现。这个类为 DOMNodeList 提供了一个 RecursiveIterator。
请注意,$length 是计算的(php5.3.2)。
遍历大型 NodeList 可能很耗时。
更倾向于
$nb = $nodelist->length;
for($pos=0; $pos<$nb; $pos++)
而不是
for($pos=0; $pos<$nodelist->length; $pos++)
我很难弄清楚这一点…
在 PHP 5.2.5(Windows)中,无法使用 foreach 正确地迭代 DOMNode->childNodes 返回的 DOMNodeList 对象。相反,我必须使用 for 循环与 DOMNodeList 的 item() 方法一起使用,才能正确地迭代所有子节点。
我不知道这是否真的一个错误,但显然是。
如果你反向迭代,可以修改甚至删除 DOMNodeList 中的节点
$els = $document->getElementsByTagName('input');
for ($i = $els->length; --$i >= 0; ) {
$el = $els->item($i);
switch ($el->getAttribute('name')) {
case 'MAX_FILE_SIZE'
$el->parentNode->removeChild($el);
break;
case 'inputfile'
$el->setAttribute('type', 'text');
//break;
}
}
我做了一些测试,发现两个结果
(我的系统:Win XP 和 PHP 5.2.1)
1) 如果只对 foreach 进行只读操作或对某些属性进行少量写入,则使用 foreach 的迭代确实可以正常工作,正如 "james dot j dot hackett at gmail dot com" 所写。
2) 如果你在迭代时执行一些 DOM 操作,则 foreach 不会起作用。在我的情况下,它是在将迭代的 $node 添加到新节点的子节点中
$newNode = $dom->createElement('newNode') ;
foreach ($nodeList as $node) {
echo $node->nodeValue ;
$newNode->appendChild($node) ;
}
这只会给你第一个元素…
我把它解释为一个令人困惑但正确的行为,因为在将节点追加到其他地方时,$dom 对象内部发生了变化…
所以,如果你想做类似于 2) 的操作,请使用 for、length 和 item() :)
值得一提的是,DOMNodeList 不是数组,因此在使用 for、foreach 或 array_map、array_filter、array_walk 函数之前,必须先将其转换为数组。
使用 iterator_to_array 进行转换(自 PHP 5.1.0 起)。
<code>
/* @ suppress warning var_dump not yet implemented for class */
@array_walk( iterator_to_array( $Some_NodeList ), 'var_dump' ) );
foreach( iterator_to_array( $Some_NodeList ) as $node )
@var_dump( $node );
</code>
希望有用。
回复 "kassah at gmail"
你不需要将 DOMNodeList 转换为数组,就可以使用 'foreach' 迭代它。你可以直接对 DOMNodeList 使用 foreach。
$nodeList = $someDomDocument->getElementsbytagname('user');
foreach ($nodeList as $node) {
echo $node->nodeValue;
}
这实际上是不正确的。你可以将函数结果用作对象。这使得为你的数据库构建 API 变得非常干净整洁。例如
我们的代码
$articles = Node::screate('tags', 123456)->assets('like:title:test')->articles;
我们使用上述代码来获取与链接到特定标签的资源链接的文章。
对我的第一个注释的补充
传统的 for 循环不允许你在循环过程中更改 DOM 树 - 其效果与 foreach 几乎相同。所以你必须将节点收集到一个数组中,并在第二个循环中(这次循环数组...)进行树的修改操作。