XML.com

XSLT 3.0 xsl:iterate instruction use cases and examples

May 23, 2025

Mukul Gandhi

Mukul Gandhi introduces us to the XSLT 3.0 xsl:iterate instruction with use cases and examples.

1) Introduction

XSLT 3.0 language has instructions xsl:for-each and xsl:iterate for performing repetition processing of an XSL stylesheet logic. This article discusses in detail, about XSLT 3.0's xsl:iterate instruction.

In this introduction section of this article we'll first discuss the fundamentals of the xsl:for-each instruction, since thexsl:iterate instruction provides some new features and improvements compared to the xsl:for-each instruction.

An xsl:for-each instruction has been available since version 1.0 of the XSLT language. The xsl:for-each instruction is an important XSLT instruction, and is used for performing repetition (usually sequentially, similar to a loop available in various programming languages) of XSLT logic a certain number of times. The XSLT xsl:for-each instruction is used extensively by XSL stylesheet authors while writing XSL transformation stylesheets using all the XSLT language versions (1.0, 2.0 and 3.0).

In the XSLT 1.0 language, an xsl:for-each instruction performs repetition processing of an XSL stylesheet logic for each XML document input node iterated by the xsl:for-each instruction using its 'select' expression.

The XSLT 1.0 language specifies the xsl:for-each instruction as follows:

<xsl:for-each select = node-set-expression>
    <!-- Content: (xsl:sort*, template) -->
</xsl:for-each>

With XSLT 3.0, an xsl:for-each instruction, in addition to iterating over a set of nodes, can iterate a sequence of atomic values or a heterogeneous sequence containing any combination of XML nodes, atomic values, function items, map or array instances. With XSLT 3.0, an xsl:iterate instruction can also do such iterations over heterogeneous sequences using input values provided by the xsl:iterate instruction's 'select' expression.

For XSLT stylesheets written for simple requirements, the stylesheet elements that usually contain xsl:for-each instructions are xsl:template and xsl:variable. For XSLT stylesheets that contain complex logic, an xsl:for-each instruction may also occur within XSLT instructions like xsl:function (an XSLT 2.0 and 3.0 instruction), xsl:if, xsl:choose (within its xsl:when or xsl:otherwise clauses) etc.

The XSL stylesheet logic coded within the xsl:for-each instruction is evaluated once for each XPath item produced by the xsl:for-each instruction's 'select' expression. Different iterations performed by the xsl:for-each instruction will typically produce different results, depending on the values of the context item and the context position in the XPath context.

2) What xsl:iterate can do, that xsl:for-each cannot

xsl:for-each and xsl:iterate instructions can do similar tasks when both of these have only the 'select' attribute. In fact, any XSL transformation task that can be done by the xsl:for-each instruction can also be done by the xsl:iterate instruction but the vice-versa is not true.

Following are a few examples where the xsl:iterate instruction can function differently and is more useful than the xsl:for-each instruction:

  1. When XSL stylesheet logic repition needs to break (using xsl:break instruction), before an input sequence is completely iterated. This is one of the main reasons, why an XSL stylesheet author will select an xsl:iterate instruction over xsl:for-each instruction.
  2. Different xsl:iterate instruction repititions can have access to named parameter references whose values typically change between iterations (similar to XSL template and function calls that use parameters), using xsl:iterate's xsl:param and xsl:next-iteration sub instructions. When an xsl:iterate instruction uses named parameters, xsl:iterate works like an anonymous template or an anonymous function with parameter passing capability from a previous iteration to next. This is also one of the main reasons, why an XSL stylesheet author will select an xsl:iterate instruction over xsl:for-each instruction.

3) The xsl:iterate instruction definition

An xsl:iterate instruction is specified by the XSLT 3.0 language as the following:

<xsl:iterate select = expression>
     <!-- Content: (xsl:param*, xsl:on-completion?, sequence-constructor) -->
</xsl:iterate>

<xsl:next-iteration>
   <!-- Content: (xsl:with-param*) -->
</xsl:next-iteration>

<xsl:break select? = expression >
   <!-- Content: sequence-constructor -->
</xsl:break>

<xsl:on-completion select? = expression>
   <!-- Content: sequence-constructor -->
</xsl:on-completion>

As we can see, an xsl:iterate instruction may, other than its mandatory select attribute (which is similar in purpose to the xsl:for-each element's select attribute), have the following optional sub-instructions as well: Zero or more xsl:param elements and zero or one xsl:on-completion element. After an xsl:iterate instruction processes the last item within the sequence of items produced by xsl:iterate's 'select' attribute (i.e, after the xsl:iterate instruction's child sequence constructor evaluates completely), an xsl:on-completion element, if present within the xsl:iterate element, can do any additional trailing final processing for an xsl:iterate instruction. Use of the xsl:on-completion element within an xsl:iterate element depends on the XSL stylesheet use case and also on the ability of the XSL stylesheet author to use the xsl:on-completion element in a meaningful way.

An xsl:next-iteration instruction within xsl:iterate may be used (when the corresponding xsl:param element(s) are present within the xsl:iterate element) to pass one or more argument values (using the xsl:with-param instruction) to the next iteration of the xsl:iterate instruction. We can imagine that an xsl:next-iteration instruction passing arguments to the xsl:iterate's next iteration is like a recursive function call (this is like a tail recursive function call within xsl:iterate, where the recursive looking call to xsl:iterate is done using xsl:iterate's xsl:next-iteration instruction which is the last stylesheet instruction within xsl:iterate).

An xsl:iterate instruction processing can be exited using the xsl:break instruction (similar to loops exiting their processing prematurely in other languages when specific condition(s) are true), before the xsl:iterate instruction has traversed all its input sequence items. An xsl:for-each instruction, in comparison, doesn't have any mechanisms by which its processing can exit prematurely (i.e, before all its input items have been traversed).

In the following section of this article we'll discuss a few use case examples for using an xsl:iterate instruction.

4) xsl:iterate use case examples

4.1) A simple logic repetition using the xsl:iterate instruction

The following XSL stylesheet, when run, produces the output shown.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
  
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <numbers>
	   <xsl:iterate select="1 to 5">
	     <number><xsl:value-of select="."/></number>
	   </xsl:iterate>
	</numbers>
  </xsl:template>

</xsl:stylesheet>

The following XSL stylesheet transformation output is produced:

<?xml version="1.0" encoding="UTF-8"?>
<numbers>
    <number>1</number>
    <number>2</number>
    <number>3</number>
    <number>4</number>
    <number>5</number>
</numbers>

The XSL stylesheet example illustrated above uses the XPath range operator 'to' to produce a sequence of five xs:integer values, each of which is emitted to the stylesheet's transformation output in an XML element named 'number'.

4.2)  An xsl:iterate instruction repeating logic, while passing varying argument values to xsl:iterate's subsequent iterations

The following XSL stylesheet, when run, produces the output shown.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
				exclude-result-prefixes="xs"
                version="3.0">
  
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <numbers>
	   <xsl:iterate select="1 to 5">
	     <xsl:param name="m" select="1" as="xs:integer"/>
	     <number m1="{$m}"><xsl:value-of select="."/></number>
		 <xsl:next-iteration>
		   <xsl:with-param name="m" select="$m * 2" as="xs:integer"/>
		 </xsl:next-iteration>
	   </xsl:iterate>
	</numbers>
  </xsl:template>

</xsl:stylesheet>

The following XSL stylesheet transformation output is produced:

<?xml version="1.0" encoding="UTF-8"?>
<numbers>
    <number m1="1">1</number>
    <number m1="2">2</number>
    <number m1="4">3</number>
    <number m1="8">4</number>
    <number m1="16">5</number>
</numbers>

The explanation about the semantics of the XSL stylesheet in this example:

  1. An xsl:iterate instruction repeats processing its contained child sequence constructor five times, with a context item value changing from 1 up to 5.
  2. The xsl:next-iteration instruction provides an argument value for parameter "m" with a value modified according to the xsl:with-param element's 'select' attribute.

4.3) An xsl:iterate instruction doing logic repetition, getting data for xsl:iterate's 'select' expression from an XPath map

The following XSL stylesheet, when run, produces the output shown.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:map="http://www.w3.org/2005/xpath-functions/map"				
				exclude-result-prefixes="xs map"
                version="3.0">
  
  <xsl:output method="xml" indent="yes"/>
  
  <xsl:variable name="map1" select="map {'mon' : 1, 'tue' : 2, 'wed' : 3, 'thu' : 4, 'fri' : 5, 'sat' : 6, 'sun' : 7}" as="map(xs:string, xs:integer)"/>

  <xsl:template match="/">
    <daysOfWeek>
	   <xsl:iterate select="map:keys($map1)">
	     <day name="{.}" seq="{map:get($map1, .)}"/>
	   </xsl:iterate>
	</daysOfWeek>
  </xsl:template>

</xsl:stylesheet>

The following XSL stylesheet transformation output is produced:

<?xml version="1.0" encoding="UTF-8"?>
<daysOfWeek>
    <day name="thu" seq="4"/>
    <day name="tue" seq="2"/>
    <day name="sat" seq="6"/>
    <day name="wed" seq="3"/>
    <day name="fri" seq="5"/>
    <day name="sun" seq="7"/>
    <day name="mon" seq="1"/>
</daysOfWeek>

Following is the explanation about the semantics of the XSL stylesheet illustrated in this example:

  1. An XSL stylesheet declares a variable named 'map1', whose value is an XPath literal map expression referring to the days of the week as key value pairs.
  2. An xsl:iterate instruction iterates over the key names of the map, and produces a sample output for each day of the week. Since there is no guarantee of the order of an XPath map's keys the order in which the names of the days are emitted is not stable.

The following is a modified XSL stylesheet that produces the days of the week information in calendar order:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:map="http://www.w3.org/2005/xpath-functions/map"				
				exclude-result-prefixes="xs map"
                version="3.0">
  
  <xsl:output method="xml" indent="yes"/>
  
  <xsl:variable name="map1" select="map {1 : 'mon', 2: 'tue', 3 : 'wed', 4 : 'thu', 5 : 'fri', 6 : 'sat', 7 : 'sun'}" as="map(xs:integer, xs:string)"/>

  <xsl:template match="/">
    <daysOfWeek>
	   <xsl:iterate select="sort(map:keys($map1))">
	     <day name="{map:get($map1, .)}" seq="{.}"/>
	   </xsl:iterate>
	</daysOfWeek>
  </xsl:template>

</xsl:stylesheet>

The following XSL stylesheet transformation output is produced:

<?xml version="1.0" encoding="UTF-8"?>
<daysOfWeek>
    <day name="mon" seq="1"/>
    <day name="tue" seq="2"/>
    <day name="wed" seq="3"/>
    <day name="thu" seq="4"/>
    <day name="fri" seq="5"/>
    <day name="sat" seq="6"/>
    <day name="sun" seq="7"/>
</daysOfWeek>

The XSL stylesheet in this example uses an XPath map with numeric key values that are sorted using the function fn:sort while evaluating the xsl:iterate instruction's 'select' attribute.

4.4) Using xsl:iterate with xsl:break

Unlike XSLT's xsl:for-each instruction, an xsl:iterate instruction can prematurely exit from the processing using the xsl:break instruction. This is similar to the programming language 'break' functionality that is used to similarly prematurely break from logic processing loops such as for and while loops.

The following XSL stylesheet, when run, produces the output shown.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:map="http://www.w3.org/2005/xpath-functions/map"
                xmlns:array="http://www.w3.org/2005/xpath-functions/array"
                exclude-result-prefixes="map array"                
				version="3.0">
  
  <xsl:output method="xml" indent="yes"/>
  
  <!-- An 'id' value, passed as the value for this XSL stylesheet parameter. 
       If this parameter is not provided to this stylesheet, the default 
	   value specified with xsl:param's 'select' attribute shall be used. -->
  <xsl:param name="maxId" select="5"/>
  
  <xsl:variable name="infoMap1" select="parse-json(unparsed-text('example5.json'))" as="map(*)"/>

  <xsl:template match="/">
     <details>
	    <xsl:variable name="array1" select="map:get($infoMap1, 'data')"/>
	    <xsl:iterate select="1 to array:size($array1)">
	      <xsl:choose>
		    <xsl:when test=". le $maxId">
	          <xsl:variable name="itemMap" select="array:get($array1, .)"/>
			  <item>
			    <id><xsl:value-of select="map:get($itemMap, 'id')"/></id>
				<value><xsl:value-of select="map:get($itemMap, 'value')"/></value>
			  </item>
		    </xsl:when>
		 	<xsl:otherwise>
			   <xsl:break/>
		 	</xsl:otherwise>
		  </xsl:choose>
	    </xsl:iterate>
	 </details>
  </xsl:template>

</xsl:stylesheet>

A sample JSON document used by above cited stylesheet is example5.json:

{
   "info" : "example",
   "data" : [
      {
	     "id" : 1,
		 "value" : "hello"
	  },
	  {
	     "id" : 2,
		 "value" : "there"
	  },
	  {
	     "id" : 3,
		 "value" : "we have"
	  },
	  {
	     "id" : 4,
		 "value" : "a wonderful cat"
	  },
	  {
	     "id" : 5,
		 "value" : "walking downstairs"
	  },
	  {
	     "id" : 6,
		 "value" : "let's"
	  },
	  {
	     "id" : 7,
		 "value" : "listen to the music"
	  },
	  {
	     "id" : 8,
		 "value" : "coming from the"
	  },
	  {
	     "id" : 9,
		 "value" : "other side of this room"
	  },
	  {
	     "id" : 10,
		 "value" : "this JSON document"
	  },
	  {
	     "id" : 11,
		 "value" : "sample is provided"
	  },
	  {
	     "id" : 12,
		 "value" : "for testing an XSL stylesheet"
	  },
	  {
	     "id" : 13,
		 "value" : "Have a great time enjoying the work"
	  },
	  {
	     "id" : 14,
		 "value" : "Many thanks"
	  }
   ]
}

The following XSL stylesheet transformation output is produced:

<?xml version="1.0" encoding="UTF-8"?>
<details>
        <item>
            <id>1</id>
            <value>hello</value>
        </item>
        <item>
            <id>2</id>
            <value>there</value>
        </item>
        <item>
            <id>3</id>
            <value>we have</value>
        </item>
        <item>
            <id>4</id>
            <value>a wonderful cat</value>
        </item>
        <item>
            <id>5</id>
            <value>walking downstairs</value>
        </item>
</details>

The following is the explanation about the semantics of the XSL stylesheet illustrated in this example:

  1. The XSL stylesheet reads a JSON document using the XPath function fn:parse-json (which requires a JSON document string as argument, which is retrieved using the XPath function fn:unparsed-text, which reads a JSON text file from the file system). The fn:parse-json function returns the information as an XPath map (which has a set of data 'key' and 'value' pairs).
  2. The XPath map returned by the fn:parse-json function is iterated using the xsl:iterate instruction. The xsl:iterate instruction processing exits from its processing using the xsl:break instruction when a specific boolean condition is true. In this XSL stylesheet example, the xsl:break instruction causes the exit from xsl:iterate after the first maxId (value 5 in this example) number of array items have been processed.

It's also useful to implement this xsl:iterate and xsl:break instruction use case if the same semantic information has been modelled as the following XML input document.

<?xml version="1.0" encoding="UTF-8"?>
<info details="example">
   <data>
     <id>1</id>
	 <value>hello</value>
   </data>
   <data>
     <id>2</id>
	 <value>there</value>
   </data>
   <data>
     <id>3</id>
	 <value>we have</value>
   </data>
   <data>
     <id>4</id>
	 <value>a wonderful cat</value>
   </data>
   <data>
     <id>5</id>
	 <value>walking downstairs</value>
   </data>
   <data>
     <id>6</id>
	 <value>let's</value>
   </data>
   <data>
     <id>7</id>
	 <value>listen to the music</value>
   </data>
   <data>
     <id>8</id>
	 <value>coming from the</value>
   </data>
   <data>
     <id>9</id>
	 <value>other side of this room</value>
   </data>
   <data>
     <id>10</id>
	 <value>this XML document</value>
   </data>
   <data>
     <id>11</id>
	 <value>sample is provided</value>
   </data>
   <data>
     <id>12</id>
	 <value>for testing an XSL stylesheet</value>
   </data>
   <data>
     <id>13</id>
	 <value>Have a great time enjoying the work</value>
   </data>
   <data>
     <id>14</id>
	 <value>Many thanks</value>
   </data>
</info>

The following XSL stylesheet, when run, produces the output shown.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   
				version="3.0">
  
  <xsl:output method="xml" indent="yes"/>
  
  <!-- An 'id' value, passed as the value for this XSL stylesheet parameter. 
       If this parameter is not provided to this stylesheet, the default 
	   value specified with xsl:param's 'select' attribute shall be used. -->
  <xsl:param name="maxId" select="5"/>
  
  <xsl:template match="/">
    <details>
	   <xsl:apply-templates select="info"/>
	</details>
  </xsl:template>

  <xsl:template match="info">
	 <xsl:iterate select="data">
	    <xsl:choose>
		   <xsl:when test="number(id) le $maxId">
			 <item>
			   <id><xsl:value-of select="id"/></id>
			   <value><xsl:value-of select="value"/></value>
			 </item>
		   </xsl:when>
		   <xsl:otherwise>
			  <xsl:break/>
		   </xsl:otherwise>
		</xsl:choose>
	 </xsl:iterate>
  </xsl:template>

</xsl:stylesheet>

The following XSL stylesheet transformation output is produced:

<?xml version="1.0" encoding="UTF-8"?>
<details>
        <item>
            <id>1</id>
            <value>hello</value>
        </item>
        <item>
            <id>2</id>
            <value>there</value>
        </item>
        <item>
            <id>3</id>
            <value>we have</value>
        </item>
        <item>
            <id>4</id>
            <value>a wonderful cat</value>
        </item>
        <item>
            <id>5</id>
            <value>walking downstairs</value>
        </item>
</details>

4.5) Using xsl:iterate instruction with xsl:on-completion

The following XSL stylesheet, when run, produces the output shown subsequently.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
				exclude-result-prefixes="xs"
                version="3.0">
  
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <numbers>
	   <xsl:iterate select="1 to 5">
	     <xsl:param name="m" select="1" as="xs:integer"/>
		 <xsl:on-completion>
		    <summary finalMvalue="{$m}"/>
		 </xsl:on-completion>
	     <number m1="{$m}"><xsl:value-of select="."/></number>		 
		 <xsl:next-iteration>
		   <xsl:with-param name="m" select="$m * 2" as="xs:integer"/>
		 </xsl:next-iteration>
	   </xsl:iterate>
	</numbers>
  </xsl:template>

</xsl:stylesheet>

The following XSL stylesheet transformation output is produced:

<?xml version="1.0" encoding="UTF-8"?>
<numbers>
    <number m1="1">1</number>
    <number m1="2">2</number>
    <number m1="4">3</number>
    <number m1="8">4</number>
    <number m1="16">5</number>
    <summary finalMvalue="32"/>
</numbers>

The following is the explanation about the semantics of the XSL stylesheet illustrated in this example:

  1. This XSL stylesheet is similar to the usual stylesheet that would use the xsl:iterate instruction with xsl:param and xsl:next-iteration child instructions.
  2. This stylesheet also has an xsl:on-completion instruction that produces an XML element named 'summary' with the final available value of variable "m". Without using the xsl:on-completion instruction, it would be a little harder to emit the value of the variable "m" (the XSL stylesheet author has to either use an xsl:if instruction in the xsl:iterate element that can emit this information by checking that the context item in the xsl:iterate is the last item being iterated, or they have to embed the xsl:iterate in an xsl:variable instruction and process the resulting xsl:variable information. Using the xsl:on-completion instruction simplifies this requirement within the XSL stylesheet).

5) Summary

This article explained the purpose of the xsl:iterate instruction, discussed the differences between the xsl:iterate and xsl:for-each instructions, and discussed various XSL stylesheet technical use cases (involving a hard-coded range of values with xsl:iterate, using JSON and XML documents as input for the xsl:iterate instruction) with relevant detailed examples.

The XSL stylesheet examples used in this article were successfully run with both the Apache Xalan-J XSLT 3.0 processor's latest development code base and the Saxon XSLT 3.0 HE processor.

References

The following W3C specifications are available, and are relevant to this article:

1) XSL Transformations (XSLT) Version 3.0 [W3C Recommendation 8 June 2017]

2) XML Path Language (XPath) 3.1 [W3C Recommendation 21 March 2017]

3) XPath and XQuery Functions and Operators 3.1 [W3C Recommendation 21 March 2017]