[xsl] Reverse (Was: RE: last index of...)

Subject: [xsl] Reverse (Was: RE: last index of...)
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Tue, 13 Nov 2001 04:23:02 -0800 (PST)
> Here's my attempt at getting the index of the last occurrence - basically
> defining a reverse template that just reverses strings, then using
> string-length and substring-before on the reversed strings in a template
> called rindex.

Two implementations of the reverse function (one of them DVC) can be found at:


Here's a functional implementation:

reverse    = foldl (flip (:)) []

where (flip (:))  xs x = x:xs  ((:) adds an element in front of a list, flip just
reverses the order of the arguments), 
and [] is the empty list.

This can be immediately translated to an XSLT implementation using the XSLT
implementation of foldl provided at:


However, for this foldl implementation, an XSLT synonym for "list" is a node-set.

In this concrete case we want to reverse a string, not a node-set. While in Haskell
a string is just a list of characters, in XSLT a string is not a node-set of

Therefore, a separate XSLT implementation is needed of a foldl function operating on
strings. It can be mechanuically obtained from the foldl we have, by substituting 

$nodeSet[1] with substring($someString, 1, 1)


$nodeSet[position() > 1]  with substring($someString, 2)

Here it is:

    <xsl:template name="str-foldl">
      <xsl:param name="pFunc" select="/.."/>
      <xsl:param name="pA0"/>
      <xsl:param name="pStr"/>

         <xsl:when test="not($pStr)">
            <xsl:copy-of select="$pA0"/>

            <xsl:variable name="vFunResult">
              <xsl:apply-templates select="$pFunc[1]">
                <xsl:with-param name="arg0" select="$pFunc[position() > 1]"/>
                <xsl:with-param name="arg1" select="$pA0"/>
                <xsl:with-param name="arg2" select="substring($pStr,1,1)"/>

            <xsl:call-template name="str-foldl">
		<xsl:with-param name="pFunc" select="$pFunc"/>
		<xsl:with-param name="pStr" select="substring($pStr,2)"/>
		<xsl:with-param name="pA0" select="$vFunResult"/>



Now, it is easy to write the strReverse template:

<xsl:stylesheet version="1.0"
exclude-result-prefixes="xsl str-reverse-func"

   <xsl:import href="str-foldl.xsl"/>


    <xsl:template name="strReverse">
      <xsl:param name="pStr"/>

      <xsl:variable name="vReverseFoldlFun" 

      <xsl:call-template name="str-foldl">
        <xsl:with-param name="pFunc" select="$vReverseFoldlFun"/>
        <xsl:with-param name="pStr" select="$pStr"/>
        <xsl:with-param name="pA0" select="/.."/>

    <xsl:template match="str-reverse-func:*">
         <xsl:param name="arg1" select="0"/>
         <xsl:param name="arg2" select="0"/>

         <xsl:value-of select="concat($arg2,$arg1)"/>


Do you notice how easy it is to produce a multitude of important functions using a
small number of very general list-processing functions like foldl/foldr, map,...
etc.? Just pass some specific functions as parameters to these generic
list-processing functions.

Dimitre Novatchev.

Do You Yahoo!?
Find the one for you at Yahoo! Personals

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

Current Thread