【问题标题】:Regex to strip outer HTML tags in string正则表达式去除字符串中的外部 HTML 标记
【发布时间】:2026-01-31 12:20:07
【问题描述】:

我需要一个正则表达式来去除字符串中的外部/* HTML 标签,但保留内部标签。

$str = "<div>Start <br /> <span>test</span> end.</div>";

进入

$str = "Start <br /> <span>test</span> end.";

还有

$str = "<aside id="main" class="one">Start <br /> <span>test</span> end.</aside>";

进入

$str = "Start <br /> <span>test</span> end.";

.

preg_replace('/<[^>]*>/', '', $str);

删除所有标签,而不仅仅是外部标签。

【问题讨论】:

  • 使用DOM 比使用老套的正则表达式更好
  • DOM 无法选择标签的内容而不剥离内容中存在的标签。但是,它可以选择带有 &lt;div&gt;bla &lt;br&gt; bla&lt;/div&gt; 等内容的整个标签,现在我只需要剥离实际的外部标签(在本例中为 div)并保留带有标签的内容。
  • $html = $domElement-&gt;ownerDocument-&gt;saveHTML($domElement); 应该在 $html 中返回 Dom 节点的内容,而不剥离其中的标签
  • 问题不在于 DOM 是否比正则表达式更好,而是如何使用正则表达式... 使用正则表达式而不是 DOM 是有正当理由的,正则表达式的一个主要优点是性能更快比 DOM(见这里blog.futtta.be/2014/05/01/…
  • 1000 次观看,只有一票否决。太棒了,这个地方曾经是积极的。发生了什么?没有答案,只是有些人自视甚高

标签: php html regex html-parsing


【解决方案1】:

请注意

使用正则表达式并不是修改 HTML 代码的最佳方式! 在大多数情况下,使用 DOMDocument 或 DOMDocumentFragement 对象从 HTML 代码中修改或提取数据会更好、更可靠。

但是,在某些情况下,正则表达式更好,主要是在以下因素适用时:

  • 您知道您编辑的 HTML 代码将是有效的。
  • 修改后的 HTML 结构在所有情况下都是相同的。
  • 您只对代码进行了非常简单的更改。
  • 性能很重要(例如在循环内执行时)。 DOMDocument 比简单的正则表达式慢得多!

代码

要从一些 HTML 代码中去除最外层的标签,请使用这个正则表达式:

/* Note: 
 * The code must start with an opening tag and end with a closing tag. 
 * No white space or other text must be present before the first 
 * tag/after the last tag, else you get some unexpected results.
 */

$contents = preg_replace( '/^<[^>]+>|<\/[^>]+>$/', '', $markup );
            // ^<[^>]+>     This removes the first tag
            // <\/[^>]+>$   This removes the last closing tag

示例

此正则表达式适用于大多数 HTML 标记,例如

In: '<div class="my-text" id="text" style="color:red">some text</div>'
Out: 'some text' (expected result)

当第一个标签包含 ">" 字符时,它将破坏所有内容,例如

In: '<div title="Home > Archives">Archive overview</div>'
Out: ' Archives">Archive overview' (unexpected result)

开头或结尾的空格/文本也会破坏正则表达式

In: '<div>Your name</div>:'
Out: 'Your name</div>:' (unexpected result)

当然,任何标签都会被剥离,没有任何完整性检查,例如

In: '<h2>Settings</h2><label>Page Title</label>'
Out: 'Settings</h2><label>Page Title' (unexpected result)

【讨论】:

    【解决方案2】:

    如何获取一个DOM元素,并模拟innerHTML()

    $html = '<html><body><div><ul><li>1</li><li>2</li><li>3</li></ul></div></body></html>';
    
    function DOMinnerHTML(DOMNode $element) { 
        $innerHTML = "";
        foreach ($element->childNodes as $child) { 
            $innerHTML .= $element->ownerDocument->saveHTML($child);
        }
    
        return $innerHTML; 
    } 
    
    $doc = new DOMDocument();
    $doc->loadHTML($html);
    
    foreach ($doc->getElementsByTagName('ul') as $child) {
        $html = DOMinnerHTML($child); 
        echo $html, PHP_EOL;
    }
    

    无需借助正则表达式

    【讨论】:

    • 在不知道父标记名的情况下有什么方法可以做到这一点?
    【解决方案3】:

    这个基本的正则表达式可能会做。但是,它不考虑具有包含&gt;s 的属性的标签,因此会跳闸。

    Find: <[^>]*>([\s\S]*)<\/[^>]*>
    Replace: $1
    

    如果您期望属性可能包含标签括号,它会变得更加复杂。

    Find: <(?:[^>]*?(?:(?:"[^"]*?"|'[^']*?')+[^>]*?)|[\s\S]*?)>([\s\S]*)<\/[^>]*>
    Replace: $1
    

    任何一个都应该做到这一点。

    【讨论】:

    • 第一个正则表达式出现错误Warning: preg_replace(): Unknown modifier ']'
    • @RomanToasov 尝试转义正斜杠。 &lt;[^&gt;]*&gt;([\s\S]*)&lt;\/[^&gt;]*&gt;
    【解决方案4】:

    我做了一个函数来删除 HTML 标签及其内容:

    功能:

    <?php
    function strip_tags_content($text, $tags = '', $invert = FALSE) {
    
      preg_match_all('/<(.+?)[\s]*\/?[\s]*>/si', trim($tags), $tags);
      $tags = array_unique($tags[1]);
    
      if(is_array($tags) AND count($tags) > 0) {
        if($invert == FALSE) {
          return preg_replace('@<(?!(?:'. implode('|', $tags) .')\b)(\w+)\b.*?>.*?</\1>@si', '', $text);
        }
        else {
          return preg_replace('@<('. implode('|', $tags) .')\b.*?>.*?</\1>@si', '', $text);
        }
      }
      elseif($invert == FALSE) {
        return preg_replace('@<(\w+)\b.*?>.*?</\1>@si', '', $text);
      }
      return $text;
    }
    ?>
    

    示例文本: $text = '示例 带有标签的文本';

    strip_tags($text) 的结果: 带有标签的示例文本

    strip_tags_content($text) 的结果: 文字与

    strip_tags_content($text, '') 的结果: 示例文本与

    strip_tags_content($text, '', TRUE); 的结果 带标签的文本

    希望有人有用:)

    【讨论】:

      最近更新 更多