Как выполнять заданные операции в XPath 1.0

Я видел в SO и других местах, что должно работать следующее (этот пример снят непосредственно из Cookbook от O'Reilly XSLT):

(: intersection :)
$set1[count(. | $set2) = count($set2)]

(: difference :)
$set1[count(. | $set2) != count($set2)]

и похоже, что все должно быть ОК, однако это, похоже, терпит неудачу при использовании с реальными путями, а не с переменными. Например, учитывая следующий документ

<a>
  <new>
    <val>1</val>
    <val>2</val>
  </new>
  <old>
    <val>2</val>
    <val>3</val>
  </old>
</a>

и выражение XPath /a/new/val[count(. | /a/old/val)=count(/a/old/val)]/text() Я ожидаю получить node -set { 2 }, но вместо этого получаю { 1 2 }. Любые идеи, что я делаю неправильно?

Ответ 1

Формулы для пересечения node -set используют node -тождество, а не значение.

Два узла идентичны тогда и только тогда, когда count($n1|$n2) =1

Однако вы хотите пересечься на основе идентификатора значения.

Решение

Использование

/a/new/val[. = /a/old/val]

это выбирает любой /a/new/val, для которого существует хотя бы один элемент /a/old/val, так что строковые значения этих двух элементов одинаковы.

Ответ 2

Примечание, что пересечение всегда приводит к одному набору node, составленному узлами в общем между двумя исходными наборами узлов.

Также отметить, что два узла с одинаковым именем и содержимым должны рассматриваться как два различных узла. Таким образом, /a/new/val/text() и /a/old/val/text() имеют одинаковое значение, но они являются полностью различными текстовыми узлами.

Таким образом, ваше текущее пересечение:

/a/new/val[count(. | /a/old/val)=count(/a/old/val)]

должен вычисляться до пустого node -set, потому что вы пересекаете два набора узлов без какого-либо node общего (операция count() никогда не будет соответствовать). Вы делаете что-то вроде этого:

/a/new/val/a/old/val= ∅

While /a/new/a/old/preceding::new will produce new.