This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
RE: last index of...
- To: "'xsl-list at lists dot mulberrytech dot com'" <xsl-list at lists dot mulberrytech dot com>
- Subject: RE: [xsl] last index of...
- From: "McNally, David" <David dot McNally at moodys dot com>
- Date: Mon, 12 Nov 2001 15:01:47 -0500
- Reply-to: xsl-list at lists dot mulberrytech dot com
> > Is there a function in XSLT which obtains the position of the last
> > occurrence of a string within another string?
>
[snip]
> Getting the last index would be slightly more complicated, and it
> looks like you want to use it to get hold of the string after the last
> occurrence of something, so hopefully this is sufficient.
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.
Using this input file, searching for "nme" in each case:
<foo>
<test>aaa bbb nme ccc ddd nme aaa 21</test>
<test>aaa bbb nme ccc nme aaa 17</test>
<test>aaa ccc ddd nme aaa 13</test>
<test>aaanmenmenme bbb nme ccc ddd nmenmenme aaa 36</test>
<test>;l sdkjsdf lsdfkj 0</test>
</foo>
This stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:html="http://www.w3.org/1999/xhtml" >
<xsl:output method="text"/>
<xsl:template name="reverse">
<xsl:param name="string"/>
<xsl:value-of select="substring($string, string-length($string))"/>
<xsl:if test="string-length($string) > 1">
<xsl:call-template name="reverse">
<xsl:with-param name="string"
select="substring($string, 1, (string-length($string)-1))"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="rindex">
<xsl:param name="string"/>
<xsl:param name="substring"/>
<xsl:choose>
<xsl:when test="contains($string,$substring)">
<xsl:variable name="rstring">
<xsl:call-template name="reverse">
<xsl:with-param name="string"
select="$string"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="rsubstring">
<xsl:call-template name="reverse">
<xsl:with-param name="string"
select="$substring"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="string-length($string) -
(string-length(substring-before($rstring,$rsubstring)) +
string-length($rsubstring)) + 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="0"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="test">
<xsl:text>
Position: </xsl:text>
<xsl:call-template name="rindex">
<xsl:with-param name="string" select="."/>
<xsl:with-param name="substring" select="'nme'"/>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
gives output:
Position: 21
Position: 17
Position: 13
Position: 36
Position: 0
which seems right.
I just checked the archives to see if reverse templates had been discussed
before, and indeed they have:
http://www.biglist.com/lists/xsl-list/archives/200108/msg00248.html
I guess the reverse template I wrote is tail-recursive, and so slow?
David.
--
David McNally Moody's Investors Service
Software Engineer 99 Church St, NY NY 10007
David.McNally@Moodys.com (212) 553-7475
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list