I. Using a recursively called named template:
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:call-template name="eatAllSlashes">
<xsl:with-param name="pText" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template name="eatAllSlashes">
<xsl:param name="pText"/>
<xsl:choose>
<xsl:when test="not(contains($pText,'/'))">
<xsl:value-of select="$pText"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="eatAllSlashes">
<xsl:with-param name="pText"
select="substring-after($pText, '/')"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
when applied on this XML document:
<t>http://stackoverflow.com/questions/2981175/is-it-possible-to-slice-the-end-of-a-url-with-xslt-1-0</t>
produces the wanted, correct output:
is-it-possible-to-slice-the-end-of-a-url-with-xslt-1-0
II. Using the FXSL library:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my" exclude-result-prefixes="xsl my">
<xsl:import href="iter.xsl"/>
<xsl:output method="text"/>
<my:condition/>
<my:skipSlash/>
<xsl:variable name="vfunCondition"
select="document('')/*/my:condition"/>
<xsl:variable name="vfunSkipSlash"
select="document('')/*/my:skipSlash"/>
<xsl:template match="/">
<xsl:call-template name="iterUntil">
<xsl:with-param name="pCond" select="$vfunCondition"/>
<xsl:with-param name="pFun" select="$vfunSkipSlash"/>
<xsl:with-param name="arg1" select="string(/)"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="my:condition">
<xsl:param name="arg1"/>
<xsl:value-of select="number(not(contains($arg1, '/')))"/>
</xsl:template>
<xsl:template match="my:skipSlash">
<xsl:param name="arg1"/>
<xsl:value-of select="substring-after($arg1, '/')"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on this XML document:
<t>http://stackoverflow.com/questions/2981175/is-it-possible-to-slice-the-end-of-a-url-with-xslt-1-0</t>
the wanted result is produced:
is-it-possible-to-slice-the-end-of-a-url-with-xslt-1-0
Do note:
The template iterUntil
has three parameters:
-- pCond
-- a function (template reference) that checks a condition on the current result and potentially issues a "stop signal" (1).
-- pFun
-- a function (template reference) that is used to produce the next current result from the current result (or initially from the input argument $arg1).
-- arg1
-- the input argument on which the pFun
function is initially applied.
Our pCond
function is the template that matches my:condition
. It issues the "stop signal" (outputs 1) only if the string passed as $arg1
does not contain any '/' characters.
Our pFun
function is the template that matches my:skipSlash
. It discards all characters up to and including the first '/' in the string $arg1
The initial input argument is defined in $arg1
and is the string value from which only the text after the last '/' must be produced.
The main advantage of using FXSL is that this avoids the need to code explicit recursion and the possibilities for errors doing this. Also, the template/functions are very generic and powerful and can be re-used for solving huge classes of similar problems.