# 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 was new in Saxon 9.1. Some changes have been made in 9.2, and it should still 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-EE, 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. 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

Next