DOM 无法将节点附加到 DOMNodeList (PHP 7.3) 中的元素
Posted
技术标签:
【中文标题】DOM 无法将节点附加到 DOMNodeList (PHP 7.3) 中的元素【英文标题】:DOM cannot append nodes to element from DOMNodeList (PHP 7.3) 【发布时间】:2021-06-13 21:16:54 【问题描述】:我正在使用 php 7.3 编写一个函数,该函数循环遍历输入中收到的一组节点并将它们添加到文档中。
public function appendChildren($nodes)
foreach ($nodes as $node)
$this->appendChild($node);
它可以工作,但是当输入值不是数组而是 DOMNodeList 时,它只会循环第一个元素。
重现问题:
<?php
$doc = new DOMDocument();
$doc->formatOutput=true;
$root = $doc->createElementNS('urn:oasis:names:tc:SAML:2.0:metadata', 'md:root');
$nodes[] = $doc->createElementNS('urn:oasis:names:tc:SAML:2.0:metadata', 'KeyInfo');
$nodes[] = $doc->createElementNS('urn:oasis:names:tc:SAML:2.0:metadata', 'KeyFile');
$nodes[] = $doc->createElementNS('urn:oasis:names:tc:SAML:2.0:metadata', 'KeyStory');
$nodes[] = $doc->createElementNS('urn:oasis:names:tc:SAML:2.0:metadata', 'KeyRole');
foreach($nodes as $node)
$root->appendChild($node);
$nlist = $root->childNodes;
$newroot = $doc->createElementNS('urn:oasis:names:tc:SAML:2.0:metadata', 'md:newroot');
foreach($nlist as $node)
$newroot->appendChild($node);
echo 'size of root: '.$root->childNodes->count()."\n";
echo 'size of newroot: '.$newroot->childNodes->count()."\n";
$doc->appendChild($newroot);
echo $doc->saveXML();
预期输出:
size of root: 4
size of newroot: 4
<?xml version="1.0"?>
<md:newroot xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
<md:KeyInfo/>
<md:KeyFile/>
<md:KeyStory/>
<md:KeyRole/>
</md:root>
但是我得到了:
size of root: 3
size of newroot: 1
<?xml version="1.0"?>
<md:newroot xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
<md:KeyInfo/>
</md:newroot>
循环不完整,不知何故,第一个元素的引用从前一个列表中删除并添加到后者(因此大小为 3)。此外,如果我发表评论
$newroot->appendChild($node);
循环按预期遍历列表。 appendChild() 函数如何停止循环?为什么会在第一次迭代后发生?
有人能解释一下这种行为吗?
【问题讨论】:
@DanielProtopopov 这确实有效。所以这毕竟是一个迭代的问题!在第二个循环之后长度为 0 的前一个节点结果,我应该在插入之前克隆节点以避免这种副作用吗? (如果您可以将评论作为答案发布,我很乐意将其标记为已接受) 【参考方案1】:$nlist
在迭代时由于 appendChild 而发生变化。您正在移动内容。可以通过调试看到
for($i = 0; $i < $nlist->length; $i++)
$newroot->appendChild($nlist->item($i));
所以你需要这样重写
while($nlist->length)
$newroot->appendChild($nlist->item(0));
【讨论】:
以上是关于DOM 无法将节点附加到 DOMNodeList (PHP 7.3) 中的元素的主要内容,如果未能解决你的问题,请参考以下文章