2014-03-26 47 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 –

相關問題