Abbreviating the descendant axis in XSLT

Say we have the following XML:

[sourcecode language=’xml’]
p1 p2 p3

[/sourcecode]

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

[sourcecode language=’xml’]
p1
p3
[/sourcecode]

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

One response to “Abbreviating the descendant axis in XSLT”

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from Stuff I've learned recently...

Subscribe now to keep reading and get access to the full archive.

Continue reading