Question

I'm performing an XSLT transformation on some XML, with one of the elements looking like the following:

<element>Item1,Item2,Item3,Item4</element>

What's the best way to loop through each comma seperated value in this list using an xsl:for-each? I'd envision something like the following:

<xsl:for-each select="item at position 0, until item at last position">
     <!-- DO SOMETHING WITH ITEM -->
</xsl:for-each>
Was it helpful?

Solution

In XSLT 2.0 it's trivial

<xsl:for-each select="tokenize(element, ',')">
  <!-- "." in here is the item from the comma separated list -->
</xsl:for-each>

Regarding your comment:

is it possible, that whilst looping through each value, to reference another value in the same list at say position 4? If I wanted to do something like "Item1 * Item4"?

For this I'd recommend storing the sequence that results from tokenize in a variable which you can later subscript into:

<!-- assuming the items in your list are actually numbers rather than "ItemN" -->
<xsl:variable name="items" as="xs:double*" select="tokenize(element, ',')" />
<xsl:for-each select="$items[position() lt 4]">
  <num><xsl:value-of select=". * $items[4]" /></num>
</xsl:for-each>

You may find it clearer to for-each over the indexes

<xsl:for-each select="1 to 3">
  <!-- here "." or "current()" is the number 1, 2 or 3 -->
  <num><xsl:value-of select="$items[current()] * $items[4]" /></num>
</xsl:for-each>

If you're stuck with 1.0 then there's no concept of sequences of primitive values - you can only for-each over nodes - so the usual solution there is to use a tail recursive template

<xsl:template name="processCSV">
  <xsl:param name="value" />
  <xsl:if test="$value">
    <xsl:variable name="item" select="substring-before($value, ',')" />
    <!-- do stuff with $item here -->

    <xsl:call-template name="processCSV">
      <xsl:with-param name="value" select="substring-after($value, ',')" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

and call it with

<xsl:call-template name="processCSV">
  <xsl:with-param name="value" select="concat(element, ',')" />
</xsl:call-template>

(having the recursive template expect a trailing comma on the $value keeps the logic rather simpler).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top