Html Agility Pack,从节点选择节点

本文关键字:节点 选择 Agility Pack Html | 更新日期: 2023-09-27 18:34:01

为什么这会在我的文档中选择我所有的<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"id获得<div>中的所有<li>元素。

Html Agility Pack,从节点选择节点

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

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

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

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

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

doc.DocumentNode.SelectNodes("//li");
some_deeper_node.SelectNodes("//li");
在某些情况下,

创建新节点可能会有所帮助,并允许您更直观地使用 xpath。我发现这在几个地方很有用。

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

您可以使用 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"));
}

我希望它有所帮助

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

无论如何,如果您更改此行,则为OP:

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

自:

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

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