2009-12-18 21 views
2

以及我有以下問題。
我的html格式不正確,當遇到這種情況時,我選擇使用html敏捷包的節點時遇到問題。
代碼是下面:有沒有可能修復HtmlAgilityPack中的問題,當有一個不封閉的HTML標記?

string strHtml = @" 
<html> 
    <div> 
    <p><strong>Elem_A</strong>String_A1_2 String_A1_2</p> 
    <p><strong>Elem_B</strong>String_B1_2 String_B1_2</p> 
    </div> 
    <div> 
    <p><strong>Elem_A</strong>String_A2_2 <String_A2_2> asdas</p> 
    <p><strong>Elem_B</strong>String_B2_2 String_B2_2</p> 
    </div> 
</html>"; 
HtmlAgilityPack.HtmlDocument objHtmlDocument = new HtmlAgilityPack.HtmlDocument(); 
objHtmlDocument.LoadHtml(strHtml); 
HtmlAgilityPack.HtmlNodeCollection colnodePs = objHtmlDocument.DocumentNode.SelectNodes("//p"); 
List<string> lststrText = new List<string>(); 
foreach (HtmlAgilityPack.HtmlNode nodeP in colnodePs) 
{ 
    lststrText.Add(nodeP.InnerHtml); 
} 

問題是,String_A2_2括在括號中。
所以htmlagility包在lststrText中返回5個字符串而不是4個。
所以有可能讓htmlagility pack返回元素3爲 "<strong>Elem_A</strong>String_A2_2 <String_A2_2> asdas"
或者我可以做一些預處理來關閉元素?
lststrText的當前內容

lststrText[0] = "<strong>Elem_A</strong>String_A1_2 String_A1_2" 
lststrText[1] = "<strong>Elem_B</strong>String_B1_2 String_B1_2" 
lststrText[2] = "" 
lststrText[3] = "" 
lststrText[4] = "<strong>Elem_B</strong>String_B2_2 String_B2_2" 
+0

您是否知道要包含的標籤的名稱,還是想要將所有打開的標籤保留爲文本? – 2009-12-23 15:34:58

+0

我想將所有打開的標籤保留爲文字 – Karim 2009-12-23 18:37:55

+1

Html Agility Pack無法做到這一點。它一次解析一個角色,並沒有真正的回溯概念。但是,它會關閉需要的標籤,但這是因爲您經歷了與您想要的不同輸出的結果。 最好的辦法是做一些預處理。 如果您知道要保留的標籤的名稱或模式,可以很容易地修改解析代碼以保持標籤類似於:,稍後可以將其替換爲您的輸出。 也許修復您正在處理的格式錯誤的html更容易? – 2009-12-23 22:12:28

回答

2

大多數html解析器都試圖構建一個可工作的DOM,這意味着懸掛標籤不被接受。他們會被轉換,或以某種方式關閉。

如果只選擇節點是很重要的你,速度和巨大的數據量不是問題,你可以抓住所有的<p>標籤用正則表達式來代替:

Regex reMatchP = new Regex(@"<(p)>.*?</\1>"); 
foreach (Match m in reMatchP.Matches(strHtml)) 
{ 
    Console.WriteLine(m.Value); 
} 

這正則表達式假設標籤格式良好並且關閉。

如果您運行此正則表達式很多程序,你應該把它聲明爲:

static Regex reMatchP = new Regex(@"<(p)>.*?</\1>", RegexOptions.Compiled); 

[編輯:敏捷包更改]

如果你想使用HtmlAgility包你可以修改在HtmlDocument.cs的PushNodeEnd功能:

if (HtmlNode.IsCDataElement(CurrentNodeName())) 
{ 
    _state = ParseState.PcData; 
    return true; 
} 

// new code start 
if (!AllowedTags.Contains(_currentnode.Name)) 
{ 
    close = true; 
} 
// new code end 

其中AllowedTags將所有已知標籤的列表:b,p,BR,跨度,DIV等

輸出不是100%你想要的,但可能夠接近?

<strong>Elem_A</strong>String_A1_2 String_A1_2 
<strong>Elem_B</strong>String_B1_2 String_B1_2 
<strong>Elem_A</strong>String_A2_2 <ignorestring_a2_2></ignorestring_a2_2> asdas 
<strong>Elem_B</strong>String_B2_2 String_B2_2 
+1

正則表達式不是parsehtml的選項。 – Karim 2009-12-26 06:58:50

+0

我添加了我的代碼更改作爲示例。它可能有幫助。 – 2009-12-26 14:18:12

+0

謝謝,我會看看,看看是否能解決這個問題。 – Karim 2009-12-26 22:38:49

2

你可以使用TidyNet做預/後處理你暗示。你可以編輯你的答案來解釋爲什麼這不適用於你的情況?

+0

以及我沒有嘗試TidyNet因爲我無法讓它工作。 但我試過SgmlReader http://developer.mindtouch.com/SgmlReader,但我也沒有工作。 – Karim 2009-12-23 18:40:36

相關問題