Учитывая этот упрощенный формат данных:
<a>
<b>
<c>C1</c>
<d>D1</d>
<e>E1</e>
<f>don't select this one</f>
</b>
<b>
<c>C2</c>
<d>D2</d>
<e>E1</e>
<g>don't select me</g>
</b>
<c>not this one</c>
<d>nor this one</d>
<e>definitely not this one</e>
</a>
Как вы выберете все C
s, D
и E
, которые являются дочерними элементами B
?
В принципе, что-то вроде:
a/b/(c|d|e)
В моей собственной ситуации вместо простого a/b/
запрос, вызывающий выбор узлов C
, D
, E
, на самом деле довольно сложный, поэтому я хотел бы избежать этого:
a/b/c|a/b/d|a/b/e
Возможно ли это?
Один правильный ответ:
/a/b/*[self::c or self::d or self::e]
Обратите внимание, что это
a/b/*[local-name()='c' or local-name()='d' or local-name()='e']
является слишком длинным и неправильным. Это выражение XPath будет выбирать узлы, такие как:
OhMy:c
NotWanted:d
QuiteDifferent:e
Вместо этого вы можете избежать повторения с помощью теста атрибута:
a/b/*[local-name()='c' or local-name()='d' or local-name()='e']
В отличие от антагонистического мнения Димитрия, вышесказанное не является ошибочным в вакууме, где ОП не задает взаимодействия с пространствами имен. Ось self::
ограничивает пространство имен, local-name()
- нет. Если намерение OP состоит в том, чтобы захватить c|d|e
независимо от пространства имен (которое я бы предположил, это даже вероятный сценарий, учитывая характер OR проблемы), то это "еще один ответ, который все еще имеет положительные голоса", что неверно.
Вы не можете быть окончательными без определения, хотя я вполне счастлив удалить свой ответ как действительно неверный, если ОП разъяснит свой вопрос таким образом, что я ошибаюсь.
Почему бы не a/b/(c|d|e)
? Я просто попробовал саксоновскую XML-библиотеку (хорошо обернулся с некоторой добротой Clojure), и, похоже, она работает.
abc.xml
- это документ, описанный OP.
(require '[saxon :as xml])
(def abc-doc (xml/compile-xml (slurp "abc.xml")))
(xml/query "a/b/(c|d|e)" abc-doc)
=> (#<XdmNode <c>C1</c>>
#<XdmNode <d>D1</d>>
#<XdmNode <e>E1</e>>
#<XdmNode <c>C2</c>>
#<XdmNode <d>D2</d>>
#<XdmNode <e>E1</e>>)
Не уверен, что это поможет, но с XSL я бы сделал что-то вроде:
<xsl:for-each select="a/b">
<xsl:value-of select="c"/>
<xsl:value-of select="d"/>
<xsl:value-of select="e"/>
</xsl:for-each>
и не будет ли этот XPath выбирать всех дочерних узлов B-узлов:
a/b/*
or
является логическим оператором - он работает с двумя логическими значениями. Оператор объединения XPath|
работает на двух наборах узлов. Они совершенно разные, и для каждого из них существуют конкретные варианты использования. Использование|
может решить исходную проблему, но это приводит к более длинному и сложному пониманию выражения XPath. Более простое выражение в этом ответе, использующее операторor
создает требуемый набор узлов и может быть указано в атрибуте «select» операции XSLT<xsl:for-each>
. Просто попробуйте.