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

%d bloggers like this: