Mr.Pleasant
Mr.Pleasant

Reputation: 13

xpath to let the nearest ancestor's attribute value decides if it's in or not

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!

Upvotes: 1

Views: 2732

Answers (2)

nwellnhof
nwellnhof

Reputation: 33648

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).

Upvotes: 1

Antarus
Antarus

Reputation: 1621

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

Upvotes: 0

Related Questions