Since others have joined the conversation, I should publish the reply I sent you when this went off-list.
 
Essentially, there's a limitation with tail-call optimization in Saxon 8.4 (and some earlier releases, I'm not sure how far back): a call on call-template or apply-templates is not treated as tail-recursive if it's preceded (as a sibling) by a local variable declaration. In the particular case in question, I suggested a workaround along the lines
 
<template>
  <if test="always-true-condition">
    <variable>
    <other stuff>
  </if>
  <if test="not finished">
    <call-template>
  </if>
</template>
 
(The always-true-condition must not be one that Saxon can recognize to be always true at compile time!)
 
I also suggested that in this case it might be possible to write the application without using recursion at the top level.
 
Michael Kay
http://www.saxonica.com/


From: saxon-help-admin@lists.sourceforge.net [mailto:saxon-help-admin@lists.sourceforge.net] On Behalf Of Alan Painter
Sent: 14 June 2005 15:59
To: saxon-help@lists.sourceforge.net
Subject: [saxon] Template recursion, StackOverflowError, saxon:while and variable assignability

Hello,

I've been using Template recursion in order to iterate over the N instances
of a node in a big input document, each node creating a separate result-document.

Haven't had any problem to date, even with big files (100Mo) and around 100 output documents.

But I just ran into a case of "StackOverflowError":

SXLM0001: Too many nested apply-templates calls. The stylesheet is probably looping.

Sure, it's looping, but over the nodes that I need to output, not in error.

So I thought that I'd try the Saxon extensions that allow iteration, to wit the "saxon:while"
extension and the "saxon:assignable" attribute to xsl:variable, along with "saxon:assign".
I noticed that the 8.4 documentation says that "saxon:assign" may go away in the future.
However, in spite of repeated attempts and tweaks, I couldn't get saxon:assign to work:
my global variable remained a constant value:

    <xsl:variable name="tradePartCount"  as="xs:integer" select="count($tradeParts)"/>
    <xsl:variable name="topCurTradePart" select="0" saxon:assignable="yes" />

    <saxon:while test="$topCurTradePart lt $tradePartCount">
        <saxon:assign name="topCurTradePart" select="$topCurTradePart+1"/>
        <xsl:call-template name="makeATradePart"/>
    </saxon:while>

Note: I tried both the "select" and "expr" attributes to saxon:assign.

So I'm in a corner and I'm curious what I should do:

-- Try to pursue the "saxon:assign" workaround, in the hopes of making it work
-- Modify a configuration (which?) in order to keep from having StackOverFlow exception in a normal recursion.

Thanks for pointers.

-alan