2010-04-20 9 views
9

Comment utiliser quelque chose de similaire à l'exemple ci-dessous, mais avec le résultat inverse, c'est-à-dire les éléments qui ne contiennent pas (default) dans le texte.Comment construire un xpath pour sélectionner des éléments qui ne contiennent pas de chaîne

<test> 
    <item>Some text (default)</item> 
    <item>Some more text</item> 
    <item>Even more text</item> 
</test> 

Donné ce

//test/item[contains(text(), '(default)')] 

retourneraient le premier élément. Y at-il un opérateur non que je peux utiliser avec contient?

Répondre

17

Oui, il y a:

//test/item[not(contains(text(), '(default)'))]

Astuce: not() est une fonction XPath au lieu d'un opérateur.


Une alternative, peut-être meilleure façon d'exprimer c'est:

//test/item[not(text()[contains(., '(default)')])]

Il y a une différence subtile mais importante entre les deux expressions (appelons-les A et B, respectivement).

Cas simple: Si tous les <item> ne possèdent qu'un seul nœud de noeud enfant, A et B se comportent tous deux de la même manière.

cas complexe: Si <item> peut avoir plusieurs enfants noeud texte, l'expression A correspond uniquement lorsque '(default)' se produit dans le premier d'entre eux. Ceci est dû au fait que text() correspond à tous les enfants de nœud de texte et produit un ensemble de nœuds. Jusqu'à présent, pas de surprise. Maintenant, accepte un ensemble de nœuds comme premier argument, mais il doit le convertir en chaîne pour faire son travail. Et la conversion d'un ensemble de nœuds en une chaîne ne produit que la valeur de chaîne du premier nœud de l'ensemble, tous les autres nœuds sont ignorés (essayez string(//item) pour voir ce que je veux dire). Dans le cas simple, c'est exactement ce qui se passe aussi, mais le résultat n'est pas aussi surprenant. L'expression B traite de ceci en vérifiant explicitement chaque noeud de texte individuellement au lieu de vérifier seulement la valeur de chaîne de l'élément entier <item>. C'est donc le plus robuste des deux.

Questions connexes