XPath-получить узел без дочернего элемента определенного типа
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>
5 ответов:
может быть
*[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" />
первый / вызывает XPath, чтобы начать в корне документа, я сомневаюсь, что это то, что вы намеревались.
возможно, вы имели в виду //A[not(B)], который найдет все узлы A в документе на любом уровне, которые не имеют прямого дочернего элемента B.
или, возможно, вы уже находитесь на узле, который содержит узлы, и в этом случае вы просто хотите A[not(B)] в качестве XPath.
Если вы пытаетесь получить в любом месте иерархии от корня, это работает (для 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 нет способов достичь того же самого.
Примечание: XPaths чувствительны к регистру, поэтому, если ваши имена узлов отличаются (что я уверен, никто не будет использовать A, B), то, пожалуйста, убедитесь, что случай соответствует.