2

さて私は次の問題を抱えています。
私が持っているhtmlは不正な形式であり、この場合、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 packは、lststrTextで4つではなく5つの文字列を返します。
それで、htmlagilityパックが要素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"
4

2 に答える 2

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
于 2009-12-25T23:05:57.400 に答える