XPath для выбора нескольких тегов
учитывая этот упрощенный формат данных:
<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
s и E
s, которые являются детьми B
элементов?
в основном, что-то вроде:
a/b/(c|d|e)
в моей ситуации, а не просто a/b/
, запрос, ведущий к выбору тех C
,D
,E
узлы на самом деле довольно сложны, поэтому я хотел бы избежать этого:
a/b/c|a/b/d|a/b/e
это возможно?
4 ответа:
один правильный ответ:
/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']
вопреки антагонистическому мнению Дмитрия, вышесказанное некорректно в вакууме, где OP не указал взаимодействие с пространствами имен. Элемент
self::
axis является ограничителем пространства имен,local-name()
нет. Если намерение ОП состоит в том, чтобы захватитьc|d|e
независимо от пространства имен (которое я бы предложил даже вероятный сценарий, учитывая или характер проблемы), то это " другой ответ это все еще имеет некоторые положительные голоса", что неверно.вы не можете быть окончательным без определения, хотя я очень рад удалить свой ответ как действительно неправильный, если OP уточняет свой вопрос таким образом, что я ошибаюсь.
почему бы и нет
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>>)