web-dev-qa-db-fra.com

Html Agility Pack, SelectNodes à partir d'un nœud

Pourquoi cela sélectionne-t-il tous mes éléments <li> dans mon document?

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

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

Ce que je veux, c'est obtenir tous les éléments <li> dans le <div> avec une id de "myTrips".

16
thatsIT

C'est un peu déroutant parce que vous vous attendez à ce qu'il fasse un selectNodes uniquement sur le div portant l'id "myTrips". Toutefois, si vous faites un autre SelectNodes ("// li"), il effectuera une autre recherche à partir du haut du document.

J'ai corrigé cela en combinant la déclaration en une seule déclaration, mais cela ne fonctionnerait que sur une page Web contenant un seul div portant un identifiant "mytrips". La requête ressemblerait à ceci:

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

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

Notez le point dans la deuxième ligne. À cet égard, HTMLAgitilityPack repose entièrement sur la syntaxe XPath, mais le résultat n’est pas intuitif, car ces requêtes sont en réalité les mêmes:

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

La création d'un nouveau nœud peut être bénéfique dans certaines situations et vous permet d'utiliser les xpath de manière plus intuitive. J'ai trouvé cela utile dans quelques endroits. 

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

Vous pouvez le faire avec une requête 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"));
}

J'espère que ça aide

4
vfportero

Cela me semble aussi contre-intuitif, si vous exécutez une méthode selectNodes sur un nœud particulier, je pensais que cela ne ferait que rechercher des éléments situés sous ce nœud, pas dans le document en général.

Quoi qu'il en soit OP si vous modifiez cette ligne: var liOfTravels = doc.DocumentNode.SelectSingleNode ("// div [@ id = 'myTrips']"). SelectNodes ("// li");

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

Je pense que ça va aller, je viens d'avoir le même problème et cela a résolu le problème pour moi. Je ne sais pas si le li doit être un enfant direct du noeud que vous avez.

1
Paul