當有一個未關閉的html標籤時,是否可以解決HtmlAgilityPack中的問題?

c# html-agility-pack xpath

我有以下問題。
我遇到的html格式不正確,在這種情況下我使用html agility pack選擇節點時遇到問題。
代碼如下:

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 pack在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"

一般承認的答案

大多數html解析器嘗試構建一個工作DOM,這意味著不接受懸空標籤。它們將被轉換或以某種方式關閉。

如果只選擇節點對您來說很重要,速度和大量數據不是問題,您可以使用正則表達式獲取所有<p>標籤:

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

此正則表達式假定<p>標記格式良好且已關閉。

如果您要在程序中運行此正則表達式,則應將其聲明為:

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,span,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

熱門答案

您可以使用TidyNet進行前提/後處理。你能編輯你的答案來解釋為什麼那些不適用於你的情況嗎?



許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因