I'm tokenising a string with XSLT 1.0 and trying to prevent empty strings from being recognised as tokens. Here's the entire function, based on XSLT Cookbook:
<xsl:template name="tokenize">
<xsl:param name="string" select="''" />
<xsl:param name="delimiters" select="';#'" />
<xsl:param name="tokensplitter" select="','" />
<xsl:choose>
<!-- Nothing to do if empty string -->
<xsl:when test="not($string)" />
<!-- No delimiters signals character level tokenization -->
<xsl:when test="not($delimiters)">
<xsl:call-template name="_tokenize-characters">
<xsl:with-param name="string" select="$string" />
<xsl:with-param name="tokensplitter" select="$tokensplitter" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="_tokenize-delimiters">
<xsl:with-param name="string" select="$string" />
<xsl:with-param name="delimiters" select="$delimiters" />
<xsl:with-param name="tokensplitter" select="$tokensplitter" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="_tokenize-characters">
<xsl:param name="string" />
<xsl:param name="tokensplitter" />
<xsl:if test="$string">
<token><xsl:value-of select="substring($string, 1, 1)"/></token>
<xsl:call-template name="_tokenize-characters">
<xsl:with-param name="string" select="substring($string, 2)" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="_tokenize-delimiters">
<xsl:param name="string" />
<xsl:param name="delimiters" />
<xsl:param name="tokensplitter" />
<!-- Extract a delimiter -->
<xsl:variable name="delimiter" select="substring($delimiters, 1, 1)"/>
<xsl:choose>
<!-- If the delimiter is empty we have a token -->
<xsl:when test="not($delimiter) and $string != ''">
<xsl:text>£</xsl:text>
<token><xsl:value-of select="$string"/></token>
<xsl:text>$</xsl:text>
<xsl:value-of select="$tokensplitter"/>
</xsl:when>
<!-- If the string contains at least one delimiter we must split it -->
<xsl:when test="contains($string, $delimiter)">
<!-- If it starts with the delimiter we don't need to handle the before part -->
<xsl:if test="not(starts-with($string, $delimiter))">
<!-- Handle the part that comes before the current delimiter with the next delimiter. -->
<!-- If there is no next the first test in this template will detect the token. -->
<xsl:call-template name="_tokenize-delimiters">
<xsl:with-param name="string" select="substring-before($string, $delimiter)" />
<xsl:with-param name="delimiters" select="substring($delimiters, 2)" />
<xsl:with-param name="tokensplitter" select="$tokensplitter" />
</xsl:call-template>
</xsl:if>
<!-- Handle the part that comes after the delimiter using the current delimiter -->
<xsl:call-template name="_tokenize-delimiters">
<xsl:with-param name="string" select="substring-after($string, $delimiter)" />
<xsl:with-param name="delimiters" select="$delimiters" />
<xsl:with-param name="tokensplitter" select="$tokensplitter" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- No occurrences of current delimiter so move on to next -->
<xsl:call-template name="_tokenize-delimiters">
<xsl:with-param name="string" select="$string" />
<xsl:with-param name="delimiters" select="substring($delimiters, 2)" />
<xsl:with-param name="tokensplitter" select="$tokensplitter" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Value for string
that I'm passing in is:
Europe;#6;#Global;#3;#Middle East, Africa and Caucasus;2;#Europe;#6;#Global;#3;#Middle East, Africa and Caucasus
(The £
and $
indicators are just there so I can see no empty strings are output. This is within SharePoint so is difficult to debug.)
This code hangs processing of the XSLT. The line causing the problem is <xsl:when test="not($delimiter) and $string != ''">
. As soon as I remove the second and
test it works again. I've also tried and string($string)
without success.
Anyone know why this is happening and how to resolve it?