web-dev-qa-db-fra.com

Opérateur XPath "! =". Comment ça marche?

Document XML:

<doc>
    <A>   
        <Node>Hello!</Node>   
    </A> 

    <B>     
        <Node/>
    </B>  

    <C>
    </C>

    <D/>
</doc>

Comment évalueriez-vous les requêtes XPath suivantes?

/doc/A/Node != 'abcd'  
/doc/B/Node != 'abcd'  
/doc/C/Node != 'abcd'  
/doc/D/Node != 'abcd'  

Je m'attendrais à [~ # ~] tous [~ # ~] à évaluer à vrai.

Voici cependant les résultats:

/doc/A/Node != 'abcd'     true
/doc/B/Node != 'abcd'     true
/doc/C/Node != 'abcd'     false
/doc/D/Node != 'abcd'     false

Est-ce un comportement attendu? Ou est-ce un bug avec mon fournisseur XPath (jaxen)?

32
Keith

Recommandation : n'utilisez jamais l'opérateur != Pour comparer l'inégalité lorsqu'un ou les deux arguments sont des ensembles de nœuds.

Par définition l'expression :

$node-set != $value

correspond à true() exactement quand il y a au moins un nœud dans $node-set de sorte que sa valeur de chaîne n'est pas égale à la valeur de chaîne de $value.

En utilisant cette définition :

$empty-nodeset != $value 

est toujours false(), car il n'y a même pas un seul nœud dans $empty-nodeset pour lequel l'inégalité se maintient.

Solution :

Utilisez :

not($node-set = $value)

Ensuite, vous obtenez tous les résultats true(), comme souhaité .

57
Dimitre Novatchev

De la XPath spec :

Si un objet à comparer est un ensemble de nœuds et l'autre une chaîne, alors la comparaison sera vraie si et seulement s'il y a un nœud dans l'ensemble de nœuds de telle sorte que le résultat de la comparaison sur la valeur de chaîne du nœud et l'autre chaîne est vraie.

Cela signifie que si l'ensemble de nœuds est vide (comme dans vos cas C et D), le résultat de l'expression booléenne sera faux, car il n'y a pas de nœud auquel l'inégalité peut s'appliquer.

Vous pouvez contourner ce problème et obtenir le résultat souhaité en utilisant une expression comme:

count(/doc/C/Node) = 0 or /doc/C/Node != 'abcd'
1
Greg Hewgill