This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Reverse (Was: RE: last index of...)


> 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:

http://sources.redhat.com/ml/xsl-list/2001-08/msg00243.html

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:

http://sources.redhat.com/ml/xsl-list/2001-11/msg00214.html

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

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)

and 

$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:choose>
         <xsl:when test="not($pStr)">
            <xsl:copy-of select="$pA0"/>
         </xsl:when>
         <xsl:otherwise>

            <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:apply-templates>
            </xsl:variable>

            <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"/>

            </xsl:call-template>
         </xsl:otherwise>
      </xsl:choose>

    </xsl:template>

Now, it is easy to write the strReverse template:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:str-reverse-func="f:str-reverse-func"
exclude-result-prefixes="xsl str-reverse-func"
>

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

   <str-reverse-func:str-reverse-func/>

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

      <xsl:variable name="vReverseFoldlFun" 
                    select="document('')/*/str-reverse-func:*[1]"/>

      <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:call-template>
    </xsl:template>

    <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)"/>
    </xsl:template>

</xsl:stylesheet>


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.

Cheers,
Dimitre Novatchev.




__________________________________________________
Do You Yahoo!?
Find the one for you at Yahoo! Personals
http://personals.yahoo.com

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]