Abbreviating the descendant axis in XSLT

Say we have the following XML:

<root>
  <para>p1</para>
  <para>p2</para>
  <other>
    <para>p3</para>
  </other>
</root>

The question is, what does the XPath expression //para[1] return? I originally expected it to select all the para elements and then return just the first one. In fact, what it returns is

p1
p3

This is because what the expression actually means is, “return all the para elements that are the first child of any element”.

Why is that?  According to the XPath specification, // is actually the abbreviation for /descendant-or-self::node()/, so that //para is actually /descendant-or-self::node()/child::para.

Since p1 and p3 are the first children of their parents, and p2 is the second child* of its parent, the nodes returned are p1 and p3.

*Assuming we’re ignoring whitespace, of course, which is always a bit of an adventure.

If I really want the first instance of all the para elements, then I need the expression /descendant::para[1]. That collects all the para elements and returns the first one.

A side benefit to this approach is that it forced me to learn how to spell “descendant” correctly. 🙂

About Ken Kousen
I teach software development training courses. I specialize in all areas of Java and XML, from EJB3 to web services to open source projects like Spring, Hibernate, Groovy, and Grails. Find me on Google+ I am the author of "Making Java Groovy", a Java / Groovy integration book published by Manning in the Fall of 2013, and "Gradle Recipes for Android", published by O'Reilly in 2015.

One Response to Abbreviating the descendant axis in XSLT

  1. Kent says:

    Ouch. I always thought // was actual XPATH syntax and not merely an abbreviation for something, as appears to the case. Nice catch.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: