Операции над множествами¶
Задача¶
Требуется обработать последовательность, как если бы она была математическим множеством.
Решение¶
XPath 1.0¶
Операция объединения (|
) наборов узлов поддерживается и в XPath 1.0, но, чтобы вычислить пересечение или разность, придется проявить изобретательность.
объединение: $set1 | $set2
пересечение: $set1[count(. | $set2) = count($set2)]
разность: $set1[count(. | $set2) != count($set2)]
XPath 2.0¶
Оператор |
остался и в версии XPath 2.0, но добавился еще синоним для него union
. Также появились операторы intersect
и except
, вычисляющие пересечение и разность соответственно.
Объединение: $set1 union $set2
пересечение: $set1 intersect $set2
разность: $set1 except $set2
Обсуждение¶
В XPath 2.0 наборы узлов заменены последовательностями. Они, в отличие от наборов узлов, упорядочены и могут содержать дубликаты. Однако в случае применения к ним теоретикомножественных операций дубликаты устраняются, а порядок игнорируется, так что последовательности ведут себя как обычные множества. Результат операции никогда не содержит дубликатов, даже если в исходных последовательностях они были.
Оператор except идиоматически используется в XPath 2.0 для отбора всех атрибутов, кроме входящих в заданное множество:
Все атрибуты, кроме @a
: @a* except @a
Все атрибуты, кроме @a
и @b
: @a* except @a, @b
В версии 1.0 решение будет более громоздким:
1 |
|
Интересно, что в XPath теоретикомножественные операции разрешены только над последовательностями узлов, а к атомарным значениям неприменимы. Связано это с тем, что операции выполняются над идентификаторами узлов, а не над значениями. Имитировать операции над значениями в XPath 2.0 можно с помощью показанных ниже выражений. В XPath 1.0 для этого потребуется рекурсия.
объединение: distinct-values( ($items1, $items2) )
пересечение: distinct-values( ($items1[. = $items2] )
разность: distinct-values( ($items1[not(. = $items2)] )