Это часто совершаемая ошибка. Никогда не используйте Оператор XPath "! =" , когда один или оба операнда имеют / устанавливаются в узлах.
value != node-set
по определению истинно, если в наборе узлов существует узел n, такой что
value
не равно string(n)
То, что вы хотите, это
value
не равен любому узлу в наборе узлов.
Это можно выразить следующим образом:
value = node-set
истина, если существует хотя бы один узел n в наборе узлов, такой что:
value = string(n)
Тогда
not(value = node-set)
имеет значение true, если в наборе узлов не существует ни одного узла n, например,
value = string(n)
Поэтому следующее выражение XPath выберет нужные узлы :
/*/*/describes[not(. = ../../*/physical/distribution/@id)
and
not(. = ../../*/implementation/distribution/@id)]
Лично я предпочел бы иметь только одно сравнение узла контекста с объединением двух наборов узлов:
/*/*/describes
[not(. = (../../*/physical/distribution/@id
|
../../*/implementation/distribution/@id
)
)
]
Пожалуйста, обратите внимание, что я избегаю использования сокращения "//" . Обычно это очень дорого (неэффективно) и должно использоваться, только если мы не знаем структуру XML-документа.
И, конечно, вышеприведенные выражения XPath должны быть сопоставлены со следующим XML-документом (второе, приведенное в вопросе):
<eml>
<datatable>
<physical>
<distribution id="100"/>
</physical>
</datatable>
<datatable>
<physical>
<distribution id="300"/>
</physical>
</datatable>
<software>
<implementation>
<distribution id="200"/>
</implementation>
</software>
<additionalMetadata>
<describes>100</describes>
<describes>200</describes>
<describes>300</describes>
<describes>400</describes>
</additionalMetadata>
</eml>