2012-05-14 115 views
15

为什么选择我的文档中的所有<li>元素?Html Agility Pack,节点中的SelectNodes

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

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

我要的是让在<div>所有<li>元素与“myTrips”的id

回答

15

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

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

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

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

我希望它能帮助

1

这似乎直觉上我藏汉,如果你跑我想到了一个特定节点上的SelectNodes方法它只会搜索该节点下的东西,而不是一般的文档。如果你改变这一行: var liOfTravels = doc.DocumentNode.SelectSingleNode(“// div [@ id ='myTrips']”)。

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

我认为你会没事的,我刚刚有同样的问题,并为我解决了它。林不知道,如果李将不得不成为你有节点的直接孩子。

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

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

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

我不认为查询是一样的。实际上,当他做第一个选择“//div [@ id ='myTrips']”当前节点改变。这就是为什么第二个选择应该是“.//li”(来自当前节点的任何地方)而不是“// li”(从根节点的任何地方)。敏捷性的确如预期的那样。 – derloopkat

+0

@derloopkat,他们**是相同的(这里没有恕我直言;如果他们不是,你可以在解决方案查询中删除点,但你不能,你能吗?)。不幸的是,HTMLAgilityPack从根目录搜索,无论你在哪个节点。恕我直言部分是这样的 - 通常关注给定节点的重点是,您继续从该节点搜索**,而不是从根节点再次搜索。在第二个子查询中没有添加点的解决方案查询根本没有意义,因此问题为什么支持它们? – greenoldman

+0

我们正在谈论不同的事情。当我说查询不一样时,我正在谈论“// li”和“。//li”。通过“那些查询”你可以参考下面的查询。 – derloopkat

5

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

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