为什么DomDocument getElementsByTagName返回一半的NodeList? [英] Why DomDocument getElementsByTagName give back an half NodeList?

查看:98
本文介绍了为什么DomDocument getElementsByTagName返回一半的NodeList?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用DomDocument生成了一些非标准标记的HTML,结果是这样的:

I generate some non-standard-tag HTML with DomDocument and the result is this:

/* 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>
*/

我要做的是在有用的东西中翻译每个小部件...它们是带有参数的简单占位符。

What I want to do is to "translate" each widget in something useful... they are simple placeholders with params.

该类的函数提取为:

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;
    }

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

then when I saveHTML() the $doc I see:

/* 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>
*/

为什么未翻译 horizo​​ntal_menu?

why "horizontal_menu" wasn't translated?

小部件在哪里都没有关系(我尝试了一个div,其中包含所有小部件,每个小部件都有div)。

It doesn't matter where widgets are (I tried with only one div with all widgets in and with a div per widget).

我不知道...

推荐答案

发生这种情况是因为在循环时您正在替换DOMNodeList中的元素他们。 DOMNodeList不是数组,因此foreach 不会对副本进行操作,而是对对象本身进行操作。

It happens because you are replacing the elements in the DOMNodeList while looping on them. A DOMNodeList is not an array, so foreach does not operate on a copy, but on the object itself.

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

Basically, what I think is happening is:


  • 您替换了< widget>的第一个实例。
  • You replace the first instance of <widget> (Item 0).
  • The pointer advances to the next item (Item 1).
  • Item 0 has been replaced and does not exist anymore.
  • Item shifting occurs: Item 1 becomes Item 0, Item 2 becomes Item 1.
  • The pointer still points to Item 1 (which was originally Item 2, effectively skipping a node).

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

What you need to do is to save the elements in an array and then change them, instead of looping on the DOMNodeList:

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

foreach ($this->_widgetList as $widget) {
   // do stuff
}

这篇关于为什么DomDocument getElementsByTagName返回一半的NodeList?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆