为什么getElementsByTagName只抓取其他所有元素?

时间:2011-08-12 03:07:00

标签: php dom domdocument getelementsbytagname

使用此代码使用DomDocument:

<?php
$html = '<pre>one</pre><pre>two</pre><pre>three</pre><pre>four</pre>';

$doc = new DomDocument();
$doc->loadHTML($html);
$sub = $doc->getElementsByTagName("pre");
foreach($sub as $pre) {
    $fragment = $doc->createDocumentFragment(); 
    $fragment->appendXML(str_replace('&', '&amp;', '<p>& it\'s replaced</p>'));
    $pre->parentNode->replaceChild($fragment, $pre);
}

echo $doc->saveHTML();
?>

我得到了这个输出:

<p>& it's replaced</p> 
<pre>two</pre>
<p>& it's replaced</p>
<pre>four</pre>

Working (or not) example

有人可以向我解释发生了什么以及为什么所有pre标签都没有被替换?

2 个答案:

答案 0 :(得分:4)

您可以尝试这种方式:http://codepad.viper-7.com/ALYWEi

<?php
$html = '<pre>one</pre><pre>two</pre><pre>three</pre><pre>four</pre>';

$doc = new DomDocument();
$doc->loadHTML($html);
$sub = $doc->getElementsByTagName("pre");
$i = $sub->length - 1;
while ($i > -1) {
    $pre = $sub->item($i);
    $fragment = $doc->createDocumentFragment(); 
    $fragment->appendXML(str_replace('&', '&amp;', '<p>& it\'s replaced</p>'));


    $pre->parentNode->replaceChild($fragment, $pre);

    $i--;
} 

echo $doc->saveHTML();
?>

当我用Google搜索“DomDocument replacechild”而没有引号

时,我发现了这个问题

请在此处查看第一条评论:http://php.net/manual/en/domnode.replacechild.php,尤其是:

  

如果您尝试一次替换多个节点,则必须小心迭代DOMNodeList。如果旧节点具有与新节点不同的名称,则一旦替换它,它将从列表中删除。使用回归循环:

答案 1 :(得分:1)

这与方向有关:

for ($i = 0; $i < $sub->length; $i++) {
    $pre = $sub->item($i);
    $fragment = $doc->createDocumentFragment();
    $fragment->appendXML(str_replace('&', '&amp;', '<p>& it\'s replaced</p>'));
    $pre->parentNode->replaceChild($fragment, $pre);
}

不起作用,但

for ($i = $sub->length -1; $i >=0; $i--) {
    $pre = $sub->item($i);
    $fragment = $doc->createDocumentFragment();
    $fragment->appendXML(str_replace('&', '&amp;', '<p>& it\'s replaced</p>'));
    $pre->parentNode->replaceChild($fragment, $pre);
}

工作正常。我估计必须有类似内部计数器的东西。

HTH Andreas