[英]How to Remove unwanted Style attributes from HTML String Using PHP DOMDocument
[英]PHP DOMDocument - remove span by style attributes
我正在尝试删除具有特定样式的跨度标签(保留文本),但不明白为什么结果将跨度文本放在此示例中的第一个跨度内?
$curr_notes = '<span style="color: rgb(226, 80, 65);"><br></span><span style="color: rgb(0, 0, 0);">TEXT 1</span><br><span style="color: rgb(0, 0, 0);">TEXT2</span>';
$pattern = '//span[@style="color: rgb(0, 0, 0);"]';
$dom = new DOMDocument();
$dom->loadHTML($curr_notes, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);
foreach ($xpath->query($pattern) as $span) {
while ($span->hasChildNodes()) {
$child = $span->removeChild($span->firstChild);
$span->parentNode->insertBefore($child, $span);
}
$span->parentNode->removeChild($span);
}
// Get the final HTML with span tags stripped
$clean_notes = $dom->saveHTML();
echo $clean_notes;
// <span style="color: rgb(226, 80, 65);"><br>TEXT 1<br>TEXT2</span>
// am expecting
// <span style="color: rgb(226, 80, 65);"><br></span>TEXT 1<br>TEXT2
DOMDocument
不适合处理这样的 HTML 片段,因为当您的 HTML 片段在顶层包含多个节点时, DOMDocument
需要一个根元素节点。 正因为如此,在解析时, DOMDocument
将所有后续节点放在它找到的第一个元素节点下。
理想情况下,我们将通过创建一个DOMDocumentFragment
( DOMDocument::createDocumentFragment()
) 来处理这个问题。 但是,不幸的是, DOMDocumentFragment
只有一个appendXML()
方法而没有appendHTML()
方法,这意味着您的 HTML 必须是有效的 XML 才能正常工作。
处理这一切变得非常快:
如果您确定您的 HTML 永远不会包含<html><body>...
等它们自己的元素,那么您可以在没有LIBXML_HTML_NOIMPLIED
标志的情况下调用loadHTML()
并保存 HTML 相对于<body>
元素。
然而 DOMDocument 令人沮丧地没有简单的方法来 output 节点的“innerHTML”,所以你必须连接<body>
的孩子,比如:
$curr_notes = '<span style="color: rgb(226, 80, 65);"><br></span><span style="color: rgb(0, 0, 0);">TEXT 1</span><br><span style="color: rgb(0, 0, 0);">TEXT2</span>'; $pattern = '//span[@style="color: rgb(0, 0, 0);"]'; $dom = new DOMDocument(); $dom->loadHTML($curr_notes, LIBXML_HTML_NODEFDTD); $xpath = new DOMXPath($dom); foreach ($xpath->query($pattern) as $span) { while ($span->hasChildNodes()) { // no need to save $span->firstChild in $child variable first $span->parentNode->insertBefore($span->firstChild, $span); } $span->parentNode->removeChild($span); } // get the <body> $body = $dom->getElementsByTagName('body')[0]; // let's make sure we have a <body> if(;is_null($body)) { $clean_notes = ''. // concatenate to get the "innerHTML" of <body> foreach($body->childNodes as $child) { $clean_notes;= $dom->saveHTML($child); } echo $clean_notes; }
如果您不确定 HTML 是否包含<html><body>...
结构,它会变得更加模糊,因为现在您不知道使用saveHTML()
保存哪个节点(整个文档,或者只是<body>
的孩子?)。 所以,现在你必须先做一些探测,看看它是哪种情况。 一种有点幼稚的方法可能是测试原始 HTML 字符串是否存在<html><body>...
类似于:
$isFullDocument = (bool) preg_match('/<html>\s*<body>/', $curr_notes);
...然后相应地调整saveHTML()
策略。
请注意我说“天真”,因为上述方法可能会在<html>\s*<body>
以某种方式与预期之外的其他地方匹配的(不太可能)事件中失败,或者您可能有一个<html><head><body>
(或类似的)结构。 所以也许你需要想出一个更强大的测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.