正则表达式删除所有空的 HTML 标记
Posted
技术标签:
【中文标题】正则表达式删除所有空的 HTML 标记【英文标题】:Regex to remove all empty HTML tags 【发布时间】:2014-01-29 20:18:11 【问题描述】:这是我的 php 函数,用于从字符串输入中删除所有空 html 标记:
/**
* Remove the nested HTML empty tags from the string.
*
* @param $string String to remove tags
* @param null $replaceTo Replace empty string with
* @return mixed Cleaned string
*/
function crl_remove_empty_tags($string, $replaceTo = null)
// Return if string not given or empty
if (!is_string($string) || trim($string) == '') return $string;
// Recursive empty HTML tags
return preg_replace(
'/<(\w+)\b(?:\s+[\w\-.:]+(?:\s*=\s*(?:"[^"]*"|"[^"]*"|[\w\-.:]+))?)*\s*/?>\s*</\1\s*>/gixsm',
!is_string($replaceTo) ? '' : $replaceTo,
$string
);
我的正则表达式:/<(\w+)\b(?:\s+[\w\-.:]+(?:\s*=\s*(?:"[^"]*"|"[^"]*"|[\w\-.:]+))?)*\s*/?>\s*</\1\s*>/gixsm
我用http://gskinner.com/RegExr/ 和http://regexpal.com/ 对其进行了测试,效果很好。 但是当我尝试运行它时。服务器总是返回错误:
Warning: preg_replace(): Unknown modifier '\'
我不知道究竟是什么'\'出了问题。有人请帮帮我!
【问题讨论】:
How to remove only html tags in a string?的可能重复 很抱歉,我想删除不包含任何内容的 HTML 标签。这不是strip_tags
所做的。
【参考方案1】:
在 php 正则表达式中,如果分隔符出现在表达式中,则需要转义它们。
在您的情况下,您有两个未转义的/
;只需将它们替换为\/
。你也不需要修饰符数组——php默认是全局的,你没有定义文字字符。
之前:
/<(\w+)\b(?:\s+[\w\-.:]+(?:\s*=\s*(?:"[^"]*"|"[^"]*"|[\w\-.:]+))?)*\s*/?>\s*</\1\s*>/gixsm
之后:
/<(\w+)\b(?:\s+[\w\-.:]+(?:\s*=\s*(?:"[^"]*"|"[^"]*"|[\w\-.:]+))?)*\s*\/?>\s*<\/\1\s*>/
// ^ ^
【讨论】:
另外,删除g
修饰符。 PCRE 默认是全局的。
您可以删除所有修饰符。
@CasimiretHippolyte 确实,因为没有定义文字字母。
谢谢大家!这是我的坏事。我是 RegEx 的新手,很难接近。
@MạnhHaiLúa 很高兴看到一些努力已经解决了这个问题;)【参考方案2】:
此模式能够删除“空标签”(即不包含任何内容、空格、html cmets 或其他“空标签”的非自闭合标签),即使这些标签像 <span><span></span></span>
一样嵌套。不考虑html cmets中的标签:
$pattern = <<<'EOD'
~
<
(?:
!--[^-]*(?:-(?!->)[^-]*)*-->[^<]*(*SKIP)(*F) # skip comments
|
( # group 1
(\w++) # tag name in group 2
[^"'>]* #'"# all that is not a quote or a closing angle bracket
(?: # quoted attributes
"[^\\"]*(?:\\.[^\\"]*)*+" [^"'>]* #'"# double quote
|
'[^\\']*(?:\\.[^\\']*)*+' [^"'>]* #'"# single quote
)*+
>
\s*
(?:
<!--[^-]*(?:-(?!->)[^-]*)*+--> \s* # html comments
|
<(?1) \s* # recursion with the group 1
)*+
</\2> # closing tag
) # end of the group 1
)
~sxi
EOD;
$html = preg_replace($pattern, '', $html);
限制:
此方法将删除指向外部 javascript 文件的链接:<script src="myscript.js"></script>
如果发现类似:var myvar="<span></span>";
或类似:var myvar1="<span><!--";
function doSomething() alert("!!!");
var myvar2="--></span>";
的内容,该模式可能会删除部分嵌入的 Javascript 代码。
这些限制是由于基本的文本方法无法区分 html 和 javascript 代码。但是,如果在模式跳过列表中添加“脚本”标签(与 html cmets 相同),则可以解决此问题,但在这种情况下,您需要基本描述 Javascript 内容(字符串、cmets、文字模式,所有这不是前三个)这不是一项微不足道的任务,而是可能的。
【讨论】:
绝对比我的好!非常棒且乐于助人!谢谢! 有什么方法可以让它在 PHP 5.3 (PCRE 8.12 2011-01-15) 上运行?它似乎不匹配任何东西,而在正则表达式测试站点(phpliveregex 或 regex101)上一切正常 @MarkL:没有理由该模式不适用于 php 5.3 及其相应的 PCRE 版本,您可能遗漏了一些东西,我建议在您的代码开头添加ini_set('display_errors', 'On');
走着瞧吧。不管怎样,我都会尽快改进这个答案。
无法让它工作。 3 台不同的服务器,各种版本的 PHP/PCRE。启用错误显示。产生一个空值的数组。 phpliveregex.com 虽然有效。在这里拉头发。示例代码:pastie.org/10310797 如果我逐字使用您的代码(带有 EOD 等),它可以工作。什么给了?
@MarkL:您的问题与如何根据引号计算字符串中的文字反斜杠有关。请参阅eval.in/405609 和有关字符串和八进制数的 php 手册。【参考方案3】:
删除空元素...以及下一个空元素。
体育
<p>Hello!
<div class="foo"><p id="nobody">
</p>
</div>
</p>
结果:
<p>Hello!</p>
php代码:
/* $html store the html content */
do
$tmp = $html;
$html = preg_replace( '#<([^ >]+)[^>]*>([[:space:]]| )*</\1>#', '', $html );
while ( $html !== $tmp );
【讨论】:
确实不错!对于终极杀手空间进化,也可以试试这个:'#<([^ >]+)[^>]*>([[:space:]]|&nbsp;)*</\1>#'
【参考方案4】:
不太确定这是否是您需要的,但我今天找到了。你需要 PHP 5.4+!
$oDOMHTML = DOMDocument::loadHTML(
$sYourHTMLString,
LIBXML_HTML_NOIMPLIED |
LIBXML_HTML_NODEFDTD |
LIBXML_NOBLANKS |
LIBXML_NOEMPTYTAG
);
$sYourHTMLStringWithoutEmptyTags = $oDOMHTML->saveXML();
也许这对你有用。
【讨论】:
我试过了,但没有用。我的 PHP 是 5.4.19。稍后我会尝试(当我理解时)。谢谢! 也许你给我一些示例代码,这只是编写没有任何测试。今天下午刚刚阅读了 LIBXML_* 常量。 嗯,显然这些选项只是将“”变成了“”。 “”->“”也是如此。抱歉,我认为这可能会有所帮助。值得一试。【参考方案5】:您也可以使用递归来解决这个问题。继续将 HTML blob 传递回函数,直到不再存在空标记。
public static function removeHTMLTagsWithNoContent($htmlBlob)
$pattern = "/<[^\/>][^>]*><\/[^>]+>/";
if (preg_match($pattern, $htmlBlob) == 1)
$htmlBlob = preg_replace($pattern, '', $htmlBlob);
return self::removeHTMLTagsWithNoContent($htmlBlob);
else
return $htmlBlob;
这将检查是否存在空 HTML 标记并替换它们,直到正则表达式模式不再匹配为止。
【讨论】:
【参考方案6】:这是删除所有空标签的另一种方法。 (如果它们因为空子而被认为是空的,它也会删除周围的标签:
/**
* Remove empty tags.
* This one will also remove <p><a href="/foo/bar.baz"><span></span></a></p> (empty paragraph with empty link)
* But it will not alter <p><a href="/foo/bar.baz"><span>[CONTENT HERE]</span></a></p> (since the span has content)
*
* Be aware: <img ../> will be treated as an empty tag!
*/
do
$len1 = mb_strlen($string);
$string = preg_replace('/<(\w+)\b(?:\s+[\w\-.:]+(?:\s*=\s*(?:"[^"]*"|"[^"]*"|[\w\-.:]+))?)*\s*\/?>\s*<\/\1\s*>/', '', $string);
$len2 = mb_strlen($string);
while ($len1 > 0 && $len2 > 0 && $len1 != $len2);
我一直在使用它来清理来自外部 CMS 的 html,并取得了积极的结果。
【讨论】:
以上是关于正则表达式删除所有空的 HTML 标记的主要内容,如果未能解决你的问题,请参考以下文章
Oracle 正则表达式 - 删除字符串中长度为 1 的字母标记之间的空格