如何使用标签的 id 剥离标签及其所有内部 html?

Posted

技术标签:

【中文标题】如何使用标签的 id 剥离标签及其所有内部 html?【英文标题】:How to strip a tag and all of its inner html using the tag's id? 【发布时间】:2011-03-19 12:31:51 【问题描述】:

我有以下html

<html>
 <body>
 bla bla bla bla
  <div id="myDiv"> 
         more text
      <div id="anotherDiv">
           And even more text
      </div>
  </div>

  bla bla bla
 </body>
</html>

我想删除从 &lt;div id="anotherDiv"&gt; 开始直到关闭 &lt;div&gt; 的所有内容。我该怎么做?

【问题讨论】:

此页面上似乎存在编辑战。请澄清这个不清楚的问题,以便研究人员受益。 删除单个特定元素与删除具有特定标记名的所有标记之间存在很大差异。 对于这个问题的任何解释,这个问题的每个正则表达式解决方案都是不正确的,并且在许多不同的输入上都会以令人惊讶的方式失败。正如接受的答案所使用的那样,您需要一个 DOM 解析器。无论您认为问题是要删除&lt;div&gt;,还是要通过其 ID 删除元素,都无法使用正则表达式正确完成。 考虑使用正则表达式从&lt;div data-attr="&lt;/div&gt;"&gt;&lt;/div&gt; 中剥离&lt;div&gt;(通过标签或ID)。或&lt;div&gt;&lt;script&gt;foo("&lt;/div&gt;")&lt;/script&gt;&lt;/div&gt;,或任何其他会破坏基于正则表达式的解决方案的简单案例。 【参考方案1】:

与native DOM

$dom = new DOMDocument;
$dom->loadHTML($htmlString);
$xPath = new DOMXPath($dom);
$nodes = $xPath->query('//*[@id="anotherDiv"]');
if($nodes->item(0)) 
    $nodes->item(0)->parentNode->removeChild($nodes->item(0));

echo $dom->saveHTML();

【讨论】:

如果我想删除 dom 中的所有 div 标签,我必须修改什么? @Sisir 见***.com/questions/4177376/… 是的,这是一种享受。我一直希望能够从 html 字符串中删除 html 标记,就像 jquery $(selector#id).remove() 一样。这真是太棒了! @SubstanceD 如果您想要选择器,请查看phpQuery, Zend_Dom or QueryPath。就个人而言,我更喜欢XPath。【参考方案2】:

您可以使用preg_replace() 喜欢:

$string = preg_replace('/<div id="someid"[^>]+\>/i', "", $string);

【讨论】:

这将删除所有divs,而不仅仅是指定的。 您没有指定必须删除 ID=myDiv 的 div 的任何地方? @HaimEvgi 有什么办法可以去掉里面的内容吗?例如使用 p 标签,它将被删除,但 p 标签的内容仍然存在。 这个答案肯定不符合 OP 的要求。 16 UVs 意味着许多研究人员被误导并且不理解问题和/或这个答案的作用。这个答案弊大于利。最重要的信息应该是开发人员应该使用 dom 解析器来操作有效的 html。 问题说:我想删除从 到结束 的所有内容。我该怎么做? 这个答案不正确。 【参考方案3】:

使用原生XML Manipulation Library

假设你的html内容存储在变量$html中:

$html='<html>
 <body>
 bla bla bla bla
  <div id="myDiv"> 
         more text
      <div id="anotherDiv">
           And even more text
      </div>
  </div>

  bla bla bla
 </body>
</html>';

要按 ID 删除标签,请使用以下代码:

    $dom=new DOMDocument;

    $dom->validateOnParse = false;

    $dom->loadHTML( $html );

    // get the tag

    $div = $dom->getElementById('anotherDiv');

   // delete the tag

    if( $div && $div->nodeType==XML_ELEMENT_NODE )

        $div->parentNode->removeChild( $div );
    

    echo $dom->saveHTML();

请注意,某些版本的libxml 需要存在doctype 才能使用getElementById 方法。

在这种情况下,您可以在 $html 前面加上 &lt;!doctype&gt;

$html = '<!doctype>' . $html;

或者,正如 Gordon 的回答所建议的,您可以使用 DOMXPath 使用 xpath 查找元素:

$dom=new DOMDocument;

$dom->validateOnParse = false;

$dom->loadHTML( $html );

$xp=new DOMXPath( $dom );

$col = $xp->query( '//div[ @id="anotherDiv" ]' );

if( !empty( $col ) )

    foreach( $col as $node )

        $node->parentNode->removeChild( $node );

    



echo $dom->saveHTML();

无论标签如何,第一种方法都有效。如果您想使用具有相同 id 但标签不同的第二种方法,比如说form,只需将//div[ @id="anotherDiv" ] 中的//div 替换为'//form'

【讨论】:

【参考方案4】:

strip_tags() 函数就是你要找的。​​p>

http://us.php.net/manual/en/function.strip-tags.php

【讨论】:

trip_tags() 没有按照他想要的方式工作。 strip_tags() 允许某些排除,但是当您只想排除一个标签并包含所有其他标签时,为什么要使用它 从他的问题来看,我无法确定他试图删除哪些标签。似乎他想要删除一切。感谢您的意见。 啊,使用 chrome。他的内联标记没有出现。我刚刚在 Firefox 中检查了它,我看到了他的内联标记。你是对的 :) 为什么它没有出现在 chrome 中? strip_tags() 最适合我。谢谢。它最适合我的原因是因为我的标签没有空格。这是迄今为止最简单的。谢谢。 问题说:我想删除从 到结束 的所有内容。我该怎么做? 这个答案不正确。 【参考方案5】:

我写这些是为了去除特定的标签和属性。由于它们是正则表达式,因此不能 100% 保证在所有情况下都能正常工作,但对我来说这是一个公平的权衡:

// Strips only the given tags in the given HTML string.
function strip_tags_blacklist($html, $tags) 
    foreach ($tags as $tag) 
        $regex = '#<\s*' . $tag . '[^>]*>.*?<\s*/\s*'. $tag . '>#msi';
        $html = preg_replace($regex, '', $html);
    
    return $html;


// Strips the given attributes found in the given HTML string.
function strip_attributes($html, $atts) 
    foreach ($atts as $att) 
        $regex = '#\b' . $att . '\b(\s*=\s*[\'"][^\'"]*[\'"])?(?=[^<]*>)#msi';
        $html = preg_replace($regex, '', $html);
    
    return $html;

【讨论】:

正则表达式是 DOM 无知的并且容易失败。使用合法的 DOM 解析技术将更加健壮、可靠和可扩展。重复的preg_ 调用将是低效的。 m 模式修饰符没有用。 此答案不使用问题中所述的id 定位标签。这个答案是不正确的,因为它删除了不应删除的元素。【参考方案6】:

这个怎么样?

// Strips only the given tags in the given HTML string.
function strip_tags_blacklist($html, $tags) 
    $html = preg_replace('/<'. $tags .'\b[^>]*>(.*?)<\/'. $tags .'>/is', "", $html);
    return $html;

【讨论】:

Regex 是 DOM 无知的,并且容易失败。使用合法的 DOM 解析技术将更加健壮、可靠和可扩展。没有理由声明$html(一次性变量);只是return preg_replace(...); 当标签属性值包含&gt; 时,此sn-p 将失败。无需使用捕获组。 此答案不针对使用id 的标签,如问题中所述。这个答案是不正确的,因为它删除了不应删除的元素。 这是不正确的并且对于多种输入都失败,例如strip_tags_blacklist('&lt;script&gt;let x = "&lt;div&gt;"&gt;&lt;/script&gt;&lt;div&gt;foo&lt;/div&gt;', 'div') => &lt;script&gt;let x = "。您不能使用正则表达式来剥离 HTML 或以其他方式与 HTML 交互。【参考方案7】:

按照 RafaSashi 使用 preg_replace() 的回答,这里有一个适用于单个标签或标签数组的版本:

/**
 * @param $str string
 * @param $tags string | array
 * @return string
 */

function strip_specific_tags ($str, $tags) 
  if (!is_array($tags))  $tags = array($tags); 

  foreach ($tags as $tag) 
    $_str = preg_replace('/<\/' . $tag . '>/i', '', $str);
    if ($_str != $str) 
      $str = preg_replace('/<' . $tag . '[^>]*>/i', '', $_str);
    
  
  return $str;

【讨论】:

问题说:我想删除从 到结束 的所有内容。我该怎么做? 这个答案不正确。 此答案不使用问题中所述的id 定位标签。这个答案是不正确的,因为它删除了不应删除的元素。

以上是关于如何使用标签的 id 剥离标签及其所有内部 html?的主要内容,如果未能解决你的问题,请参考以下文章

Python元素树 - 从元素中提取文本,剥离标签

PHP DOM获取nodevalue html? (不剥离标签)

去除 HTML 标签及其内容

php 剥离一些(或所有)产品标签

如何防止 Wordpress 在摘录中剥离 HTML 标签

在Java中剥离HTML标签[重复]