XSL for-each: how to detect last node?
XsltXslt Problem Overview
I have this simple code:
<xsl:for-each select="GroupsServed">
<xsl:value-of select="."/>,<br/>
</xsl:for-each></font>
I'm trying to add a comma for each item added.
This has 2 flaws:
- Case of when there's only 1 item: the code would unconditionally add a comma.
- Case of when there's more than 1 item: the last item would have a comma to it.
What do you think is the most elegant solution to solve this?
I'm using XSLT 2.0
Xslt Solutions
Solution 1 - Xslt
If you're using XSLT 2.0, the canonical answer to your problem is
<xsl:value-of select="GroupsServed" separator=", " />
On XSLT 1.0, the somewhat CPU-expensive approach to finding the last element in a node-set is
<xsl:if test="position() = last()" />
Solution 2 - Xslt
Final answer:
<xsl:for-each select="GroupsServed">
<xsl:value-of select="."/>
<xsl:choose>
<xsl:when test="position() != last()">,<br/></xsl:when>
</xsl:choose>
</xsl:for-each>
Solution 3 - Xslt
<xsl:variable name="GROUPS_SERVED_COUNT" select="count(GroupsServed)"/>
<xsl:for-each select="GroupsServed">
<xsl:value-of select="."/>
<xsl:if test="position() < $GROUPS_SERVED_COUNT">
,<br/>
</xsl:if>
</xsl:for-each></font>
Solution 4 - Xslt
Insert the column delimiter before each new item, except the first one. Then insert the line break outside the for-each loop.
<xsl:for-each select="GroupsServed">
<xsl:if test="position() != 1">,</xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
<br/>
In other words, treat every item like the last item. The exception is that the first item does not need a comma separator in front of it. The loop ends after the last item is processed, which also tells us where to put the break.