2014-03-26 48 views
8

我有这个重叠的标签病态的HTML:如何使用HTML Agility Pack修复格式不正确的HTML?

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

重叠可以被嵌套了。

如何将它转换为HTML格式的HTML与HTML敏捷包(HAP)?

我在寻找这样的输出:

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

我试过HtmlNode.ElementsFlags["b"] = HtmlElementFlag.Closed | HtmlElementFlag.CanOverlap,但预期它不工作。

回答

19

它实际上按预期工作,但可能不起作用您预期的。无论如何,下面是一段代码示例(一个控制台应用程序),演示了如何使用该库实现一些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>(); 
} 
+1

谢谢西蒙,我需要“消化”这:)这是很好的直接听到作者,你的工作在HAP是非常广泛的赞赏。 – avo

+0

上有特殊情况吗? 我只问,因为我似乎正在收到意想不到的行为周围框架没有被自动关闭。 – twobob

+0

@twobob - 是的,也许,你可以在这里检查这个行为(框架声明,你可以使用ElementFlags集合删除它):http://htmlagilitypack.codeplex.com/SourceControl/latest#Trunk/HtmlAgilityPack/HtmlNode.cs –

相关问题