xslt 1.0 code isn’t reusable

I'm building an XML site. One of the common tasks is to get a book by isbn. I needed 4(!) attempts to get it working!

The first attempt was obvious. I created an template:

<xsl:template name="find-book">
 <xsl:param name="isbn"/>

The supposed use was like:

<xsl:variable name="book">
 <xsl:call-template name="find-book">
  <xsl:with-param name="isbn" select="@isbn"/>

Unfortunately, this solution fails when I want something like:

<xsl:value-of select="$book/title"/>

The variable book is a result tree fragment (RTF), not a node set. One can't apply XPath to a RTF.

Second attempt.

Let use node-set:

<xsl:value-of select="exsl:node-set($book)/title" xmlns:exsl="http://exslt.org/common"/>

Mistake. The right way is (note the root node):

<xsl:value-of select="exsl:node-set($book)/book/title" xmlns:exsl="http://exslt.org/common"/>

Unfortunately, it doesn't work when I need the parent node. Nodeset created by exsl-node isn't connected to the original tree.

Third attempt.

Instead of returning a book tree, I return generate-id() for the node. Also I defined a key to get a book by its generated ID.

Again failed. I load the XML database using the document() function, function key() lookups only in the current document, and switching the current document isn't good for me.

Final solution.

First, I get an generated ID. Then I manually search for a book in the database:

<xsl:variable name="book" select="$xmldb//book[generate-id()=$book-genid]"/>

Ugly, but works.