如何删除 DOM 元素标签但保留其内容?

Mar*_* AJ 4 html php xpath dom

我有 PHP 代码,它删除了至少具有一个属性的所有节点。是我的代码:

<?php

$data = <<<DATA
<div>
    <p>These line shall stay</p>
    <p class="myclass">Remove this one</p>
    <p>But keep this</p>
    <div style="color: red">and this</div>
</div>
DATA;

$dom = new DOMDOcument();
$dom->loadHTML($data, LIBXML_HTML_NOIMPLIED);
$dom->removeChild($dom->doctype);

$xpath = new DOMXPath($dom);

$lines_to_be_removed = $xpath->query("//*[count(@*)>0]");

foreach ($lines_to_be_removed as $line) {
    $line->parentNode->removeChild($line);
}

// just to check
echo $dom->saveHTML();
?>
Run Code Online (Sandbox Code Playgroud)

正如你在小提琴中看到的,这是上面代码的当前输出:

<div>
    <p>These line shall stay</p>

    <p>But keep this</p>

</div>
Run Code Online (Sandbox Code Playgroud)

虽然这是理想的结果:

<div>
    <p>These line shall stay</p>
    Remove this one
    <p>But keep this</p>
    and this
</div>
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

use*_*918 6

在删除元素之前,您要拔出它们的子节点并将它们添加到其后面。

例子:

$data = <<<DATA
<div>
    <p>These line shall stay</p>
    <p class="myclass">Remove this one</p>
    <p>But keep this</p>
    <div style="color: red">and this</div>
    <div style="color: red">and <p>also</p> this</div>
    <div style="color: red">and this <div style="color: red">too</div></div>
</div>
DATA;

$dom = new DOMDocument();
$dom->loadHTML($data, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);

foreach ($xpath->query("//*[@*]") as $node) {
    $parent = $node->parentNode;
    while ($node->hasChildNodes()) {
        $parent->insertBefore($node->lastChild, $node->nextSibling);
    }
    $parent->removeChild($node);
}

echo $dom->saveHTML();
Run Code Online (Sandbox Code Playgroud)

输出:

<div>
    <p>These line shall stay</p>
    Remove this one
    <p>But keep this</p>
    and this
    and <p>also</p> this
    and this too
</div>
Run Code Online (Sandbox Code Playgroud)

https://3v4l.org/9qHRM

(我添加了一些嵌套元素来演示这种方法的安全性。)


几个旁白:

  • $dom->removeChild($dom->doctype)如果您加载了附加LIBXML_HTML_NODEFDTD标志,则不需要。
  • 您的 xpath 表达式可以简化为 //*[@*]