ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> xsl-list
xsl-list
[xsl] Reverse (Was: RE: last index of...)
by Dimitre Novatchev other posts by this author
Nov 13 2001 12:23PM messages near this date
Re: [xsl] Positions | [xsl] using position to change row colors
>  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
 

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved