为什么DomDocument getElementsByTagName会返回一半NodeList?

MiP*_*mic 6 php xhtml domdocument getelementsbytagname

我使用DomDocument生成一些非标准标记HTML,结果如下:

/* Input HTML
  <div id="toobar_top">
    <widget id="flag_holder"></widget>
    <widget id="horizontal_menu"></widget>
  </div>
  <div id="header">
    <widget name="header"></widget>
  </div>
*/
Run Code Online (Sandbox Code Playgroud)

我想要做的是用一些有用的东西"翻译"每个小部件......它们是带有参数的简单占位符.

该类的函数提取是:

private function widgeter($doc) { //Give it an DomDocument HTML containing <widget> elements and will translate them into usable stuff
    $this->_widgetList = $doc->getElementsByTagName($this->_widgetTransformTo);
    foreach ($this->_widgetList as $widget) {
        $data = array();
        if ($widget->hasAttributes()) {
        foreach ($widget->attributes as $attribute) {
            $data[][$attribute->name] = $attribute->value;
            // @TODO: Implements Widget Transformation

        }
        }
        // Next 2 lines are just for debug
        $string = serialize($data);
        $newWidget = $doc->createElement('p', $string);
        $widget->parentNode->replaceChild($newWidget, $widget);
    }
    return $doc;
    }
Run Code Online (Sandbox Code Playgroud)

然后,当我保存HTML()$ doc时,我看到:

/* Output HTML
  <div id="toobar_top">
    <p>[{"id":"flag_holder"}]</p>
    <widget id="horizontal_menu"></widget>
  </div>
  <div id="header">
    <p>[{"id":"header"}]</p>
  </div>
*/
Run Code Online (Sandbox Code Playgroud)

为什么"horizo​​ntal_menu"没有被翻译?

小部件的位置并不重要(我尝试只使用一个包含所有小部件的div,每个小部件使用div).

我弄不清楚......

net*_*der 8

之所以发生这种情况,是因为您在循环它们的同时替换DOMNodeList中的元素.甲的DOMNodeList不是数组,所以的foreach 不会在副本上操作,但对象本身.

基本上,我认为正在发生的事情是:

  • 您替换<widget>(第0项)的第一个实例.
  • 指针前进到下一个项目(项目1).
  • 项目0已被替换,不再存在.
  • 发生项目转移:项目1变为项目0,项目2变为项目1.
  • 指针仍指向第1项(最初为第2项,有效地跳过节点).

您需要做的是将元素保存在数组中然后更改它们,而不是在DOMNodeList上循环:

$this->_widgetList = array();
foreach ($domNodeList as $node) {
   $this->_widgetList[] = $node;    
}

foreach ($this->_widgetList as $widget) {
   // do stuff
}
Run Code Online (Sandbox Code Playgroud)