Rise_against
Rise_against

Reputation: 1060

XML & XPath expression

Say I have this XML:

<root>
    <A></A>
    <B></B>
    <C>one</C>
    <C>two</C>
    <C>three</C>
    <D></D>
</root>

Now I want to get all nodes, except for The C nodes 'two' and 'three'. Now I want to choose which C node can stay by index.

So this is the xpath that I already have:

 //*[not(ancestor-or-self::C)]

But this removes all C nodes, so now I have to add an index to which C node I want to stay

//*[not(ancestor-or-self::C)] exept for C[1]

How can I accomplsh this so my output would be if I select index 1:

<root>
   <A></A>
   <B></B>
   <C>one</C>
   <D></D>
</root>

Or if I select index 2:

<root>
   <A></A>
   <B></B>
   <C>two</C>
   <D></D>
</root>

Hope I made myself clear enough :p thx

Upvotes: 1

Views: 230

Answers (3)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243459

Use:

//*[not(self::c and not(count(preceding-sibling::c) = $ind - 1))]

where $ind is the wanted position (1-based) of the c element you want to select.

Upvotes: 0

user357812
user357812

Reputation:

Why except? You have any element but those, then you add some of those:

//*[not(ancestor-or-self::C)]|//C[1]/descendant-or-self::*

Upvotes: 1

Niko
Niko

Reputation: 6269

i think it depends on what you define as "index". If you define "index" as the C that has n-1 C siblings then you can just do:

to display one the first (get rid of all afterwards

/root/*[not(name() = 'C'  and count(preceding::C) >= 1)]

to display only the second

/root/*[not(name() = 'C' and (count(preceding::C) < 1 or count(preceding::C) > 1))]

(I tested this with: http://www.xmlme.com/XpathTool.aspx just fyi )

Upvotes: 1

Related Questions