XPath - получите node без дочернего элемента определенного типа
XML: /A/B
или /A
Я хочу получить все узлы A
, у которых нет дочерних B
.
Я пробовал
/A[not(B)]
/A[not(exists(B))]
без успеха
Я предпочитаю решение с синтаксисом /*[local-name()="A" and .... ]
, если это возможно. Любые идеи, которые работают?
Разъяснение. Xml выглядит так:
<WhatEver>
<A>
<B></B>
</A>
</WhatEver>
или
<WhatEver>
<A></A>
</WhatEver>
Ответы
Ответ 1
Может быть,
*[local-name() = 'A' and not(descendant::*[local-name() = 'B'])]
?
Кроме того, должен быть только один корневой элемент, поэтому для /A[...]
вы либо получаете весь свой XML обратно, либо нет. Может быть, //A[not(B)]
или /*/A[not(B)]
?
Я действительно не понимаю, почему /A[not(B)]
не работает для вас.
~/xml% xmllint ab.xml
<?xml version="1.0"?>
<root>
<A id="1">
<B/>
</A>
<A id="2">
</A>
<A id="3">
<B/>
<B/>
</A>
<A id="4"/>
</root>
~/xml% xpath ab.xml '/root/A[not(B)]'
Found 2 nodes:
-- NODE --
<A id="2">
</A>
-- NODE --
<A id="4" />
Ответ 2
Попробуйте выполнить "/A[not(.//B)]"
или "/A[not(./B)]"
.
Ответ 3
Первый/заставляет XPath начинаться с корня документа, я сомневаюсь, что это то, что вы намеревались.
Возможно, вы имели в виду //A [not (B)], который нашел бы все узлы A в документе на любом уровне, не имеющем прямого B-ребенка.
Или, возможно, вы уже находитесь в node, который содержит узлы A, в этом случае вам просто нужен A [not (B)] как XPath.
Ответ 4
Если вы пытаетесь получить A в любом месте иерархии от корня, это работает (для xslt 1.0, а также 2.0 в случае его использования в xslt)
//descendant-or-self::node()[local-name(.) = 'a' and not(count(b))]
ИЛИ вы также можете сделать
//descendant-or-self::node()[local-name(.) = 'a' and not(b)]
ИЛИ также
//descendant-or-self::node()[local-name(.) = 'a' and not(child::b)]
В xslt нет n путей для достижения того же.
Примечание. XPaths чувствительны к регистру, поэтому, если ваши имена node различны (что я уверен, никто не будет использовать A, B), тогда, пожалуйста, убедитесь, что случай соответствует.
Ответ 5
Используйте это:
/*[local-name()='A' and not(descendant::*[local-name()='B'])]