Html Agility Pack,来自节点的SelectNodes

时间:2012-05-14 13:05:33

标签: c# .net html-agility-pack

为什么选择我文档中的所有<li>元素?

HtmlWeb web = new HtmlWeb();
HtmlDocument doc = web.Load(url);

var travelList = new List<Page>();
var liOfTravels = doc.DocumentNode.SelectSingleNode("//div[@id='myTrips']")
                     .SelectNodes("//li");

我想要的是<li>中的所有<div>元素都带有id的“myTrips”。

5 个答案:

答案 0 :(得分:15)

这有点令人困惑,因为你期望它只会在id为“myTrips”的div上执行selectNodes,但是如果你再做一个SelectNodes(“// li”),它将从顶部执行另一个搜索文件。

我通过将语句合并为一个来修复此问题,但这只适用于您只有一个ID为“mytrips”的div的网页。查询将如下所示:

  

doc.DocumentNode.SelectNodes(“// div [@ id ='myTrips'] // li”);

答案 1 :(得分:13)

var liOfTravels = doc.DocumentNode.SelectSingleNode("//div[@id='myTrips']")
                 .SelectNodes(".//li");

注意第二行中的点。基本上在这方面,HTMLAgitilityPack完全依赖于XPath语法,但结果是不直观的,因为这些查询实际上是相同的:

doc.DocumentNode.SelectNodes("//li");
some_deeper_node.SelectNodes("//li");

答案 2 :(得分:5)

在某些情况下创建新节点会很有用,并且可以让您更直观地使用xpath。我发现这在几个地方很有用。

var myTripsDiv = doc.DocumentNode.SelectSingleNode("//div[@id='myTrips']");
var myTripsNode = HtmlNode.CreateNode(myTripsDiv.InnerHtml);
var liOfTravels = myTripsNode.SelectNodes("//li");

答案 3 :(得分:4)

您可以使用Linq查询执行此操作:

HtmlWeb web = new HtmlWeb();
HtmlDocument doc = web.Load(url);

var travelList = new List<HtmlNode>();
foreach (var matchingDiv in doc.DocumentNode.DescendantNodes().Where(n=>n.Name == "div" && n.Id == "myTrips"))
{
    travelList.AddRange(matchingDiv.DescendantNodes().Where(n=> n.Name == "li"));
}

我希望它有所帮助

答案 4 :(得分:1)

这对我来说似乎有点直观,如果你在特定节点上运行一个selectNodes方法,我认为它只会搜索该节点下面的东西,而不是一般在文档中搜索。

无论如何OP如果你改变这一行:     var liOfTravels = doc.DocumentNode.SelectSingleNode(“// div [@ id ='myTrips']”)。SelectNodes(“// li”);

TO:     var liOfTravels = doc.DocumentNode.SelectSingleNode(“// div [@ id ='myTrips']”)。SelectNodes(“li”);

我认为你会好的,我刚刚遇到了同样的问题并为我解决了这个问题。我不确定李是否必须是你所拥有的节点的直接孩子。