XSLT 1.0 string reversal & tail recursion
The need or desire to reverse a string in XSLT (1.0) might be rare, but I have found it useful in the past to manipulate or deal with characters at the end. However, I will admit that I could not immediately determine the exact purpose for its use looking at some older code I had written - having the input XML would have helped.
Here was my first attempt at writing a named template to do reversal:
<xsl:template name="reverseString">
<xsl:param name="inputStr"/>
<xsl:variable name="strLength"
select="string-length($inputStr)"/>
<xsl:choose>
<xsl:when test="$strLength < 2">
<xsl:value-of select="$inputStr"/>
</xsl:when>
<xsl:when test="$strLength = 2">
<xsl:value-of select="substring($inputStr,2,1)"/>
<xsl:value-of select="substring($inputStr,1,1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring
($inputStr,$strLength,1)"/>
<xsl:call-template name="reverseString">
<xsl:with-param name="inputStr"
select="substring($inputStr,1,$strLength - 1)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
I was curious how XSLT 2.0 would accomplish this, and consulted my copy of O'Reilly's XSLT Cookbook, 2nd Edition by Sal Mangano (the solution, by the way, is only three lines, using codepoints-to-string and string-to-codepoints).
Included in the book is a section on string reversal - with a close to identical recursive template example to the one above that is deemed "an ineffcient tail recursive implementation". This led to me look up tail recursion as the term was not totally familiar to me. Tail recursion involves a function calling itself as the very last step in the function - allowing the existing underlying stack frame to be used instead of creating a new one (the recursion is handled by iteration). I believe most major XSLT engines are optimized for tail recursion - Saxon (my favorite) definitely is.
Doing the recursive, self call at the end of a named template seems natural and logical to me anyway - without knowing the processor is optimized for it.
Back to my inefficient reversal function - it's inefficient because each recursive call is only repositioning a single character. I failed to heed CS 101 (or maybe 201) basics of dividing and conquering, attempting to cut work in half.
Sal's most efficient solution to XSLT 1.0 string reversal is fairly similar to the one above, but with two tail recursive calls, each one reversing one-half of the input string.
Trackbacks
Use the following link to trackback from your own site:
http://ossolab.com/trackbacks?article_id=xslt-1-0-string-reversal-tail-recursion&day=29&month=08&year=2006