Search

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

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.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details