xsl-list
[Top] [All Lists]

## Re: [xsl] [XSLT 1.0] How to get the last number in a string of numbers?

2009-12-23 10:09:13
```At 2009-12-23 09:01 -0500, Costello, Roger L. wrote:
```
```I have a variable that contains a bunch of numbers:

<xsl:variable name="numbers">
generate some numbers
</xsl:variable>

I want to obtain the last number in \$numbers.

For example, this might be the value of \$numbers:

6 23 45 67

I want the last number:

67

```
I want the last number fast, i.e., I want it in constant time, not O(n), where n is the length of the list of numbers.
```
Plus, I don't want to use any extension functions/elements.

Finally, I want to use only XSLT 1.0

Can it be done? How?
```
```
```
I can't think of a way of doing it in constant time because of the limited set of functions available.
```
Is this a real-world problem or just a puzzle?

```
You don't say why you have the constraint of O(n), which is typical when using the design pattern of car/cdr but if you want to reduce the number of recursive calls to the length of the last number, I thought of a lexical approach below.
```
```
I would suppose the advantage with the lexical approach is that the string functions are being evaluated behind the scenes and the number of executed stylesheet loops (which would be relatively slower) is always going to be the length of the last number regardless of whether you have one number or a thousand numbers.
```
```
In both cases, though, remember that tail recursion optimization (implemented in Saxon) is going to make execution really quite quick and without occupying any stack space if that was your concern.
```
Both approaches are illustrated below.

I hope this helps.

. . . . . . . . . . . . Ken

T:\ftemp>xslt roger.xsl roger.xsl

Last: 67
Last: 67
T:\ftemp>type roger.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0">

<xsl:output method="text"/>

<xsl:variable name="numbers">
6 23 45 67
</xsl:variable>

<xsl:template match="/">
<xsl:call-template name="find-last-token-using-tokens">
<xsl:with-param name="nums" select="normalize-space(\$numbers)"/>
</xsl:call-template>

<xsl:call-template name="find-last-token-using-string">
<xsl:with-param name="nums" select="normalize-space(\$numbers)"/>
</xsl:call-template>
</xsl:template>

<xsl:template name="find-last-token-using-tokens">
<xsl:param name="nums"/>
<xsl:choose>
<xsl:when test="contains(\$nums,' ')">
<xsl:call-template name="find-last-token-using-tokens">
<xsl:with-param name="nums" select="substring-after(\$nums,' ')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
Last: <xsl:value-of select="\$nums"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template name="find-last-token-using-string">
<xsl:param name="nums"/>
<xsl:param name="last"/>
<xsl:variable name="last-char"
select="substring(\$nums,string-length(\$nums))"/>
<xsl:choose>
<xsl:when test="\$last-char and \$last-char!=' '">
<xsl:call-template name="find-last-token-using-string">
<xsl:with-param name="nums"
select="substring(\$nums,1,string-length(\$nums)-1)"/>
<xsl:with-param name="last"
select="concat(\$last-char,\$last)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
Last: <xsl:value-of select="\$last"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>

T:\ftemp>

--
UBL and Code List training:      Copenhagen, Denmark 2010-02-08/10
XSLT/XQuery/XPath training after http://XMLPrague.cz 2010-03-15/19
XSLT/XQuery/XPath training:   San Carlos, California 2010-04-26/30
Vote for your XML training:   http://www.CraneSoftwrights.com/s/i/
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video