tags:

views:

29

answers:

2

His,

I think I've got a tricky questions for XPath experts. There is a node structure like this:

A(1)-|
     |-B(1)
     |-B(2)
     |-B(3)
A(2)-|
     |-B(2.1)
     |-B(2.2)
     |-B(2.3)
...

How to, with a single XPath-expression, extract only the following nodes

A(1)-|
     |-B(2)
     |-B(3)
A(2)-|
     |-B(2.2)
     |-B(2.3)
...

That is for every parent node its first child element should be excluded.

I tried A/B[position() != 1] but this would filter out only B(1.1) and select B(2.1).

Thanks

+2  A: 

Tricky. You could select nodes that have preceding siblings:

A/B[preceding-sibling::*]

This will fail for the first element and succeed for the rest.

John Kugelman
You beat me to it by five seconds.
Welbog
Thanks. I tried it out too. Somehow it doesn't work on xalan i am using. Actually, according to results i've got at http://www.futurelab.ch/xmlkurs/xpath.en.html, the solution with position() != 1 should work as well, but it doesn't on my system. Are there any particularities that one should keep in mind using xalan (2.7.1)?
d56
Thanks. That was my mistake. Both solutions work (preceding-sibling::* and position()=1]
d56
+1  A: 

This XPath expression (no preceding-sibling:: axis used):

/*/a/*[not(position()=1)]

when applied on this XML document:

<t>
 <a>
   <b11/>
   <b12/>
   <b13/>
 </a>
 <a>
   <b21/>
   <b22/>
   <b23/>
 </a>
</t>

selects the wanted nodes:

<b12 />
<b13 />
<b22 />
<b23 />

This can be verified with this XSLT transformation, producing the above result:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:copy-of select="/*/a/*[not(position()=1)]"/>
 </xsl:template>
</xsl:stylesheet>
Dimitre Novatchev
Thanks. That was my mistake. Both solutions work (preceding-sibling::* and position()=1]
d56