DOMDocument getElementsByTagNameNS

时间:2014-09-06 20:44:31

标签: php xml namespaces domdocument

我遇到DOMDocument :: getElementsByTagNameNS的问题 当我尝试替换节点或我尝试修改元素一个是和一个没有被修改这是我的例子:     

$xml = <<<EOD
<html xmlns:x="helloworld">
    <head>
        <title>ClasseAS - Home</title>
        <meta name="title" content="Hello World"/>
        <meta name="keywords" content="hello"/>
        <x:hello/>
        <x:hello/>
        <x:hello/>
        <x:hello/>
    </head>
</html>
EOD;

$DOMDocument = new DOMDocument("1.0","utf-8");

    $DOMDocument->loadXML($xml);
    foreach ($DOMDocument->getElementsByTagNameNS("helloworld","*") as $element){
        if($element->localName == "hello"){
            $else = $element;
            $fragment = $DOMDocument->createDocumentFragment();
            $fragment->appendXML("<div id=\"hello\"></div>");
            $else->parentNode->replaceChild($fragment,$else);
        }
    }

    $HTML = $DOMDocument->saveXML();
    echo "<pre>".htmlentities($HTML)."</pre>";
?>

我的错误在哪里? 抱歉我的英文不好

2 个答案:

答案 0 :(得分:0)

DOMNodeList&#39;(由$DOMDocument->getElementsByTagNameNS("helloworld","*")返回)是实时的,当您替换节点时,您修改了NodeList。

一些伪代码来澄清行为:

foreach(liveNodeList as $index => $element){
 //1st loop
          [node0, node1, node2, node3]
   //$index 0_^
   //$element is node0

 //2nd loop
          [node1, node2, node3]
   //$index 1_______^
   //$element is node2

 //3rd loop
          [node1, node3]
   //$index 2____________^
    //end of loop
}
  1. 在第一个循环$index上是0,NodeList包含4个元素。原始NodeList的第一项将被替换(并且也从NodeList中删除)
  2. 第二个循环$index上的
  3. 是1,但NodeList现在只包含3个元素(第一个已被替换/删除)。 $element现在是NodeList中$index 1的节点,但循环必须再次使用$index 0替换节点以获得所需的结果。原始Nodelist的第3项将被替换
  4. 第三个循环$index上的
  5. 2,NodeList现在包含2个元素,NodeList末尾后面的$index个点
  6. 可能的解决方案:

    在NodeList结尾处启动Node-replacement:

    for($i=$DOMDocument->getElementsByTagNameNS("helloworld","*")->length-1;
        $i>=0;--$i){
        $element=$DOMDocument->getElementsByTagNameNS("helloworld","*")->item($i);
        if($element->localName == "hello"){
            $fragment = $DOMDocument->createDocumentFragment();
            $fragment->appendXML("<div id=\"hello\"></div>");
            $element->parentNode->replaceChild($fragment,$element);
        }
    }
    

答案 1 :(得分:0)

如果使用XPath选择元素,则可以在foreach循环中更可靠地操作它们:

$xpath = new DOMXPath($DOMDocument);
$xpath->registerNamespace('h', 'helloworld');

foreach ($xpath->query('//h:hello') as $element) {