С одной стороны, в языке XPath используются знакомые каждому программисту операторы сравнения «равно», «не равно», «меньше», «больше» и другие. С другой стороны, эти операторы умеют работать не только с примитивными типами, но и с целыми наборами узлов. Незнание правил сравнения наборов узлов может привести к некоторым сюрпризам.
Попробуйте быстро ответить на вопрос, чему равно следующее выражение:
Если ваш ответ —
Простая задача: проверить, равен ли атрибут
При решении обратной задачи довольно часто можно увидеть следующий код:
В большинстве случаев этот код работает так, как ожидается. Однако в случае, когда атрибут
Правильное решение задачи:
Что в переводе на русский означает: не существует ни одного атрибута
Возьмём следующий документ:
Применим различные сочетания операторов равенства, неравенства и отрицания:
Как видите, возможна ситуация, когда выражение
При сравнении двух узлов они приводятся к строке. Как быть, если нужно проверить не совпадение строкового представления, а идентичность? Другими словами, необходимо установить, что два проверяемых узла суть один и тот же узел. Такая задача, например, встречается в группировке Мюнха.
Первое решение — на чистом XPath:
В данном выражении используется свойство оператора объединения, заключающееся в том, что один и тот же узел не может войти в результат операции дважды. Если в итоге получен единственный узел, значит, исходные узлы идентичны.
Второе решение использует XSLT-функцию generate-id:
Данная функция по определению возвращает одинаковый результат для одного и того же узла. Если результаты работы функции равны, значит, исходные узлы идентичны.
Комментарии и дополнения приветствуются.
Попробуйте быстро ответить на вопрос, чему равно следующее выражение:
foo = 'bar' and foo != 'bar'Если ваш ответ —
false, автор предлагает читать дальше.Сравнение узла со строкой
Простая задача: проверить, равен ли атрибут
foo строке 'bar':@foo = 'bar'При решении обратной задачи довольно часто можно увидеть следующий код:
@foo != 'bar'В большинстве случаев этот код работает так, как ожидается. Однако в случае, когда атрибут
foo отсутствует, данное выраж��ние возвращает false. Если внимательно прочесть документацию и перевести @foo != 'bar' на русский язык, получится следующее: существует хотя бы один атрибут foo, который не равен 'bar'. При отсутствии атрибута foo условие не выполняется, отсюда false.Правильное решение задачи:
not(@foo = 'bar')Что в переводе на русский означает: не существует ни одного атрибута
foo, равного 'bar'.Сравнение набора узлов со строкой
Возьмём следующий документ:
<list>
<item>foo</item>
<item>bar</item>
<item>baz</item>
</list>Применим различные сочетания операторов равенства, неравенства и отрицания:
| Выражение | Перевод | Результат |
|---|---|---|
item = 'foo' |
Есть хотя бы один элемент, равный 'foo'. |
true |
item != 'bar' |
Есть хотя бы один элемент, не равный 'bar'. |
true |
not(item = 'foo') |
Нет ни одного элемента, равного 'foo'. |
false |
not(item != 'baz') |
Все имеющиеся элементы равны 'baz'. |
false |
item = 'foo' and item != 'foo' возвращает true.Проверка идентичности узлов
При сравнении двух узлов они приводятся к строке. Как быть, если нужно проверить не совпадение строкового представления, а идентичность? Другими словами, необходимо установить, что два проверяемых узла суть один и тот же узел. Такая задача, например, встречается в группировке Мюнха.
Первое решение — на чистом XPath:
count($foo | $bar) = 1В данном выражении используется свойство оператора объединения, заключающееся в том, что один и тот же узел не может войти в результат операции дважды. Если в итоге получен единственный узел, значит, исходные узлы идентичны.
Второе решение использует XSLT-функцию generate-id:
generate-id($foo) = generate-id($bar)Данная функция по определению возвращает одинаковый результат для одного и того же узла. Если результаты работы функции равны, значит, исходные узлы идентичны.
Комментарии и дополнения приветствуются.