Name

cx:until-unchanged — Iterates to a fixed point.

Synopsis

<cx:until-unchanged
  name? = NCName>
    (p:output?,
     p:log?,
     subpipeline)
</cx:until-unchanged>>

Description

The cx:until-unchanged step is an extension compound step. There's no provision in the language for defining these steps, but that doesn't mean implementors can't.

On the first iteration, the cx:until-unchanged step provides (on the #current port) the document that it reads from the default readable port[3] to the subpipeline it contains.

The subpipeline must produce exactly one output document on cx:until-unchanged’s single output port.

On the second and subsequent iterations, the result of the preceding iteration is provided on the #current port.

Iteration continues until the document produce is deep-equal to the document produced on the previous iteration.

Here's a trivial example:

<p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
                xmlns:cx="http://xmlcalabash.com/ns/extensions"
                name="main" version="1.0">
  <p:input port="parameters" kind="parameter"/>
  <p:output port="result" sequence="true" primary="true"/>

  <p:identity name="id">
    <p:input port="source">
      <p:inline><doc>1</doc></p:inline>
    </p:input>
  </p:identity>

  <cx:until-unchanged>
    <p:output port="result"/>
    <p:xslt>
      <p:input port="stylesheet">
        <p:inline>
          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                          xmlns:xs="http://www.w3.org/2001/XMLSchema"
                          exclude-result-prefixes="xs"
                          version="2.0">

            <xsl:template match="doc">
              <xsl:variable name="count" select="xs:integer(.)"/>
              <xsl:choose>
                <xsl:when test="$count &lt; 5">
                  <doc><xsl:value-of select="$count+1"/></doc>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:sequence select="."/>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:template>
          </xsl:stylesheet>
        </p:inline>
      </p:input>
    </p:xslt>
  </cx:until-unchanged>

</p:declare-step>

The stylesheet adds one to the integer value of the document that it is styling as long as the value is less than 5.

The result of running this pipeline is that the stylesheet is run five times, producing documents with the “values” 2, 3, 4, 5, 5. At that point the loop terminates and the last document,

<doc>5</doc>

is returned.


[3]Yes, it's a bug that there's no equivalent of p:iteration-source for this step.