如何使用HTML敏捷包修复格式错误的HTML

本文关键字:HTML 格式 错误 包修复 何使用 | 更新日期: 2023-09-27 17:54:02

我有这个格式错误的HTML,标签重叠:

<p>word1<b>word2</p>
<p>word3</b>word4</p>

重叠也可以嵌套。

如何使用HTML敏捷包(HAP)将其转换为格式良好的HTML ?

我正在寻找这个输出:

<p>word1<b>word2</b></p>
<p><b>word3</b>word4</p>

我尝试了HtmlNode.ElementsFlags["b"] = HtmlElementFlag.Closed | HtmlElementFlag.CanOverlap,但它不像预期的那样工作。

如何使用HTML敏捷包修复格式错误的HTML

它实际上按预期工作,但可能不像期望的那样工作。无论如何,这里有一段示例代码(一个控制台应用程序),它演示了如何使用库实现一些HTML修复。

库有一个ParseErrors集合,您可以使用它来确定在标记解析过程中检测到哪些错误。

这里实际上有两种类型的问题:

1) 未闭合元素。默认情况下,标准库是固定的,但在这种情况下,P元素上有一个选项可以防止这种情况发生。

2) 未打开元素。这个更复杂,因为它取决于你想如何修复它,你想让标签在哪里打开?在下面的示例中,我使用了最近的前一个文本兄弟节点来打开元素。

static void Main(string[] args)
{
    // clear the flags on P so unclosed elements in P will be auto closed.
    HtmlNode.ElementsFlags.Remove("p");
    // load the document
    HtmlDocument doc = new HtmlDocument();
    doc.Load("yourTestFile.htm");
    // build a list of nodes ordered by stream position
    NodePositions pos = new NodePositions(doc);
    // browse all tags detected as not opened
    foreach (HtmlParseError error in doc.ParseErrors.Where(e => e.Code == HtmlParseErrorCode.TagNotOpened))
    {
        // find the text node just before this error
        HtmlTextNode last = pos.Nodes.OfType<HtmlTextNode>().LastOrDefault(n => n.StreamPosition < error.StreamPosition);
        if (last != null)
        {
            // fix the text; reintroduce the broken tag
            last.Text = error.SourceText.Replace("/", "") + last.Text + error.SourceText;
        }
    }
    doc.Save(Console.Out);
}
public class NodePositions
{
    public NodePositions(HtmlDocument doc)
    {
        AddNode(doc.DocumentNode);
        Nodes.Sort(new NodePositionComparer());
    }
    private void AddNode(HtmlNode node)
    {
        Nodes.Add(node);
        foreach (HtmlNode child in node.ChildNodes)
        {
            AddNode(child);
        }
    }
    private class NodePositionComparer : IComparer<HtmlNode>
    {
        public int Compare(HtmlNode x, HtmlNode y)
        {
            return x.StreamPosition.CompareTo(y.StreamPosition);
        }
    }
    public List<HtmlNode> Nodes = new List<HtmlNode>();
}