Упрощение сложной логики с помощью кванторов¶
Задача¶
Требуется проверить выполнение некоторого условия для некоторых или всех элементов последовательности.
Решение¶
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 – пустая последовательность, то это не так! А все потому, что, раз последовательность пуста, то нет ни одной пары равных значений.