Перейти к содержанию

Упрощение сложной логики с помощью кванторов

Задача

Требуется проверить выполнение некоторого условия для некоторых или всех элементов последовательности.

Решение

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

Однако без особых усилий можно пойти гораздо дальше.

Существует раздел, который ссылается на любой раздел, кроме себя самого:

some $s in //section satisfies
every $id in //section[@id ne $s/@id]/@id satisfies
$id = $s/ref/@idref

$sequence2 является подпоследовательностью $sequence1:

count($sequence2) <= count($sequence1) and
every $pos in 1 to count($sequence1),
$item in $sequence1[$pos],
$item in $sequence2[$pos] satisfies $item1 = $item2

Если удалить из этого выражения проверку count, то оно будет означать, что по крайней мере первые count($sequence1) элементов последовательности $sequence2 совпадают с соответствующими элементам $sequence1.

Обсуждение

Семантика операторов =, !=, <, >, <=, >= в XPath 1.0 и 2.0 иногда приводит новичков в недоумение, если один из операндов является последовательностью или набором узлов в смысле XPath 1.0. Дело в том, что эти операторы возвращают true, если хотя бы одна пара значений с каждой стороны удовлетворяет условию. В XPath 1.0 это бывает полезно, как мы раньше видели, но чаще заставляет чесать в затылке и мечтать о возвращении в пятый класс, где математика была ясной и понятной. Например, всякий сказал бы, что выражение $x = $x всегда истинно, но, если $x – пустая последовательность, то это не так! А все потому, что, раз последовательность пуста, то нет ни одной пары равных значений.