XPath - выбрать все элементы, кроме элемента (и его подэлементов) с заданным атрибутом
Я использую xinclude для включения некоторых частей документа в другой документ, например, в свой основной документ:
<document>
<xi:include href="included.xml"
xpointer = "xpointer(*//[@condition="cond1" or not(@condition)])"
xmlns:xi="http://www.w3.org/2001/XInclude" />
</document>
И мой include.xml выглядит так:
<root>
<chapter>
<section condition="cond1">
<para> Condition 1 Para </para>
</section>
<section condition="cond2">
<para> Condition 2 Para </para>
</section>
</chapter>
</root>
Мой вопрос, как я могу выбрать все, сохранив правильную структуру EXCEPT элемент с атрибутом условие ="cond2", а также ни один из его дочерних элементов? Поэтому я хочу выбрать
<root>
<chapter>
<section condition="cond1">
<para> Condition 1 Para </para>
</section>
</chapter>
</root>
У меня там не работает xpointer:
xpointer(*//[@condition="cond1" or not(@condition)])
1 ответ
Начните с исправления синтаксиса:
//*[@condition="cond1" or not(@condition)]
Затем снова посмотрите на требования: "EXCEPT элемент с атрибутом условие ="cond2"
Это было бы
//*[not(@condition="cond2")]
Теперь хитрый момент: "а также ни один из его дочерних элементов". В заголовке вопроса вы называете их "подэлементами" - я предполагаю, что вы на самом деле имеете в виду элементы-потомки на любой глубине.
Буквальный ответ
//*[not(ancestor-or-self::*[@condition="cond2"])]
Но на этом мы должны остановиться. Вы пометили этот вопрос XPath, но на самом деле это не XPath, а XPointer. В частности, речь идет о XPointer, использующем схему xpointer(), которая существует только как рабочий проект W3C от 2002 года, который так и не был завершен. Смотрите https://www.w3.org/TR/xptr-xpointer/. Итак, сначала нам нужно определить, какую реализацию XPointer вы на самом деле используете, и какой спецификации она соответствует.
И тогда нам нужно подумать о том, чего вы пытаетесь достичь с точки зрения XInclude. Я думаю, что вы пытаетесь включить не набор выбранных элементов, а целое дерево с некоторыми удаленными поддеревьями. Когда вы выбираете узел для включения в XInclude, он объединит этот узел с поддеревом, корнем которого является этот узел, независимо от того, были ли явно выбраны дочерние узлы или нет. Вы не можете использовать XInclude для преобразования дерева, которое вы включаете.
Так что это не просто проблема синтаксиса или проблема XPath. Вы в основном используете не тот инструмент для работы.