Php 用于replacechild后下一个停止循环的XML Dom

Php 用于replacechild后下一个停止循环的XML Dom,php,xml,replace,Php,Xml,Replace,然后我尝试在第一个替换循环停止后使用此代码 $Autos->length=10 $Autos = $dom->getElementsByTagName('cars'); // Find Sections $NewElement = $dom->createElement('hello','hi'); for ($i = 0; $i < $Autos->length; $i++) { $Autos->item($i)->parentNode->

然后我尝试在第一个替换循环停止后使用此代码
$Autos->length=10

$Autos = $dom->getElementsByTagName('cars'); // Find Sections 
$NewElement = $dom->createElement('hello','hi');
for ($i = 0; $i < $Autos->length; $i++) 
{

    $Autos->item($i)->parentNode->replaceChild($NewElement, $Autos->item($i));
    echo $Autos->length . " i= " .$i;
}
$Autos=$dom->getElementsByTagName('cars');//查找部分
$NewElement=$dom->createElement('hello','hi');
对于($i=0;$i<$Autos->length;$i++)
{
$Autos->item($i)->parentNode->replaceChild($NewElement,$Autos->item($i));
echo$Autos->length.“i=”.$i;
}
所以$i总是=0
为什么会出现这种情况?

DOMNode::getElementsByTagName()返回一个“活动”列表。如果文档发生更改,则会发生更改。替换节点后,列表也会更改

这里有三种方法来解决这个问题

  • 将节点列表强制转换为数组:

    $Autos=iterator_to_数组($dom->getElementsByTagName('cars')

  • 将列表从最后一个节点循环到第一个节点:

    for($i=$Autos->length-1;$i>=0;$i--){

  • 使用XPath获取节点:

    $xpath=newdomxpath($dom);

    $Autos=$xpath->evaluate('//cars');

  • XPath表达式比用于获取节点的DOM方法灵活且功能强大得多,并且结果不是“实时的”。例如,您可以执行以下操作:

    $Autos = $xpath->evaluate('//cars[@manufacturer = "SomeCompanyName"]');
    
    源中还有一个问题。您只使用一个创建的节点替换节点。因此,它将替换第一个节点,然后相同的节点替换第二个节点,…直到替换列表中的最后一个节点

    您需要克隆已创建的节点:

    $Autos->item($i)->parentNode->replaceChild(
      $NewElement->cloneNode(TRUE), $Autos->item($i)
    );
    
    节点列表实现可遍历接口。可以使用foreach()

    作为旁注,构建一个新的目标XML文档并将节点复制到其中,然后操作现有文档通常更容易。XSLT是一种专门用于此任务的语言

    foreach ($xpath->evaluate('//cars') as $i => $car) {
      $car->parentNode->replaceChild($NewElement->cloneNode(TRUE), $car);
      echo " i= " .$i;
    }