正则表达式剥离字符串中的外部HTML标记

时间:2015-02-23 09:50:32

标签: php html regex html-parsing

我需要一个正则表达式来删除字符串中的外部/顶级HTML标记,但保留内部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);

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

4 个答案:

答案 0 :(得分:2)

请注意

使用正则表达式不是修改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)

当第一个标记包含“&gt;”时这个角色会破坏一切,例如

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)

答案 1 :(得分:1)

如何获取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;
}

无需借助regexp

答案 2 :(得分:0)

这个基本的正则表达式可能会这样做。但是,它不会考虑包含> s的属性的标记,因此会跳闸。

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

如果您希望属性可能包含标记括号,则会变得更复杂。

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

任何一方都应该这样做。

答案 3 :(得分:0)

我创建了一个删除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;
}
?>

示例文字: 带有代码&#39;;

的$ text =&#39; 示例文字

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

strip_tags_content($ text)的结果: 带

的文字

strip_tags_content($ text,&#39; &#39;)的结果: 样本

的文本

strip_tags_content的结果($ text,&#39;&#39;,TRUE); 带标签的文字

我希望有人有用:)