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"/>
</xsl:template>
The supposed use was like:
<xsl:variable name="book">
<xsl:call-template name="find-book">
<xsl:with-param name="isbn" select="@isbn"/>
</xsl:call-template>
</xsl:variable>
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.