基于同级属性选择节点-HtmlAgilityPack-C#

基于同级属性选择节点-HtmlAgilityPack-C#,c#,html-parsing,html-agility-pack,C#,Html Parsing,Html Agility Pack,我有一个HTML文档,其结构如下 <ul class="beverageFacts"> <li> <span>Vintage</span> <strong>2007&nbsp;</strong> </li> <li> <span>ABV</span> <strong>13,0&nbsp;%</strong&g

我有一个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>
现在,我正在遍历
beverageFacts
-节点的每个子节点,检查值以将其解析为正确的
字符串。
到目前为止,我获得“Vintage”值的代码如下,尽管结果总是
null

HtmlNodeCollection childNodes = bevFactNode.ChildNodes;
foreach (HtmlNode subNode in childNodes)
{
    if (subNode.InnerText.TrimStart() == "Vintage")
        vintage = subNode.NextSibling.InnerText.Trim();
}
我相信我对节点的选择是不正确的,但我不知道如何以最有效的方式正确地进行选择

有没有一个简单的方法来实现这一点


编辑2013-07-29

我已尝试使用以下代码删除注释中建议的空白

        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);

看着HTML标记,我意识到我没有深入到节点中。 此外,正如恩里科瑞尔所指出的,我没有正确清理一些空白。通过跳过同级,即空格,并跳转到以下内容,我得到了正确的结果

        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进行了解码,以正确格式化结果


吸取的教训

看着HTML标记,我意识到我没有深入到节点中。 此外,正如恩里科瑞尔所指出的,我没有正确清理一些空白。通过跳过同级,即空格,并跳转到以下内容,我得到了正确的结果

        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;
string myHtml=
@"
  • 酿造的 2007
  • ABV 13,0%
  • 5克/升
  • ”; //删除标记前后的空格 myHtml=Regex.Replace(myHtml,@“\s+”,RegexOptions.Compiled|RegexOptions.Multiline); HtmlDocument doc=新的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(以val表示的HtmlNode val) { 如果(val.InnerText==“年份”) { myNodeContent=val.NextSibling.InnerText; } } 返回myNodeContent;
总之,我认为最好的解决方案是在检索下一个sibling值之前使用正则表达式剥离所有空白:

    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;
string myHtml=
@"
  • 酿造的 2007
  • ABV 13,0%
  • 5克/升
  • ”; //删除标记前后的空格 myHtml=Regex.Replace(myHtml,@“\s+”,RegexOptions.Compiled|RegexOptions.Multiline); HtmlDocument doc=新的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(以val表示的HtmlNode val) { 如果(val.InnerText==“年份”) { myNodeContent=val.NextSibling.InnerText; } } 返回myNodeContent;
问题在于下一个标签是空白。如果去掉标记之间的所有空白,则会得到正确的结果。看看我的问题:我看不出你的问题对我有什么帮助。如果兄弟姐妹是一个空格,那么我的vintage字符串不是也会被设置为“”而不是null吗?删除空格,您就会看到它会工作:
  • vintage2007
  • …现在可以工作了!你是对的,有空白,我的清洁方法不起作用!我将发布一个显示我的解决方案的答案!问题是下一个标签是一个空白。如果去掉标记之间的所有空白,则会得到正确的结果。看看我的问题:我看不出你的问题对我有什么帮助。如果兄弟姐妹是一个空格,那么我的vintage字符串不是也会被设置为“”而不是null吗?删除空格,您就会看到它会工作:
    • vintage2007
    • …现在可以工作了!你是对的,有空白,我的清洁方法不起作用!我将发布一个显示我的解决方案的答案!