如何使用 HTML Agility Pack 修复格式错误的 HTML?

Posted

技术标签:

【中文标题】如何使用 HTML Agility Pack 修复格式错误的 HTML?【英文标题】:How to fix ill-formed HTML with HTML Agility Pack? 【发布时间】:2014-05-04 21:26:12 【问题描述】:

我有这个带有重叠标签的格式错误的 html

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

重叠也可以嵌套。

如何使用 HTML Agility Pack (HAP) 将其转换为格式良好的 HTML?

我正在寻找这个输出:

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

我尝试了HtmlNode.ElementsFlags["b"] = HtmlElementFlag.Closed | HtmlElementFlag.CanOverlap,但它没有按预期工作。

【问题讨论】:

【参考方案1】:

它实际上按预期工作,但可能没有按的预期工作。不管怎样,这里有一段代码示例(一个控制台应用程序),它演示了如何使用该库实现一些 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>();

【讨论】:

谢谢 Simon,我需要“消化”一下 :) 很高兴直接收到作者的来信,您在 HAP 方面的工作受到了广泛的赞赏。 上是否有特殊情况?我只是问,因为我似乎在没有自动关闭的框架周围出现意外行为。 @twobob - 是的,也许,您可以在此处检查此行为(框架已声明,您可以使用 ElementFlags 集合将其删除):htmlagilitypack.codeplex.com/SourceControl/latest#Trunk/… 感谢您创建了如此有用的库。

以上是关于如何使用 HTML Agility Pack 修复格式错误的 HTML?的主要内容,如果未能解决你的问题,请参考以下文章

Html Agility Pack/C#:如何创建/替换标签?

HTML Agility Pack - 使用 Align=left 样式从 DIV 获取文本

使用 HTML Agility Pack 替换 HTML div InnerText 标签

Html Agility Pack:查找评论节点

csharp Html Agility Pack #CSharp #HtmlParsing

使用 Html Agility Pack 从 HTML BODY 节点中提取内部文本