Today I wanted to create a for loop in XSLT based on the value of a variable similar to what you would do in any programming language. In XSLT it's a simple task to iterate through a number of elements using XSL for-each but it proved to be a bit trickier than I first thought to iterate over a variable.
After a bit of Googling and some XSLT I found a solution.
A simple For Loop with C#
| for (int i = 1; i =3; i++) |
| { |
| //something happens here |
| } |
XML Sample
The reason I'm wanting to use a for loop is the XML I am using is not of an ideal structure and cannot be changed. You can see the first and second items are related as are the third and forth and so one. The items represent a collection of fields in a form where there is an item and a price.
I want to iterate the items printing there name and price.
| < />xml version="1.0" encoding="utf-16"?> |
| Items> |
| Item Name="Item_1"> |
| Apple |
| Item> |
| Item Name="Item_1_Price"> |
| 3.50 |
| Item> |
| Item Name="Item_2"> |
| Pear |
| Item> |
| Item Name="Item_2_Price"> |
| 4.00 |
| Item> |
| Item Name="Item_3"> |
| Orange |
| Item> |
| Item Name="Item_3_Price"> |
| 3.00 |
| Item> |
| Items> |
I found the
XSLT for loop question had been asked and answered previously,the solution uses recursion to iterate the collection until the index variable has reached the upper limit.
I also want to create a basic XPath select based on the value of the index. The problem was I thought I would simply add the string and the index together to create the select, this was not the case. Doing this return Nan and would not select anything. With a little digging I found I had to use the
XSLT function format-number(number,format,[decimalformat]) to transform the variable from a number to a string.
XSLT Template
| < />xml version="1.0" encoding="utf-16"?> |
| xsl:stylesheet version="1.0" |
| xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> |
| xsl:output method="xml" indent="yes" encoding="utf-8" omit-xml-declaration="yes" /> |
| xsl:template match="/Items"> |
| |
| xsl:call-template name="forloop"> |
| xsl:with-param name="i">1xsl:with-param> |
| xsl:with-param name="count">3xsl:with-param> |
| xsl:call-template> |
| |
| xsl:template> |
| |
| xsl:template name="forloop"> |
| xsl:param name="i" /> |
| xsl:param name="count" /> |
| |
| xsl:if test="$i < />> |
| |
| xsl:variable name="name" select="format-number($i,'Item_0')"/> |
| xsl:variable name="price" select="format-number($i,'Item_0_Price')"/> |
| |
| xsl:value-of select="Item[@Name=$name]"/>: $xsl:value-of select="Item[@Name=$price]"/> |
| br/> |
| |
| xsl:if> |
| |
| |
| xsl:if test="$i < />> |
| xsl:call-template name="forloop"> |
| xsl:with-param name="i"> |
| xsl:value-of select="$i + 1"/> |
| xsl:with-param> |
| xsl:with-param name="count"> |
| xsl:value-of select="$count"/> |
| xsl:with-param> |
| xsl:call-template> |
| xsl:if> |
| |
| xsl:template> |
| xsl:stylesheet> |
So this XSLT For Loop snippet works well in this case.
Has anyone got any better suggestions?