6

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

我想做的是将每个小部件“翻译”成有用的东西......它们是带有参数的简单占位符。

从类中提取的函数是:

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

然后当我 saveHTML() 我看到的 $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>
*/

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

小部件在哪里并不重要(我只尝试了一个包含所有小部件的 div,每个小部件都有一个 div)。

我想不通...

4

2 回答 2

8

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

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

  • <widget>您替换(Item 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
}
于 2011-04-01T15:44:50.840 回答
0

为避免两次迭代,您可以反向解析元素列表

$widgets = $doc->getElementsByTagName( 'widget' ); // get all elements

for( $i = $widget->length; $i > 0; $i-- ){
    $widget = $doc->getElementsByTagName( 'widget' )->item( $i - 1 );

    // do stuff whith the widget
}
于 2013-07-09T16:01:25.723 回答