Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Here is a generic "iterate" template that performs an action on an initial input and then on its result, until a given condition is specified</strong>.</p> <p>This transformation is <em>tail-recursive</em> and works without stack overflow with an intelligent XSLT processor:</p> <pre><code>&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my:my"&gt; &lt;xsl:output method="text"/&gt; &lt;my:action&gt; &lt;end&gt;1000000&lt;/end&gt; &lt;/my:action&gt; &lt;xsl:variable name="vAction" select="document('')/*/my:action"/&gt; &lt;xsl:template match="/"&gt; &lt;xsl:call-template name="iterate"&gt; &lt;xsl:with-param name="pAction" select="$vAction"/&gt; &lt;xsl:with-param name="pInput" select="0"/&gt; &lt;/xsl:call-template&gt; &lt;/xsl:template&gt; &lt;xsl:template name="iterate"&gt; &lt;xsl:param name="pAction"/&gt; &lt;xsl:param name="pInput"/&gt; &lt;xsl:if test="string-length($pInput)"&gt; &lt;xsl:variable name="vResult"&gt; &lt;xsl:apply-templates select="$pAction"&gt; &lt;xsl:with-param name="pInput" select="$pInput"/&gt; &lt;/xsl:apply-templates&gt; &lt;/xsl:variable&gt; &lt;xsl:copy-of select="$vResult"/&gt; &lt;xsl:call-template name="iterate"&gt; &lt;xsl:with-param name="pAction" select="$pAction"/&gt; &lt;xsl:with-param name="pInput" select="$vResult"/&gt; &lt;/xsl:call-template&gt; &lt;/xsl:if&gt; &lt;/xsl:template&gt; &lt;xsl:template match="my:action"&gt; &lt;xsl:param name="pInput" select="0"/&gt; &lt;xsl:if test="not($pInput &gt;= end)"&gt; &lt;xsl:value-of select="concat($pInput+1,'&amp;#xA;')"/&gt; &lt;/xsl:if&gt; &lt;/xsl:template&gt; &lt;/xsl:stylesheet&gt; </code></pre> <p>when this transformation is applied on any XML document (not used), an intelligent XSLT processor that optimizes tail recursion into iteration produces the wanted result without stack overflow. This is the case with Saxon 6.5.4, which I used to produce the result.</p> <p><strong>Your problem is that not all XSLT processors recognize and optimize tail-recursion.</strong></p> <p><strong>For such processors, one can use DVC - style recursion</strong>:</p> <pre><code>&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt; &lt;xsl:output method="text"/&gt; &lt;xsl:template match="/"&gt; &lt;xsl:call-template name="displayNumbers"&gt; &lt;xsl:with-param name="pStart" select="1"/&gt; &lt;xsl:with-param name="pEnd" select="1000000"/&gt; &lt;/xsl:call-template&gt; &lt;/xsl:template&gt; &lt;xsl:template name="displayNumbers"&gt; &lt;xsl:param name="pStart"/&gt; &lt;xsl:param name="pEnd"/&gt; &lt;xsl:if test="not($pStart &gt; $pEnd)"&gt; &lt;xsl:choose&gt; &lt;xsl:when test="$pStart = $pEnd"&gt; &lt;xsl:value-of select="$pStart"/&gt; &lt;xsl:text&gt;&amp;#xA;&lt;/xsl:text&gt; &lt;/xsl:when&gt; &lt;xsl:otherwise&gt; &lt;xsl:variable name="vMid" select= "floor(($pStart + $pEnd) div 2)"/&gt; &lt;xsl:call-template name="displayNumbers"&gt; &lt;xsl:with-param name="pStart" select="$pStart"/&gt; &lt;xsl:with-param name="pEnd" select="$vMid"/&gt; &lt;/xsl:call-template&gt; &lt;xsl:call-template name="displayNumbers"&gt; &lt;xsl:with-param name="pStart" select="$vMid+1"/&gt; &lt;xsl:with-param name="pEnd" select="$pEnd"/&gt; &lt;/xsl:call-template&gt; &lt;/xsl:otherwise&gt; &lt;/xsl:choose&gt; &lt;/xsl:if&gt; &lt;/xsl:template&gt; &lt;/xsl:stylesheet&gt; </code></pre> <p><strong>this transformation produces the correct result without any crash using MSXML4.</strong></p> <p>With this DVC transformation the maximum recursion-depth is only Log2(N) -- in this case 19.</p> <p><strong>I would recommend using the <a href="http://fxsl.sf.net" rel="noreferrer">FXSL library</a></strong>. It provides DVC variants of commonly used higher-order functions, such as <code>foldl()</code> and <code>map()</code> making it possible to produce the DVC variant of almost any recursive algorithm. </p> <p><strong>Of course, in XSLT2.0 one would simply write</strong>:</p> <pre><code>&lt;xsl:sequence select="1 to 1000000"/&gt; </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload