【问题标题】:PHP: "Couldn't fetch DOMElement. Node no longer exists in" using DOMXpathPHP:“无法获取 DOMElement。节点不再存在于”使用 DOMXpath
【发布时间】:2020-03-20 18:28:55
【问题描述】:

我有一些包含以下内容的 HTML:

<div class="test">
  Outer
  <div class="test">Inner 1</div>
  <div class="test">Inner 2</div>
</div>

我正在对这些元素的内容做str_replace()

$dom = new DOMDocument();
$dom->loadHTML($html);
$xpath = new DOMXpath($dom);

foreach($xpath->query("//div[@class='test']") as $node) {
    $node->nodeValue = str_replace(" ", "X", $node->nodeValue);
}

这应该用“X”替换任何空格。

但是会导致这个错误:

警告:无法获取 DOMElement。节点不再存在于 /path/to/my/file.php63

如果只有一个嵌套的 div 就可以了:

<div class="test">
  Outer
  <div class="test">Inner 1</div>
</div>

为什么会发生这种情况,我怎样才能让它发挥作用?

【问题讨论】:

  • 您要替换哪些空格?作为调试,将echo $node-&gt;nodeValue.PHP_EOL; 添加到循环中以检查它正在处​​理的文本。
  • 我认为问题在于您只需要查询元素一次,然后遍历对象。目前,您正在一遍又一遍地执行相同的查询。 $elements = $xpath-&gt;query("//div[@class='test']" 然后foreach($elements as $node) {...}
  • @NigelRen 它首先输出“Outer Inner 1 Inner 2”然后“Inner 1”,然后发生错误。然后它输出 "" 并且错误再次发生。
  • @EternalHour 谢谢,但这没有任何区别。

标签: php domxpath


【解决方案1】:

尝试改变

foreach($xpath->query("//div[@class='test']") as $node) 

foreach($xpath->query('//div[@class="test"]//div[@class="test"]') as $node)

按 cmets 编辑:

假设外部元素中有一个空格(即它的“Outer 1:”):

<?php
$string = <<<XML
<div class="test">
  Outer 1
  <div class="test">Inner 1</div>
  <div class="test">Inner 2</div>
</div>
XML;
$dom = new DOMDocument();
$dom->loadHTML($string);
$xpath = new DOMXpath($dom);

foreach($xpath->query('//div[@class="test"]//text()') as $node) {
   $nnode = trim($node->nodeValue);

   echo $nnode  = str_replace(" ", "X", $nnode);
}

【讨论】:

  • 谢谢 - 它确实成功处理了两个 Inner n 元素,但它跳过了 Outer 元素(在现实世界中也可能有一个空格;我应该在我的例子中澄清这一点)。
  • @PhilGyford - 实际上它确实跳过了外部元素 - 根据原始问题,它是故意的。那么您是说外部元素中也可能有一个空格,并且您也想用 X 替换它吗?
  • 是的,对不起,当我说“我正在对这些元素的内容做str_replace()”时,我应该更明确地提供一个更好的例子——我的意思是 all i> 的元素,而不仅仅是内部的两个。
  • 太好了,谢谢@JackFleeting!一件奇怪的事情 - foreach 循环在每个内部元素之后都有一个额外的迭代。它们很容易被忽略,因为它们最终是空字符串,但你能解释一下原因吗?
  • @PhilGyford - 这是 xpath 的产物之一;如果你尝试count(//div[@class="test"]//text()),你会看到返回5,而不是3,正如人们直觉所期望的那样。每对关闭 &lt;/div&gt; 与其紧随其后的打开 &lt;div&gt; 之间的空格计为 1。其中有两对,因此额外的迭代......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-12
  • 2020-04-08
  • 2014-12-27
相关资源
最近更新 更多