【问题标题】:PHP Dom Remove element leave contentsPHP Dom 移除元素离开内容
【发布时间】:2011-06-08 05:00:54
【问题描述】:

我正在尝试根据 ID 标签删除某些链接,但保留链接的内容。比如我想转

Some text goes <a href="http://www.domain.tdl/" id="remove">here</a>

Some text goes here

我已经尝试使用下面的。

$dom = new DOMDocument;
$dom->loadHtml(mb_convert_encoding($html, 'HTML-ENTITIES', "UTF-8"));
$xp = new DOMXPath($dom);

foreach($xp->query('//a[contains(@id="remove")]') as $oldNode) {
$revised = strip_tags($oldNode);
}

$revised = mb_substr($dom->saveXML($xp->query('//body')->item(0)), 6, -7, "UTF-8");
echo $revised;

大致取自 here,但它只是吐出与 $html 相同的内容。

关于我将如何实现这一目标的任何想法?

【问题讨论】:

  • 您没有在此处修改您的文档,这就是它吐出相同内容的原因。您在 DOM 对象上提供调用 replaceChild 的示例,您只是创建变量,稍后用 saveXML 的输出覆盖该变量
  • 好问题,+1。请参阅我对精确选择所需节点的单个 XPath 表达式解决方案的回答。 :)

标签: php html dom xpath


【解决方案1】:

这就是我的功能:

function DOMRemove(DOMNode $from) {
    $sibling = $from->firstChild;
    do {
        $next = $sibling->nextSibling;
        $from->parentNode->insertBefore($sibling, $from);
    } while ($sibling = $next);
    $from->parentNode->removeChild($from);    
}

所以这个:

$dom->loadHTML('Hello <a href="foo"><span>World</span></a>');
$a = $dom->getElementsByTagName('a')->item(0); // get first
DOMRemove($a);

应该给你:

Hello <span>World</span>

要获取具有特定 ID 的节点,请使用 XPath:

$xpath = new DOMXpath($dom);
$node = $xpath->query('//a[@id="something"]')->item(0); // get first
DOMRemove($node);

【讨论】:

  • 我在您所做的另一篇文章中查看了此代码,但是 a)我收到错误 Fatal error: Call to a member function insertBefore() on a non-object 和 b)我将如何调整它以仅删除具有特定 ID 的 a 元素?
  • @Jack:对不起,函数参数应该是 $from 而不是 $node。固定的。感谢您指出了这一点。还添加了一个获取具有特定id 的节点的示例。
  • 两个问题;我将如何输出修改后的数据?当我使用您为特定 ID 提供的示例时,我得到与之前相同的错误。
  • @Jack:使用DOMDocument::saveHTML 进行输出。对于错误,您是否更新了代码?这对我来说没问题。
  • 你是对的。新代码是措辞。我在请求一些不存在的东西。经过一些调整后,它完成了所需的工作。非常感谢!
【解决方案2】:

使用

 //a[@id='remove']/node() 
| 
 //*[a[@id='remove']]/node()[not(self::a[@id=''remove])]

这将选择任何a 的所有子代,其属性为id,其值为"remove",以及此a 的所有前后兄弟姐妹,它们本身不是另一个a,其属性为id,值为@ 987654328@

【讨论】:

    【解决方案3】:

    类似于@netcoder 的答案的方法,但使用不同的循环结构和 DOMElement 方法。

    $html = '<html><body>This <a href="http://www.domain.tdl/" id="remove">link</a> was removed.</body></html>';
    $dom = new DOMDocument();
    $dom->loadHTML($html);
    $xpath = new DOMXPath($dom);
    foreach ($xpath->query('//a[@id="remove"]') as $link) {
      // Move all link tag content to its parent node just before it.
      while($link->hasChildNodes()) {
        $child = $link->removeChild($link->firstChild);
        $link->parentNode->insertBefore($child, $link);
      }
      // Remove the link tag.
      $link->parentNode->removeChild($link);
    }
    $html = $dom->saveXML();
    

    【讨论】:

    • $child = $link-&gt;removeChild($link-&gt;firstChild);可以简单写成$child = $link-&gt;firstChild;吗?
    猜你喜欢
    • 2012-02-08
    • 2011-10-25
    • 2017-03-06
    • 2014-05-04
    • 1970-01-01
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多