为什么DomDocument getElementsByTagName 返回一半的NodeList?
我使用 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>
*/
为什么“horizontal_menu”没有翻译?
小部件在哪里并不重要(我尝试只使用一个 div,所有小部件都在其中,并且每个小部件都有一个 div)。
我想不通...
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.
The function extract from the class is:
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;
}
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>
*/
why "horizontal_menu" wasn't translated?
It doesn't matter where widgets are (I tried with only one div with all widgets in and with a div per widget).
I can't figure out it...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
发生这种情况是因为您在循环遍历 DOMNodeList 中的元素时替换了这些元素。 DOMNodeList 不是数组,因此 foreach 不会对副本进行操作,而是对对象本身进行操作。
基本上,我认为正在发生的事情是:
(Item 0) 的第一个实例。您需要做的是将元素保存在数组中,然后更改它们,而不是在 DOMNodeList 上循环:
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>
(Item 0).What you need to do is to save the elements in an array and then change them, instead of looping on the DOMNodeList:
为了避免两次迭代,您可以逆向解析元素列表
to avoid two iterations you can parse the list of elements inverse