Упрощение сложной логики с помощью кванторов¶
Задача¶
Требуется проверить выполнение некоторого условия для некоторых или всех элементов последовательности.
Решение¶
XPath 1.0¶
Если условие сводится к проверке на равенство, то достаточно семантики операторов =
и !=
в XPath 1.0 и 2.0.
Истинно, если есть ссылка хотя бы на один раздел: //section/@id = //ref/@idref
Истинно, если на каждый элемент section
ссылается хотя бы один элемент ref
: //count(//section) = count(//section[@id = //ref/@idref])
XPath 2.0¶
В XPath 2.0 того же результата можно достичь с помощью выражений some
и any
.
Истинно, если есть ссылка хотя бы на один раздел: some $id in //section/@id satisfies $id = //ref/@idref
Истинно, если на каждый элемент section
ссылается хотя бы один элемент ref
: every $id in //section/@id satisfies $id = //ref/@idref
Однако без особых усилий можно пойти гораздо дальше.
Существует раздел, который ссылается на любой раздел, кроме себя самого:
1 2 3 |
|
$sequence2
является подпоследовательностью $sequence1
:
1 2 3 4 |
|
Если удалить из этого выражения проверку count
, то оно будет означать, что по крайней мере первые count($sequence1)
элементов последовательности $sequence2
совпадают с соответствующими элементам $sequence1
.
Обсуждение¶
Семантика операторов =
, !=
, <
, >
, <=
, >=
в XPath 1.0 и 2.0 иногда приводит новичков в недоумение, если один из операндов является последовательностью или набором узлов в смысле XPath 1.0. Дело в том, что эти операторы возвращают true
, если хотя бы одна пара значений с каждой стороны удовлетворяет условию. В XPath 1.0 это бывает полезно, как мы раньше видели, но чаще заставляет чесать в затылке и мечтать о возвращении в пятый класс, где математика была ясной и понятной. Например, всякий сказал бы, что выражение $x = $x
всегда истинно, но, если $x
– пустая последовательность, то это не так! А все потому, что, раз последовательность пуста, то нет ни одной пары равных значений.