19

为什么这会选择<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");

我想要的是使用“myTrips”获取所有<li>元素。<div>id

4

5 回答 5

17

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

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

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

于 2012-05-14T13:32:01.683 回答
17
var liOfTravels = doc.DocumentNode.SelectSingleNode("//div[@id='myTrips']")
                 .SelectNodes(".//li");

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

doc.DocumentNode.SelectNodes("//li");
some_deeper_node.SelectNodes("//li");
于 2013-01-20T12:24:26.847 回答
7

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

var myTripsDiv = doc.DocumentNode.SelectSingleNode("//div[@id='myTrips']");
var myTripsNode = HtmlNode.CreateNode(myTripsDiv.InnerHtml);
var liOfTravels = myTripsNode.SelectNodes("//li");
于 2015-10-02T15:57:49.420 回答
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"));
}

我希望它有帮助

于 2012-05-14T14:28:29.340 回答
2

这对我来说似乎也违反直觉,如果您selectNodes在特定节点上运行一个方法,我认为它只会搜索该节点下的内容,而不是一般文档中的内容。

无论如何,如果你改变这一行:

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

到:

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

我想你会没事的,我刚刚遇到了同样的问题,并且为我解决了这个问题。我不确定 li 是否必须是您拥有的节点的直接子节点。

于 2012-06-12T22:53:54.673 回答