parse htmlnode htmlagilitypack agility c# .net html-agility-pack

htmlagilitypack - htmlnode c#



Html Agility Pack, SelectNodes desde un nodo (5)

¿Por qué elige esto todos mis elementos <li> en mi documento?

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

Lo que quiero es obtener todos los elementos <li> en <div> con un id de "myTrips".


Crear un nuevo nodo puede ser beneficioso en algunas situaciones y le permite utilizar los xpaths de manera más intuitiva. He encontrado esto útil en un par de lugares.

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


Es un poco confuso porque espera que haga un SelectNodes solo en el div con id "myTrips", sin embargo, si hace otro SelectNodes ("// li"), realizará otra búsqueda desde la parte superior del documento.

Arreglé esto combinando la declaración en una, pero eso solo funcionaría en una página web donde solo tienes un div con un id "mytrips". La consulta se vería así:

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


Esto también me parece contrario a la intuición, si ejecuta un método selectNodes en un nodo particular, pensé que solo buscaría cosas debajo de ese nodo, no en el documento en general.

De todos modos, OP si cambias esta línea: var liOfTravels = doc.DocumentNode.SelectSingleNode ("// div [@ id = ''myTrips'']"). SelectNodes ("// li");

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

Creo que estarás bien, acabo de tener el mismo problema y eso lo solucioné. No estoy seguro si el li tendría que ser un hijo directo del nodo que tiene.


Puedes hacer esto con una consulta de 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")); }

Espero que ayude


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

Note el punto en la segunda línea. Básicamente, en este sentido, HTMLAgitilityPack se basa completamente en la sintaxis de XPath, sin embargo, el resultado no es intuitivo, porque esas consultas son efectivamente las mismas:

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