Reputation: 11
I need to pull out the last word from the following string for the use of the surname:
<CUSTOMER_x0020_NAME>Mr Tim Cookson</CUSTOMER_x0020_NAME>
So I just need to pull out the 'Cookson' using XSLT, how do I do this? Tried several relations to substring-after but no luck.
Upvotes: 1
Views: 1193
Reputation: 243479
Here is a non-recursive solution, which works with word delimiters that are any non-alphabetic characters (but the characters after the last word, if any, should be only spaces):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pLower" select=
"'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:param name="pUpper" select=
"'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="vAlpha" select="concat($pUpper, $pLower)"/>
<xsl:template match="text()">
<xsl:variable name="vText" select="normalize-space()"/>
<xsl:variable name="vLength" select="string-length($vText)"/>
<xsl:variable name="vPunct" select="translate(., $vAlpha, '')"/>
<xsl:for-each select=
"document('')//node()
|document('')//@*
|document('')//namespace::*">
<xsl:variable name="vPos" select="position()"/>
<xsl:variable name="vRemaining"
select="substring($vText, $vPos)"/>
<xsl:if test=
"contains($vPunct, substring($vRemaining,1,1))
and
$vLength -$vPos
= string-length(translate($vRemaining, $vPunct, ''))
">
<xsl:value-of select="substring($vRemaining,2)"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<CUSTOMER_x0020_NAME>Mr Tim Cookson</CUSTOMER_x0020_NAME>
the wanted, correct result is produced:
Cookson
When the same transformation is applied on this XML document:
<CUSTOMER_x0020_NAME>Mr. Tim Berners-Lee</CUSTOMER_x0020_NAME>
again the correct result is produced:
Lee
Upvotes: 2
Reputation: 101700
You can use this recursive template to get the last word of a value:
<xsl:template name="GetLastWord">
<xsl:param name="value" />
<xsl:variable name="normalized" select="normalize-space($value)" />
<xsl:choose>
<xsl:when test="contains($normalized, ' ')">
<xsl:call-template name="GetLastWord">
<xsl:with-param name="value" select="substring-after($normalized, ' ')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$normalized"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
You would add this template to your XSLT, and then simply call it, like this:
<xsl:call-template name="GetLastWord">
<xsl:with-param name="value" select="CUSTOMER_x0020_NAME" />
</xsl:call-template>
Upvotes: 0