SAXONICA

Saxon Documentation
Full Contents
About Saxon
Changes in this Release
Notices
Using XSLT 2.0
Using XQuery
Handling Source Documents
XML Schema Processing
XPath API for Java
Saxon on .NET
Extensibility
Saxon Extensions
| Introduction
| EXSLT Extensions
| Extension attributes (XSLT only)
| Additional serialization parameters
| Extension functions
» | Extension instructions
Sample Saxon Applications
The Saxon SQL Extension
XSLT Elements
XPath 2.0 Expression Syntax
Function Library
Standards Conformance

# saxon:iterate

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.

This extension is new in Saxon 9.1. It should be regarded as experimental. The primary motivation for introducing it is to enable streamed processing of input files where there is a need to "remember" data read at the beginning of the document for use when processing elements encountered later. Streaming is available only in Saxon-SA, but the basic functionality of `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.

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.

Next