我正在想象一个我想要使用Regex的函数,对于像<p><strong></strong></p>
这样的实例来说,删除字符串中的所有空HTML标签会是递归的。如果可能的话,这必须考虑空白。没有疯狂的实例&lt;字符正在属性值中使用。
我在正则表达式上非常糟糕,但我想这是可能的。你怎么能这样做?
这是我到目前为止的方法:
Public Shared Function stripEmptyHtmlTags(ByVal html As String) As String
Dim newHtml As String = Regex.Replace(html, "/(<.+?>\s*</.+?>)/Usi", "")
If html <> newHtml Then
newHtml = stripEmptyHtmlTags(newHtml)
End If
Return newHtml
End Function
然而,我现在的正则表达式是PHP格式,它似乎不起作用。我不熟悉.NET正则表达式语法。
对于所有那些不使用正则表达式的人:我很好奇这种模式无论如何。当然有一种模式可以匹配所有打开/关闭开始标签与标签之间的任何数量的空白(或没有)?我已经看到正则表达式将HTML标记与任意数量的属性匹配,一个空标记(例如只是<p></p>
)等。
到目前为止,我已经在上面的方法中尝试了以下正则表达式模式无效(因为,我有一个带有空段落标记的文本字符串,甚至没有被删除。)
Regex.Replace(html, "/(<.+?>\s*</.+?>)/Usi", "")
Regex.Replace(html, "(<.+?>\s*</.+?>)", "")
Regex.Replace(html, "%<(\w+)\b[^>]*>\s*</\1\s*>%", "")
Regex.Replace(html, "<\w+\s*>\s*</\1\s*>", "")
答案 0 :(得分:8)
首先,请注意,根据定义,空HTML元素不是嵌套的。
更新:下面的解决方案现在递归地应用空元素正则表达式来删除“nested-empty-element”结构,例如:<p><strong></strong></p>
(受制于注意事项如下所述。)
对于没有包含<>
有趣内容的开始标记属性的HTML,以(未经测试的)VB.NET片段的形式,这非常有效(请参阅下面的注意事项):
Dim RegexObj As New Regex("<(\w+)\b[^>]*>\s*</\1\s*>")
Do While RegexObj.IsMatch(html)
html = RegexObj.Replace(html, "")
Loop
<(\w+)\b(?:\s+[\w\-.:]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[\w\-.:]+))?)*\s*/?>\s*</\1\s*>
以下是VB.NET中未注释的增强版本(未经测试):
Dim RegexObj As New Regex("<(\w+)\b(?:\s+[\w\-.:]+(?:\s*=\s*(?:""[^""]*""|'[^']*'|[\w\-.:]+))?)*\s*/?>\s*</\1\s*>")
Do While RegexObj.IsMatch(html)
html = RegexObj.Replace(html, "")
Loop
这个更复杂的正则表达式正确匹配有效的空HTML 4.01元素,即使它的属性值中有尖括号(再次提到主题,请注意下面的警告)。换句话说,这个正则表达式正确处理引用的所有开始标记属性值(可以有<>
),不带引号(不能)和空。这是一个完全评论(和测试)的PHP版本:
function strip_empty_tags($text) {
// Match empty elements (attribute values may have angle brackets).
$re = '%
# Regex to match an empty HTML 4.01 Transitional element.
< # Opening tag opening "<" delimiter.
(\w+)\b # $1 Tag name.
(?: # Non-capture group for optional attribute(s).
\s+ # Attributes must be separated by whitespace.
[\w\-.:]+ # Attribute name is required for attr=value pair.
(?: # Non-capture group for optional attribute value.
\s*=\s* # Name and value separated by "=" and optional ws.
(?: # Non-capture group for attrib value alternatives.
"[^"]*" # Double quoted string.
| \'[^\']*\' # Single quoted string.
| [\w\-.:]+ # Non-quoted attrib value can be A-Z0-9-._:
) # End of attribute value alternatives.
)? # Attribute value is optional.
)* # Allow zero or more attribute=value pairs
\s* # Whitespace is allowed before closing delimiter.
> # Opening tag closing ">" delimiter.
\s* # Content is zero or more whitespace.
</\1\s*> # Element closing tag.
%x';
while (preg_match($re, $text)) {
// Recursively remove innermost empty elements.
$text = preg_replace($re, '', $text);
}
}
警告:此功能不解析HTML。它只是匹配并删除与有效的空HTML 4.01元素相对应的任何文本模式序列(根据定义,它是不嵌套)。请注意,这也会错误地匹配并删除可能在普通HTML标记之外发生的相同文本模式,例如SCRIPT和STYLE标记和HTML注释以及其他开始标记的属性。此正则表达式不适用于短标签。对于任何bobenc粉丝,给这个答案一个自动向下投票,请告诉我一个有效的HTML 4.01空元素,这个正则表达式无法正确匹配。这个正则表达式遵循W3C规范,确实有效。
更新:如果您执行极其不可能(但完全有效),此正则表达式解决方案也无效(并且会错误地删除有效标记):
<div att="<p att='">stuff</div><div att="'></p>'">stuff</div>
再想一想,只需使用HTML解析器!
答案 1 :(得分:1)
您遇到的问题是任意级别的嵌套,无法与标准正则表达式匹配。我想你可以一遍又一遍地应用相同的正则表达式替换,直到没有留下任何东西。但是有更好的解决方案,例如专用的HTML解析库。
答案 2 :(得分:1)
你不能用正则表达式来做。假设html格式正确,你可以使用xml解析器。
答案 3 :(得分:0)
为什么递归,你可以简单地运行
<(\w+)\s*>\s*</\1\s*>
并将其替换为空,并继续应用该正则表达式,直到您的输入不再更改为止。