Html Agility Pack, SelectNodes из node

Почему это отображает все мои элементы <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.

Ответы

Ответ 1

Это немного сбивает с толку, потому что вы ожидаете, что он будет делать selectNodes только для div с id "myTrips", однако если вы сделаете другой SelectNodes ( "//li" ), он выполнит другой поиск с вершины документ.

Я исправил это, объединив инструкцию в одну, но это будет работать только на веб-странице, где у вас есть только один div с идентификатором "mytrips". Запрос будет выглядеть следующим образом:

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

Ответ 2

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

Обратите внимание на точку во второй строке. В основном в этом отношении HTMLAgitilityPack полностью полагается на синтаксис XPath, однако результат неинтуитивный, потому что эти запросы фактически одинаковы:

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

Ответ 3

Создание нового node может быть полезным в некоторых ситуациях и позволяет вам использовать xpaths более интуитивно. Я нашел это полезным в нескольких местах.

var myTripsDiv = doc.DocumentNode.SelectSingleNode("//div[@id='myTrips']");
var myTripsNode = HtmlNode.CreateNode(myTripsDiv.InnerHtml);
var liOfTravels = myTripsNode.SelectNodes("//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"));
}

Я надеюсь, что это поможет

Ответ 5

Это похоже на интуитивно понятное мне также, если вы запустите метод selectNodes для определенного node, я думал, что он будет искать материал под этим node, а не в документе вообще.

В любом случае OP, если вы измените эту строку:   var liOfTravels = doc.DocumentNode.SelectSingleNode( "//div [@id = 'myTrips']" ). SelectNodes ( "//li" );

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

Я думаю, вы будете в порядке, у меня была такая же проблема, и я исправил ее для меня. Я не уверен, хотя если бы li должен был быть прямым дочерним элементом node, который у вас есть.