失去了HtmlAgilityPack中loadhtml函数的“小于”符号

8

我最近开始尝试使用HtmlAgilityPack。我不熟悉它的所有选项,因此我认为我做错了什么。

我有一个包含以下内容的字符串:

string s = "<span style=\"color: #0000FF;\"><</span>";

你看到在我的span标签中有一个小于号。 我使用以下代码处理这个字符串:

HtmlDocument htmlDocument = new HtmlDocument();
htmlDocument.LoadHtml(s);

但是当我这样快速地查看span时:

htmlDocument.DocumentNode.ChildNodes[0].InnerHtml

我看到这个标签是空的

我需要设置哪个选项来保留“小于”符号。我已经尝试过这个:

htmlDocument.OptionAutoCloseOnEnd = false;
htmlDocument.OptionCheckSyntax = false;
htmlDocument.OptionFixNestedTags = false;

但是一直没有成功。

我知道这是无效的HTML。我使用它来修复无效的HTML并在“小于”符号上使用HTMLEncode

请指引我正确的方向。提前感谢。


2
这是无效的HTML,所以一切都不确定 - 你应该将小于号编码为&lt; - Damien_The_Unbeliever
1
我知道这是无效的HTML。我正在使用它来修复无效的HTML并在“小于”符号上使用HTMLEncode。 - TurBas
我本以为对于计算机来说,确定一个给定的角括号是属于一个损坏的HTML标签还是错误转义的角括号是一件困难的事情。那个解析过的HTML片段中是否有其他标签?如果它完全破坏了它而不是将其转换为其他东西,我会感到有些惊讶,但我可能是错的... - Chris
5个回答

3

如另一个回答中提到的那样,我发现最好的解决方案是预先解析HTML,将孤立的<符号转换为它们的HTML编码值&lt;

return Regex.Replace(html, "<(?![^<]+>)", "&lt;");

3
Html Agility Pack会检测到这个错误并为其创建一个HtmlParseError实例。您可以使用HtmlDocument类的ParseErrors读取所有错误。因此,如果运行此代码:
    string s = "<span style=\"color: #0000FF;\"><</span>";
    HtmlDocument doc = new HtmlDocument();
    doc.LoadHtml(s);
    doc.Save(Console.Out);

    Console.WriteLine();
    Console.WriteLine();

    foreach (HtmlParseError err in doc.ParseErrors)
    {
        Console.WriteLine("Error");
        Console.WriteLine(" code=" + err.Code);
        Console.WriteLine(" reason=" + err.Reason);
        Console.WriteLine(" text=" + err.SourceText);
        Console.WriteLine(" line=" + err.Line);
        Console.WriteLine(" pos=" + err.StreamPosition);
        Console.WriteLine(" col=" + err.LinePosition);
    }

它将显示以下内容(首先是已更正的文本,然后是有关错误的详细信息):
<span style="color: #0000FF;"></span>

Error
 code=EndTagNotRequired
 reason=End tag </> is not required
 text=<
 line=1
 pos=30
 col=31

因为你已经拥有所有必要的信息(包括行、列和流位置),所以你可以尝试修复这个错误,但在HTML中修复(而不是检测)错误的一般过程非常复杂。


2

修复标记,因为您的HTML字符串无效:

string s = "<span style=\"color: #0000FF;\">&lt;</span>";

我知道这是无效的HTML。我正在使用它来修复无效的HTML并在“小于”符号上使用HTMLEncode。 - TurBas
@TurBas:如果文本是a<b而不仅仅是<,那么InnerHtml的值将是什么? - Daniel Hilgarth
这是一个<>...所以他把它看作是一个开标签并关闭它?移除b? - TurBas
@TurBas:看起来你运气不太好啊...也许你真的应该在第一时间避免这个问题?或者你可以尝试想出一个正则表达式,检测那些无效的<字符,但我猜这并不容易。 - Daniel Hilgarth

2
尽管给定的HTML无效,但HtmlAgilityPack仍应能够解析它。在Web上忘记编码“<”是一个常见错误,如果HtmlAgilityPack用作爬虫程序,则应预期出现不良HTML。我在IE、Chrome和Firefox中测试了这个例子,它们都将额外的<显示为文本。
我编写了以下方法,您可以使用它来预处理HTML字符串,并将所有“未关闭”的'<'字符替换为"&lt;":
static string PreProcess(string htmlInput)
{
    // Stores the index of the last unclosed '<' character, or -1 if the last '<' character is closed.
    int lastGt = -1; 

    // This list will be populated with all the unclosed '<' characters.
    List<int> gtPositions = new List<int>();

    // Collect the unclosed '<' characters.
    for (int i = 0; i < htmlInput.Length; i++)
    {
        if (htmlInput[i] == '<')
        {
            if (lastGt != -1)
                gtPositions.Add(lastGt);

            lastGt = i;
        }
        else if (htmlInput[i] == '>')
            lastGt = -1;
    }

    if (lastGt != -1)
        gtPositions.Add(lastGt);

    // If no unclosed '<' characters are found, then just return the input string.
    if (gtPositions.Count == 0)
        return htmlInput;

    // Build the output string, replace all unclosed '<' character by "&lt;".
    StringBuilder htmlOutput = new StringBuilder(htmlInput.Length + 3 * gtPositions.Count);
    int start = 0;

    foreach (int gtPosition in gtPositions)
    {
        htmlOutput.Append(htmlInput.Substring(start, gtPosition - start));
        htmlOutput.Append("&lt;");
        start = gtPosition + 1;
    }

    htmlOutput.Append(htmlInput.Substring(start));
    return htmlOutput.ToString();
}

0

字符串 "s" 是不良的 HTML。

string s = "<span style=\"color: #0000FF;\">&lt;</span>";

是真的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接