XSL Array?
This is an open discussion with 5 replies, filed under XSLT.
Search
In XSLT 2.0 there is a tokenize()
function, but not in XSLT 1.0 (which we will be using), but thankfully you can use the EXSLT extension library to achieve this!
http://www.exslt.org/str/functions/tokenize/
First include the strings
namespace in your stylesheet — the EXSLT site uses a prefix of str
for brevity:
http://www.exslt.org/str/index.html
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://exslt.org/strings" extension-element-prefixes="str"> ... </xsl:stylesheet>
You can then call the tokenize function which accepts a string and an optional delimiter string. The function returns a node-set of token
nodes that you can loop through:
<xsl:for-each select="str:tokenize($url-parameter,',')/token"> ... </xsl:for-each>
If you don’t specify the delimiter, whitespace will be used (to split up words), and if you specify a blank string (''
) it will split up every character.
You’ll need to break them up using something like the XSL substring-after
function. There’s a good article on XML.com about splitting and looping over strings: http://www.xml.com/pub/a/2002/05/01/xslt-string.html. Here’s a sample that might help:
<xsl:template name="item-tokenize"> <xsl:param name="list" /> <xsl:param name="delimiter" /> <xsl:variable name="newlist"> <xsl:choose> <xsl:when test="contains($list, $delimiter)"><xsl:value-of select="normalize-space($list)" /></xsl:when> <xsl:otherwise><xsl:value-of select="concat( normalize-space($list), $delimiter )"/></xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="first" select="substring-before($newlist, $delimiter)" /> <xsl:variable name="remaining" select="substring-after($newlist, $delimiter)" /> <xsl:element name="newitem"><xsl:value-of select="$first"/></xsl:element> <xsl:if test="$remaining"> <xsl:call-template name="item-tokenize"> <xsl:with-param name="list" select="$remaining" /> <xsl:with-param name="delimiter"><xsl:value-of select="$delimiter"/></xsl:with-param> </xsl:call-template> </xsl:if> </xsl:template>
You call it like so:
<xsl:call-template name="item-tokenize"> <xsl:with-param name="list" select="." /> <xsl:with-param name="delimiter" select="','"/> </xsl:call-template>
OK then - use what nick said. Only use mine if you don’t have access to an XSL transformer that has the tokenize extension available.
There’s always more than one way to skin a cat :-)
Thanks both, the str:tokenize worked great :).
Looping through the result array and showing only the required entries without duplicates was a little tricky though (I guess I have to use a key and generate-id for that, but that’s for later).
Create an account or sign in to comment.
Hi there,
I guess this is a beginners question but I haven’t found a good answer yet ;)
I have a couple of (varying) values in an url, something like: …/value1,value2,value3/..
and based on these values the xslt transformations will be different (elements to show or not). I already have them assigned to an url paramater, but how to to turn it into an array and loop them through?
Thanks