2017-10-02 19 views
-1

Par exemple, ce HTMLPourquoi ce Xpath ne fonctionne pas?

<div> 
    <span></span> I want to find this <b>this works ok</b>. 
</div> 

Je veux trouver un DIV avec I want to find this en elle puis saisir tout le texte à l'intérieur que DIV, y compris les éléments enfants

Mon XPATH, //*[contains(text(), 'I want to find this')] ne fonctionne pas du tout.

Si je fais ce //*[contains(text(), 'this works')] cela fonctionne, mais je veux trouver DIV basé sur I want to find this texte

Cependant, si je retire le <span></span> de ce HTML, cela fonctionne, pourquoi est-ce?

+0

titre de mise à jour comme * "Pourquoi ce Xpath ne fonctionne pas ? "* n'est pas informatif du tout. Notez également que '// * [contains (text(), 'this works')]' ne fonctionne pas réellement. Il peut uniquement renvoyer 'b', mais pas' div' – Andersson

+0

Copie possible de [Test text() nœuds vs valeurs de chaînes dans XPath] (https://stackoverflow.com/questions/34593753/testing-text-nodes-vs- string-values-in-xpath) – kjhughes

+0

@ Umair, Si vous aimez avoir une solution en utilisant css selector alors il y en a une pour ce job. – SIM

Répondre

0

Essayez d'utiliser // * [texte() = « Je veux trouver ce »], cela sélectionnera la balise div et pour le texte, vous pouvez utiliser la méthode getText() pour obtenir le texte

+0

Cela vérifie le texte exact, je veux vérifier si un DIV contient ce texte, parce que dans mon cas, il peut y avoir une longue chaîne comme «Je veux trouver ce bla bla» aussi, dans Dans ce cas, votre réponse ne fonctionnera pas – Umair

2

text() obtient seulement le texte avant le premier élément interne. Vous pouvez le remplacer par . pour utiliser le nœud actuel à rechercher.

//div[contains(., 'I want to find this')] 

Ceci recherchera dans une concaténation de chaîne de tous les nœuds de texte à l'intérieur du nœud courant.

Pour saisir tout le texte que vous pouvez utiliser node.itertext() pour itérer tous les textes internes si vous utilisez lxml:

from lxml import etree 

html = """ 
<div> 
    <span></span> I want to find this <b>this works ok</b>. 
</div> 
""" 

root = etree.fromstring(html, etree.HTMLParser()) 
for div in root.xpath('//div[contains(., "I want to find this")]'): 
    print(''.join([x for x in div.itertext()])) 
# => I want to find this this works ok. 
+1

Avertissement: il n'est pas tout à fait vrai que text() n'obtient que le premier nœud de texte. Plutôt, sous XPath 1.0, la fonction contains() ignore tout sauf le premier noeud de l'argument fourni. Sous XPath 2.0, la fonction contains() renvoie une erreur si le premier argument est une liste contenant plus d'un élément. Mais la solution est correcte pour toutes les versions XPath. –

+1

Et notez le principe général: 95% du temps où les gens écrivent 'text()', ils devraient écrire '.' à la place. –

0

Vous pouvez Replace text() with string():

//div[contains(string(), " I want to find this")] 
Or, you can check that span's following text sibling contains the text: 

//div[contains(span/following-sibling::text(), " I want to find this")]