Je dois collecter des informations à partir d'une page de produit sans classe ni identifiant. J'utilise htmlagilitypack et c # 4.0.
Il existe de nombreuses tables dans le code source de cette page de produit. La table de prix contient la chaîne "KDV". Je voudrais donc obtenir cette table "KDV" contenant la chaîne. Comment puis je faire ça ?
Le xpath ci-dessous sélectionnerait toutes les tables par exemple
string srxPathOfCategory = "//table";
var selectedNodes = myDoc.DocumentNode.SelectNodes(srxPathOfCategory);
Le code ci-dessous sélectionne la table mais en partant de la plupart des tables externes. Je dois sélectionner la table la plus interne qui contient cette chaîne donnée
//table[contains(., ' KDV')]
c #, xpath, htmlagilitypack
Le code ci-dessous sélectionne la table mais en partant de la plupart des tables externes. Je dois sélectionner la table la plus interne qui contient cette chaîne donnée
Utiliser :
//table
[not(descendant::table)
and
.//text()[contains(., ' KDV')]
]
Ceci sélectionne toute table
du document XML qui n'a pas de descendant de table
et qui a un descendant de nœud de texte contenant la chaîne " KDV"
.
En général, l'expression ci-dessus pourrait sélectionner de nombreux éléments de table
.
Si vous ne voulez que l'un d'entre eux sélectionné (dites le premier), utilisez cette expression XPath - remarquez les crochets :
(//table
[not(descendant::table)
and
.//text()[contains(., ' KDV')]
]
)[1]
Rappelez - vous : si vous souhaitez sélectionner le premier élément someName
du document, l’utilisation de cet élément (comme dans la réponse acceptée actuellement) est erronée:
//someName[1]
C'est la deuxième question la plus fréquemment posée dans XPath (après celle sur la sélection d'éléments avec des noms sans préfixe dans un document XML avec un espace de nom par défaut)
L'expression ci-dessus sélectionne en fait n'importe someName
élément someName
du document, qui est le premier enfant de son parent - essayez-le.
Ce comportement non intuitif s'explique par le fait que l'opérateur XPath []
a une priorité plus élevée (priorité) que le //
pseudo-opérateur.
L'expression correcte qui sélectionne réellement uniquement le premier élément someName
(dans tout document XML), s'il en existe un, est la suivante:
(//someName)[1]
Ici, les crochets sont utilisés pour remplacer explicitement la priorité de l'opérateur XPath par défaut.
Il pourrait y avoir un moyen plus efficace de le faire. Quoi qu'il en soit, ceci est le code complet que j'ai utilisé pour votre cas et qui fonctionne pour moi
HtmlDocument doc = new HtmlDocument();
string url = "http://www.pratikev.com/fractalv33/pratikEv/pages/viewProduct.jsp?pInstanceId=3138821";
using (var response = (WebRequest.Create(url).GetResponse()))
{
doc.LoadHtml(new StreamReader(response.GetResponseStream()).ReadToEnd());
}
/*There is an bug in the xpath used here. Should have been
(//table/tr/td/font[contains(.,'KDV')])[1]/ancestor::table[2]
See Dimitre's answer for an explanation and an alternative /
more generic / (needless to say) better approach */
string xpath = "//table/tr/td/font[contains(.,'KDV')][1]/ancestor::table[2]";
HtmlNode table = doc.DocumentNode.SelectSingleNode(xpath);