Оператор XPath "! =".Как это работает? - PullRequest
29 голосов
/ 07 января 2011

XML-документ:

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

    <B>     
        <Node/>
    </B>  

    <C>
    </C>

    <D/>
</doc>

Как бы вы оценили следующие запросы XPath?

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

Я бы ожидал, что ALL из них оценивается как true .

Однако, вот результаты:

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

Это ожидаемое поведение? Или это ошибка моего провайдера XPath (jaxen)?

Ответы [ 2 ]

56 голосов
/ 07 января 2011

Рекомендация : Никогда не используйте оператор != для сравнения неравенства, где один или оба аргумента являются наборами узлов.

По определению выражение :

$node-set != $value

вычисляется как true() точно, когда в $node-set есть хотя бы один узел, так что его строковое значение не равно строковому значению $value.

Используя это определение :

$empty-nodeset != $value 

всегда равно false(), поскольку в $empty-nodeset нет ни одного узла, для которого выполняется неравенство.

Решение

Используйте

not($node-set = $value)

Тогда вы получите все результаты true(), как хотели .

1 голос
/ 07 января 2011

Из спецификации XPath :

Если один объект для сравнения является набором узлов, а другой является строкой, то сравнение будет истинным, если и только если в наборе узлов есть узел, так что результат выполнения сравнения на строковое значение узла, а другая строка - true.

Это означает, что если набор узлов пуст (как в ваших случаях C и D), результат логического выражения будет ложным, поскольку нет узла, к которому может применяться неравенство.

Вы можете обойти это поведение и получить желаемый результат, используя выражение вроде:

count(/doc/C/Node) = 0 or /doc/C/Node != 'abcd'
...