Reputation: 6557
I have a batch of xmls where each tag has an attribute isOptional. An example of such xml is
<node1 isOptional="False">
<node2 isOptional="True">
<node22 isOptional="False">
<node3 isOptional="False">text4</node3>
</node22>
</node2>
<node4 isOptional="False">
<node5 isOptional="False">
<node6 isOptional="True">text3</node6>
<node7 isOptional="False">
<node8 isOptional="True">text2</node8>
<node9 isOptional="False">text1</node9>
</node7>
</node5>
</node4>
</node1>
I need to write xpath to select all leaf nodes which do not have ancessors with @isOptional="True"
. For this example the result should be:
<node9 isOptional="False">text1</node9>
Actually I need something like this:
//*[not(*) and @isOptional="False" and count(ancestor::*[@isOptional = "True"] = 0)]
Could you please help me to get the correct xpath?
Upvotes: 0
Views: 504
Reputation: 22617
I think you forgot to mention one additional requirement. What you said:
I need to write xpath to select all leaf nodes which do not have ancessors with
@isOptional="True"
would map to the following XPath expression:
//*[not(*) and not(ancestor::*[@isOptional = 'True'])]
^^^ "all"
^^^^^^^ "leaf nodes"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "no ancestor where
@isOptional equals 'True'"
which would yield (individual results separated by ------
):
<node6 isOptional="True">text3</node6>
-----------------------
<node8 isOptional="True">text2</node8>
-----------------------
<node9 isOptional="False">text1</node9>
But I assume you meant to add: Additionally, the isOptional
attribute of the target nodes must not be set to True
either. This results in the following path expression, already correctly suggested by potame:
//*[not(*) and not(ancestor-or-self::*[@isOptional = 'True'])]
and the only result is
<node9 isOptional="False">text1</node9>
because now the XPath expression contains the ancestor-or-self::
axis, which includes the context node itself.
Upvotes: 1
Reputation: 7905
An XPath like this one should work:
//*[not(child::*) and not(ancestor-or-self::*[@isOptional = 'True'])]
Upvotes: 1