Reputation: 155
I was selecting all attributes id
and everything was going nicely then one day requirements changed and now I have to select all except one!
Given the following example:
<root>
<structs id="123">
<struct>
<comp>
<data id="asd"/>
</comp>
</struct>
</structs>
</root>
I want to select all attributes id
except the one at /root/structs/struct/comp/data
Please note that the Xml could be different.
Meaning, what I really want is: given any Xml tree, I want to select all attributes id
except the one on element /root/structs/struct/comp/data
I tried the following:
//@id[not(ancestor::struct)]
It kinda worked but I want to provide a full xpath to the ancestor axis which I couldn't
//@id[not(contains(name(), 'data'))]
It didn't work because name selector returns the name of the underlying node which is the attribute not its parent element
Upvotes: 0
Views: 537
Reputation: 101680
The following should achieve what you're describing:
//@id[not(parent::data/parent::comp/parent::struct/parent::structs/parent::root)]
As you can see, it simply checks from bottom to top whether the id
attribute's parent matches the path root/structs/struct/comp/data
.
I think this should be sufficient for your needs, but it does not 100% ensure that the parent is at the path /root/structs/struct/comp/data
because it could be, for example, at the path /someOtherHigherRoot/root/structs/struct/comp/data
. I'm guessing that's not a possible scenario in your XML structure, but if you had to check for that, you could do this:
//@id[not(parent::data/parent::comp/parent::struct/parent::structs/parent::root[not(parent::*)])]
Upvotes: 1