HTML解析C#HTMLAgilityPack

c# html-agility-pack xpath

質問

HTMLAgilityPackを使用してHTML文字列から値を読み取る際に問題が発生しています。

読んでみたい2つのアイテムは新聞:82548828と魚:8545852485です

しかし、これまでに書いたコードを使って、私は新聞記事を取り戻すことができます。

私が使用しているXPATHが完全に正しいとは思わない、私は最初のループのXPATHはこれが私に2つを返すように訂正されていると思う

私はこれらの2つの項目をループするために私の2番目のループが必要です(それは6つだと思いますか?)

div2.SelectSingleNode(sXPathT)もあります。 groupLabelを抽出する正しい方法は?それとも良い方法がありますか?

ありがとう

下の完全なテストコード

string strTestHTML = @"<div class=\""content\"" data-id=\""123456789\"">" + 
                              "  <div class=\"m-group item\">" +
                              "      <span class=\"group\">" +
                              "          <a href=\"javascript:void(0);\">" +
                              "          <span class=\"group-label\">Newspaper </span>" +
                              "          <span class=\"group-value\">82548828</span>" +
                              "          </a>" +
                              "      </span>" +
                              "      <span class=\"group\">" +
                              "          <a href=\"javascript:void(0);\">" +
                              "          <span class=\"group-label\">Fish </span>" +
                              "          <span class=\"group-value\">8545852485</span>" +
                              "          </a>" +
                              "      </span>" +
                              "  </div>" +
                              "</div>";


            //<div class="content" data-id="123456789">
            string sNewXpath = "//div[contains(@class,'content') and contains(@data-id, '" + "123456789" + "')]";
            //<div class="m-group item">
            string sSecondXPath = "/div[contains(@class,'m-group item')]";
            //<span class="group"
            string sThirdXPath = "//span[contains(@class,'group')]";

            string sXPathT = "//span[contains(@class,'group-label')]";
            string sXPathO = "//span[contains(@class,'group-value')]";

            HtmlAgilityPack.HtmlDocument Doc = new HtmlDocument();
            Doc.LoadHtml(strTestHTML);

            foreach (HtmlNode div in Doc.DocumentNode.SelectNodes(sNewXpath + sSecondXPath))
            {
                foreach (HtmlNode div2 in div.SelectNodes(sThirdXPath))
                {
                    var vOddL = div2.SelectSingleNode(sXPathT);
                    var vOddP = div2.SelectSingleNode(sXPathO);

                    string GroupLabel = vOddL.InnerText.Trim();

                    string GroupValue = vOddP.InnerText.Trim();
                }
            }

編集:

なぜ私はforloopに6つのアイテムを戻していたのか

sThirdXPathは次のとおりです:string sThirdXPath = "// span [contains(@ class、 'group')]";

次のようにする:

文字列sThirdXPath = "// span [@ class = 'group']";

関心のある値を見つけるためにdiv2に含まれるHTMLNodeを調べる正しい方法を探しています。私は、HTML文書ではなく、現在のノードと一致するようにXPathが必要であると仮定します。

更新されたHTMLサンプル:

<div class="content" data-id="123456789">
<div class="m-group item">
    <span class="group">
        <a href="javascript:void(0);">
        <span class="group-label">Newspaper </span>
        <span class="group-value">82548828</span>
        </a>
    </span>

    <span class="group">
        <a href="javascript:void(0);">
        <span class="group-label">Fish </span>
        <span class="group-value">8545852485</span>
        </a>
    </span>
</div>
</div>

<div class="content" data-id="987654321">
<div class="m-group item">
    <span class="group">
        <a href="javascript:void(0);">
        <span class="group-label">Bread</span>
        <span class="group-value">82548828</span>
        </a>
    </span>

    <span class="group">
        <a href="javascript:void(0);">
        <span class="group-label">Milk </span>
        <span class="group-value">8545852485</span>
        </a>
    </span>
</div>
</div>

上記の例では、Just BreadとそのValue、MilkとそのValueにアクセスするための正しいXPATHは何ですか?私は、データID = "987654321でフィルタリングする必要があると仮定します。

受け入れられた回答

あなたの疑惑は正しいです、あなたはすでにフルパスのXPathクエリを指定しているので、ループは必要ありません。この例で "新聞"と "フィッシュ"ノードを取得するには、ループしてSelectSingleNodeを呼び出すのではなく、単にSelectNodesを使用します。もちろん、結果セットをループすることができるアイテムが他にもある場合は、この例では2つしかないのでインデックスにアクセスしました。

string sXPathT = "//span[contains(@class,'group-label')]";
string sXPathO = "//span[contains(@class,'group-value')]";

HtmlAgilityPack.HtmlDocument Doc = new HtmlDocument();
Doc.LoadHtml(strTestHTML);

var vOddL = Doc.DocumentNode.SelectNodes(sXPathT);
var vOddP = Doc.DocumentNode.SelectNodes(sXPathO);

string GroupLabelNewsPaper = vOddL.ElementAt(0).InnerText.Trim();
string GroupLabelFish = vOddL.ElementAt(1).InnerText.Trim();

string GroupValueNewspaper = vOddP.ElementAt(0).InnerText.Trim();
string GroupValueFish = vOddP.ElementAt(1).InnerText.Trim();

Console.WriteLine($"{GroupLabelNewsPaper}\t{GroupValueNewspaper}");
Console.WriteLine($"{GroupLabelFish}\t{GroupValueFish}");

出力:

Newspaper       82548828
Fish    8545852485

UPDATE:特定のコンテンツノードを取得するには、このXPathを使用します。

string xpathForDataId = "//div[@class='content' and @data-id='987654321']";

上記の式でdivをフィルタリングし、次にこのような子ノードを得ることができます:

string sXPathT = ".//span[contains(@class,'group-label')]";
string sXPathO = ".//span[contains(@class,'group-value')]";
string xpathForDataId = "//div[@class='content' and @data-id='987654321']";

HtmlAgilityPack.HtmlDocument Doc = new HtmlDocument();
Doc.LoadHtml(strTestHTML);

var specificNode = Doc.DocumentNode.SelectSingleNode(xpathForDataId);

var vOddL = specificNode.SelectNodes(sXPathT);
var vOddP = specificNode.SelectNodes(sXPathO);

string GroupLabelBread = vOddL.ElementAt(0).InnerText.Trim();
string GroupLabelMilk = vOddL.ElementAt(1).InnerText.Trim();

string GroupValueBread = vOddP.ElementAt(0).InnerText.Trim();
string GroupValueMilk = vOddP.ElementAt(1).InnerText.Trim();

Console.WriteLine($"{GroupLabelBread}\t{GroupValueBread}");
Console.WriteLine($"{GroupLabelMilk}\t{GroupValueMilk}");

sXPathTとsXPathOの ".//"に注目してください。これにより、現在のコンテキストのみを検索し、ドキュメント全体を検索することはありません。

出力:

Bread   82548828
Milk    8545852485


ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ