根據兄弟屬性選擇節點 - HtmlAgilityPack - C#

c# html-agility-pack html-parsing

我有一個HTML文檔,其結構如下

<ul class="beverageFacts">
<li>
    <span>Vintage</span> 
    <strong>2007&nbsp;</strong>
</li>
<li>
    <span>ABV</span> 
    <strong>13,0&nbsp;%</strong>
</li>
<li>
    <span>Sugar</span> 
    <strong>5&nbsp;gram/liter</strong>
</li>

我需要將<strong> -tags的值解析為相應的string ,具體取決於<span> -tag具有的值。

我有以下內容:

String vintage;
String sugar;
String abv;

截至目前,我循環通過的每個子節點beverageFacts -Node檢查值將它解析到正確的對應string 。到目前為止,我獲得“Vintage”值的代碼如下,但結果始終為null

HtmlNodeCollection childNodes = bevFactNode.ChildNodes;
foreach (HtmlNode subNode in childNodes)
{
    if (subNode.InnerText.TrimStart() == "Vintage")
        vintage = subNode.NextSibling.InnerText.Trim();
}

我相信我選擇的節點是不正確的,但我無法弄清楚如何以最有效的方式正確地做到這一點。

有沒有一種簡單的方法來實現這一目標?


編輯2013-07-29

我試圖使用以下代碼刪除評論中的enricoariel建議的空格

        HtmlAgilityPack.HtmlDocument page = new HtmlWeb().Load("http://www.systembolaget.se/" + articleID);

        string cleanDoc = Regex.Replace(page.DocumentNode.OuterHtml, @"\s*(?<capture><(?<markUp>\w+)>.*<\/\k<markUp>>)\s*", "${capture}", RegexOptions.Singleline);

        HtmlDocument cleanPage = new HtmlDocument();
        cleanPage.LoadHtml(cleanDoc);

結果仍然是

 String vintage = null;

一般承認的答案

看看HTML標記,我意識到我在節點中沒有深入。此外,正如richoariel指出的那樣,有些空格我不能正常清理。通過跳過作為空格的兄弟,而不是跳到下面,我得到了正確的結果。

        foreach (HtmlNode bevFactNode in bevFactsNodes)
        {
            HtmlNodeCollection childNodes = bevFactNode.ChildNodes;
            foreach (HtmlNode node in childNodes)
            {
                foreach(HtmlNode subNode in node.ChildNodes)
                {
                    if (subNode.InnerText.Trim() == "Årgång")
                        vintage = HttpUtility.HtmlDecode(subNode.NextSibling.NextSibling.InnerText.Trim());
                }
            }
        }
        Console.WriteLine("Vintage: " + vintage);

將輸出

Vintage: 2007

我解碼HTML以正確格式化結果。

得到教訓!


熱門答案

總結一下,我認為最好的解決方案是在檢索nextSibling值之前使用正則表達式剝離所有空格:

    string myHtml =
    @"
    <ul class='beverageFacts'>
    <li>
        <span>Vintage</span> 
        <strong>2007&nbsp;</strong>
    </li>
    <li>
        <span>ABV</span> 
        <strong>13,0&nbsp;%</strong>
    </li>
    <li>
        <span>Sugar</span> 
        <strong>5&nbsp;gram/liter</strong>
    </li>";
    //Remove space after and before tag
myHtml = Regex.Replace(myHtml, @"\s+<", "<", RegexOptions.Multiline | RegexOptions.Compiled);
myHtml = Regex.Replace(myHtml, @">\s+", "> ", RegexOptions.Compiled | RegexOptions.Multiline);

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(myHtml.Replace("/r", "").Replace("/n", "").Replace("/r/n", "").Replace("  ", ""));
doc.OptionFixNestedTags = true;

HtmlNodeCollection vals = doc.DocumentNode.SelectNodes("//ul[@class='beverageFacts']//span");

var myNodeContent = string.Empty;
foreach (HtmlNode val in vals)
{
    if (val.InnerText == "Vintage")
    {
        myNodeContent = val.NextSibling.InnerText;
    }
}

return myNodeContent;


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow