我有一个字符串作为 HTML 源,我想检查作为字符串的 HTML 源是否包含未打开的标签。
例如,下面的字符串在 WAVEFORM 之后包含
</u>
,而 WAVEFORM 没有开头 <u>
。
WAVEFORM</u> YES, <u>NEGATIVE AUSCULTATION OF EPIGASTRUM</u> YES,
我只想检查这些类型的未打开标签,然后我必须将打开标签附加到字符串的开头?
对于这种特定情况,您可以使用 HTML Agility Pack 来断言 HTML 格式是否正确或者是否有标签未打开。
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(
"WAVEFORM</u> YES, <u>NEGATIVE AUSCULTATION OF EPIGASTRUM</u> YES,");
foreach (var error in htmlDoc.ParseErrors)
{
// Prints: TagNotOpened
Console.WriteLine(error.Code);
// Prints: Start tag <u> was not found
Console.WriteLine(error.Reason);
}
没那么容易。您不能直接使用 HTML 解析器,因为它不是有效的 HTML,但您也不能轻易地在整个过程中使用正则表达式,因为正则表达式无法处理嵌套或其他 HTML 复杂性。
您能做的最好的事情可能就是使用正则表达式来查找每个标记结构,例如。像这样的东西:
<(\w+)(?:\s+[-\w]+(?:\s*(?:=\s*(?:"[^"]*"|'[^']*'|[^'">\s][^>\s]*)))?)*\s*>
|</(\w+)\s*>
|<!--.*?-->
从空的要打开的标签列表和空的要关闭的标签列表开始。对于字符串中的每个匹配项,查看第 1 组和第 2 组,看看是否有开始或结束标记。 (或者是评论,您可以忽略它。)
如果你有一个开始标签,你需要知道它是否需要关闭,即。如果它是
EMPTY
内容模型标签之一,例如 <img>
。如果一个元素是 EMPTY
,则它不需要关闭,因此您可以忽略它。 (如果您有 XHTML,这一切都会更容易一些。)
如果您有开始标签,请将正则表达式组中的标签名称添加到要关闭的标签列表中。如果您有结束标签,请从要关闭的标签列表的末尾取出一个标签(它应该与那里的标签名称相同,否则您的标记无效。如果上没有标签要关闭的标签列表,而是将标签名称添加到要打开的标签列表中。
到达输入字符串的末尾后,以相反的顺序将每个要打开的标记添加到字符串中,并将要关闭的标记的结束标记附加到末尾,再次在颠倒顺序。
(是的,我正在用正则表达式解析 HTML。我认为这种肮脏的行为说明了为什么你不想这样做。如果你可以采取任何措施来避免已经在标签中间剪切你的标记,那就这样做。 )
using HtmlDocument = HtmlAgilityPack.HtmlDocument;
public static string HttpParse(string strIn)
{
string strRtn = "";
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(strIn);
foreach(var strErr in htmlDoc.ParseErrors)
{
strRtn += strErr.Reason + Environment.NewLine;
}
return strRtn;
}