This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Reverse (Was: RE: last index of...)
- To: xsl-list at lists dot mulberrytech dot com
- Subject: [xsl] Reverse (Was: RE: last index of...)
- From: Dimitre Novatchev <dnovatchev at yahoo dot com>
- Date: Tue, 13 Nov 2001 04:23:02 -0800 (PST)
- Reply-to: xsl-list at lists dot mulberrytech dot com
> 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