【问题标题】:Select node based on sibling properties - HtmlAgilityPack - C#根据兄弟属性选择节点 - HtmlAgilityPack - C#
【发布时间】:2013-07-28 21:00:26
【问题描述】:

我有一个结构如下的 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>

我需要将&lt;strong&gt;-tag 的值解析为对应的string,具体取决于&lt;span&gt;-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

我已尝试使用以下代码删除 cmets 中 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;

【问题讨论】:

  • 问题是 nextSibling 是一个空格。如果你去掉标签之间的所有空白,你会得到正确的结果。在这里查看我的问题:stackoverflow.com/questions/17785682/…
  • 我看不出你的问题对我有什么帮助。如果兄弟是空格,那么我的复古字符串不会也设置为“”而不是 null 吗?
  • 删除空格,您会发现它会起作用:
    • Vintage2007 
    • ...
  • 现在开始工作了!你是对的,有空格,我的清理方法不起作用!我将发布一个显示我的解决方案的答案!

标签: c# html-parsing html-agility-pack


【解决方案1】:

查看 HTML 标记,我意识到我没有深入到节点中。 此外,正如 enricoariel 指出的那样,有些空格我没有正确清理。通过跳过作为空格的兄弟姐妹,而是跳转到以下内容,我得到了正确的结果。

        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 进行了解码以获得正确格式的结果。

经验教训!

【讨论】:

    【解决方案2】:

    总结一下,我认为最好的解决方案是在检索 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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多