XSLT 3.0 xsl:iterate instruction use cases and examples
May 23, 2025
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:
- 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 overxsl:for-each
instruction. - 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 anxsl: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 anxsl:iterate
instruction overxsl: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:
- An
xsl:iterate
instruction repeats processing its contained child sequence constructor five times, with a context item value changing from 1 up to 5. - The
xsl:next-iteration
instruction provides an argument value for parameter "m" with a value modified according to thexsl: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:
- 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. - 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:
- 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 functionfn:unparsed-text
, which reads a JSON text file from the file system). Thefn:parse-json
function returns the information as an XPath map (which has a set of data'key'
and'value'
pairs). - The XPath map returned by the
fn:parse-json
function is iterated using thexsl:iterate
instruction. Thexsl:iterate
instruction processing exits from its processing using thexsl:break
instruction when a specific boolean condition is true. In this XSL stylesheet example, thexsl:break
instruction causes the exit fromxsl:iterate
after the firstmaxId
(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:
- This XSL stylesheet is similar to the usual stylesheet that would use the
xsl:iterate
instruction withxsl:param
andxsl:next-iteration
child instructions. - 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 thexsl: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 anxsl:if
instruction in thexsl:iterate
element that can emit this information by checking that the context item in thexsl:iterate
is the last item being iterated, or they have to embed thexsl:iterate
in anxsl:variable
instruction and process the resultingxsl:variable
information. Using thexsl: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]