HtmlAgilityPack选择子节点的结果不符合预期

41

我试图使用HtmlAgilityPack库解析页面中的一些链接,但是我发现方法的结果与我的期望不符。以下是一个包含链接的HtmlNodeCollection。对于每个链接,我想检查是否有一个图片节点,然后解析它的attributes,但是linkNodeSelectNodesSelectSingleNode方法似乎搜索的是父文档而不是linkNodechildNodes。怎么回事?

HtmlDocument htmldoc = new HtmlDocument();
htmldoc.LoadHtml(content);
HtmlNodeCollection linkNodes = htmldoc.DocumentNode.SelectNodes("//a[@href]");
    
foreach(HtmlNode linkNode in linkNodes)
{
    string linkTitle = linkNode.GetAttributeValue("title", string.Empty);
    if (linkTitle == string.Empty)
    {
        HtmlNode imageNode = linkNode.SelectSingleNode("/img[@alt]");     
    }
}

如果存在,还有其他方法可以获取linkNode的图像子节点的alt属性吗?

3个回答

44
你应该从"/img[@alt]"中删除斜杠前缀,因为它表示你想从文档的根部开始。
HtmlNode imageNode = linkNode.SelectSingleNode("img[@alt]");

1
嗯,好的。我真是太蠢了。我以为我漏掉了什么。抱歉浪费了问题空间。谢谢。 - Sheff
3
总有很多空间 :) - Richard Szalay
1
你真棒!刚才我还在抱怨 HtmlAgility 项目,但结果他们只是以正确的方式实现了 XPath :) - Moulde
这对我不起作用(HtmlAgilityPack 1.4.9)- 我必须使用.//符号(下面的答案)。 - wal
1
@wal 以上语法假定目标img是“linkNode”的直接子代。如果你必须使用“.//”,我猜测img是后代而不是直接子代。 - Richard Szalay

43

使用XPath查询时,你可以使用 "." 表示搜索应该从当前节点开始。

HtmlNode imageNode = linkNode.SelectSingleNode(".//img[@alt]");

默认的轴是“children”,实际上根本不需要前缀。 - Richard Szalay

10

另外,要注意null检查;SelectNodes返回null而不是空集合。

HtmlNodeCollection linkNodes = htmldoc.DocumentNode.SelectNodes("//a[@href]");

**if(linkNodes!=null)**
{
   foreach(HtmlNode linkNode in linkNodes)
  {
     string linkTitle = linkNode.GetAttributeValue("title", string.Empty);
     if (linkTitle == string.Empty)
     {
       **HtmlNode imageNode = linkNode.SelectSingleNode("img[@alt]");**   
     }
  }
}

4
在我看来,这是一个非常愚蠢的设计决策。没有理由它不应该返回空集合。 - mpen
请参见http://stackoverflow.com/questions/8619724/htmlagilitypack-documentnode-selectnodes-returns-null-shouldnt。 - Tim Abell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接