[xsl] XSLT 1.0 Stack Overflow Question

Subject: [xsl] XSLT 1.0 Stack Overflow Question
From: "Roger L. Cauvin" <roger@xxxxxxxxxx>
Date: Fri, 13 Jul 2007 12:40:06 -0500
I'm parsing raw text (not XML or a node-set) that contains a long list of
items separated by linefeeds.  Let's say it's a list of action items:

  Action Items
  1. Ensure all tests pass.
  2. Get sign-off on documentation from Amy.
  3. Create a new page on web site for product.
  4. Move product from staging area to production.
  .
  .
  .
  205. Send press release announcing release.

What I want to do is find the item with the greatest number of characters in
it.  So I have a recursive template:

  <xsl:template name="get-longest-item">
    <xsl:param name="items"/>
    <xsl:variable name="index">
      <xsl:value-of select="substring-before(substring-after($items,
'&#10;'), '.')"/>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$index = ''">
        <xsl:text disable-output-escaping="yes">-1%-1</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="item">
          <xsl:value-of select="substring-before(substring-after($items, '.
'), '&#10;')"/>
        </xsl:variable>
        <xsl:variable name="length" select="string-length($item)"/>
        <xsl:variable name="longest-of-rest">
          <xsl:call-template name="get-longest-item">
            <xsl:with-param name="items" select="substring-after($items,
'&#10;')" />
          </xsl:call-template>
        </xsl:variable>
        <xsl:choose>
          <xsl:when test="$length &gt; substring-after($longest-of-rest,
'%')">
            <xsl:value-of select="concat($index, '%', $length)" />
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$longest-of-rest" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

The template "returns" the index of the longest item, followed by the
percent symbol, followed by the length of that item.

For a large list of action items, applying this template results in a stack
overflow.  A binary divide-and-conquer approach would make much more
efficient use of stack space, but I can't figure out how to do it using XSLT
1.0.  I try to cut the text into two halves, but doing so inevitably seems
to involve order N recursion.

Current Thread