1
votes

I'm looking for the right xpath expression to select all nodes whose nearest ancestor have the proper attribute value, and not to select those whose nearest ancestor have an explicit 'don't select' attribute value. Visually explained: for each branch, follow its path to the root, and the first time a certain attribute is encountered should decide if it is in the selection or not.

<xyz select="yes">
    <blabla>this one's in</blabla>
    <qwerty select="no">this one's out
        <foobar>out please!</foobar>
        <gettingoutofnames select="yes">in again!</gettingoutofnames>
    </qwerty>
</xyz>

Example can occur anywhere in the XML structure.

Names of elements can be anything. 'select="yes"' and 'select="no"' can follow in any order, but the deepest one is decisive its descendants.

I'm thinking something like this:

//*[@select="yes"]//ancestor::*[not(@select="no")]

but that doesn't catch it all. Any help is appreciated!

2

2 Answers

1
votes

I think the following should work:

//*[ancestor::*[@select][1]/@select='yes']

To break it down: ancestor::*[@select][1] is the nearest ancestor with a select attribute. So we choose only those nodes for which the nearest ancestor with a select attribute has this attribute set to 'yes'. You have to replace ancestor with ancestor-or-self if you also want to include the nodes the have a select="yes" attribute (xyz and gettingoutofnames in your example).

0
votes

For selecting a value

cat //*[contains(@select,'yes')]

For selecting the negate results

cat //*[not(contains(@select,'yes'))]

Hope you'll figure out the catch for your problem