The saxon:iterate
element is used to iterate over a sequence. In simple cases the effect is exactly
the same as xsl:for-each
. However, saxon:iterate
offers a guarantee that the evaluation
will be sequential. It allows each iteration to set parameters which will be available during the next iteration, and it allows
early exit from the loop when some condition is true.
saxon:iterate
is also available in Saxon-B
The following example shows how a shopping basket may be displayed with the cumulative values of the items:
<saxon:iterate select="//ITEM" xmlns:saxon="http://saxon.sf.net/" xsl:extension-element-prefixes="saxon">
<xsl:param name="basketCost" as="xs:decimal" select="0"/>
<item cost="{$basketCost}"><xsl:copy-of select="TITLE"/></item>
<saxon:continue>
<xsl:with-param name="basketCost" select="$basketCost + (xs:decimal(PRICE), 0)[1]"/>
</saxon:continue>
</saxon:iterate>
The initial values of the parameters are taken from the select
attribute of the xsl:param
elements;
values for subsequent iterations are taken from the xsl:with-param
in the saxon:continue
instruction.
If any declared parameters are not given a value in the saxon:continue
instruction, they retain their values from
the previous iteration.
The following example shows early exit from the loop when the cumulative value reaches 25.00:
<saxon:iterate select="//ITEM" xmlns:saxon="http://saxon.sf.net/" xsl:extension-element-prefixes="saxon">
<xsl:param name="basketCost" as="xs:decimal" select="0"/>
<xsl:choose>
<xsl:when test="$basketCost gt 25.00">
<saxon:break/>
</xsl:when>
<xsl:otherwise>
<item cost="{$basketCost}"><xsl:copy-of select="TITLE"/></item>
<saxon:continue>
<xsl:with-param name="basketCost" select="$basketCost + (xs:decimal(PRICE), 0)[1]"/>
</saxon:continue>
</xsl:otherwise>
</xsl:choose>
</saxon:iterate>
The instructions saxon:continue
and saxon:break
must be lexically within the
saxon:iterate
instruction and must not be followed by further instructions other than xsl:fallback
.
They may appear within xsl:if
or xsl:choose
(nested to any depth) so long as none of the
intermediate instructions have a following sibling instruction. They must not appear with a nested xsl:for-each
, a nested
literal result element, or nested inside any other instruction.
Within the body of the instruction, the context item, position, and size are available just as in xsl:for-each
. The
value of last()
reflects the size of the input sequence, which may be greater than the number of iterations if
saxon:break
is used for early exit.
A saxon:finally
instruction may be included as the last child of saxon:iterate
; it is executed when
the end of the input sequence is reached. It is not evaluated if the loop is terminated using saxon:break
. The focus
(context node, position, and size) for this instruction is undefined; however, variables
declared within the loop including the loop parameters are available for reference. The loop parameters have
their values as set by the saxon:continue
instruction that ended the last normal iteration.
This instruction is similar in form to a tail-recursive function, but many users may find it easier to code. It is also easier to optimize. The main difference from a tail-recursive function is that the context item is available to refer to the the item being processed in each iteration, and there is no need to explicitly find the tail of the sequence when evaluating parameters for the next iteration, nor to test whether the sequence is empty in order to terminate the iteration.
This instruction is available in Saxon-EE only