views:

220

answers:

4

Hello,

What I'm trying to do is fairly simple, but I can't find the way to. I just want to iterate over the children of a node excluding the first child.

For instance, in this XML snippet, I would want all the <bar> elements, except the first one:

<foo>
    <Bar>Example</Bar>
    <Bar>This is an example</Bar>
    <Bar>Another example</Bar>
    <Bar>Bar</Bar>
</foo>

There is no common attribute by which I can filter (like an id tag or something similar).

Any suggestions?

+3  A: 

You can always use position together with xsl:when.

<xsl:when test="node[position() > 1]">
  <!-- Do my stuff -->
</xsl:when>
Oded
... and I feel like a n00b. `<for-each select="foo/Bar[position() > 1]">` Thank you.
zneak
@zneak - we were all there... too many things to keep in our brain in the same time.
Oded
`node.position() != 1` is not a syntactically-correct XPath expression.
Dimitre Novatchev
@Dimitre Novatchev - good eyes! Answer corrected.
Oded
The answer still contains a syntactically incorrect XPath expression! Why don't you try to run the code and to post only correct code?
Dimitre Novatchev
@Dimitre Novatchev - I was giving an example, not copy/paste code.
Oded
Examples need to be correct in order to be useful. I never reply with untested code.
Dimitre Novatchev
@Dimitre Novatchev: to be honest and as my first comment can testimony, he was the first to answer and I understood what he meant right away. For the rest of the world, yeah, working code is useful, but my requirements weren't even that high.
zneak
@zneak: that's good, but this code is seen by anybody and people will just copy it and try to use it and only then will understand it is not even syntactically correct. This is why I have the principle never to post untested code.
Dimitre Novatchev
+4  A: 
/foo/Bar[position() > 1]

For example, in C#:

[Test]
public void PositionBasedXPathExample()
{
    string xml = @"<foo>
                     <Bar>A</Bar>
                     <Bar>B</Bar>
                     <Bar>C</Bar>
                   </foo>";

    XDocument xDocument = XDocument.Parse(xml);
    var bars = xDocument.XPathSelectElements("/foo/Bar[position() > 1]")
        .Select(element => element.Value);

    Assert.That(bars, Is.EquivalentTo(new[] { "B", "C" }));
}
Elisha
A: 

Using apply-templates:

<xsl:apply-templates select="foo/Bar[position() &gt; 1]" />

or the same xpath for for-each:

<xsl:for-each select="foo/Bar[position() &gt; 1]">
    …
</xsl:for-each>
esycat
+1  A: 

/foo/bar[position() > 1]

selects all bar elements with the exception of the first, that are children of the top element, which is foo.

(//bar)[position() >1]

selects all bar elements in in any XML document, with the exception of the first bar element in this document.

Dimitre Novatchev
I see. Thank you. :)
zneak