Одной из возможностей может быть перевод алгоритма в хвостовую рекурсию и надеемся, что ваш процессор xslt распознает шаблон и превратит его в цикл.За исключением saxon , я не смог найти никакой информации о том, какие другие процессоры xslt поддерживают хвостовую рекурсию.Преобразование работает путем введения переменной-аккумулятора, которая содержит разделенный текст.Инструкция call-template
будет последней операцией, которую шаблон должен выполнить, и ее можно превратить в эквивалент goto без использования стека.
<xsl:template name="splitBinaryData">
<xsl:param name="txt"/>
<xsl:param name="width"/>
<xsl:param name="accum"/>
<xsl:choose>
<xsl:when test="string-length($txt) > 76 ">
<xsl:call-template name="splitBinaryData">
<xsl:with-param select="substring($txt, 77)" name="txt"/>
<xsl:with-param select="$width" name="width"/>
<xsl:with-param select="concat($accum, substring($txt, 1, 76), ' ')" name="accum"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="string-length($txt) < 76 or string-length($txt) = 76">
<xsl:value-of select="concat($accum, $txt)"/>
</xsl:when>
</xsl:choose>
</xsl:template>
Редактировать: Другой вариантбудет применять алгоритм разделяй и властвуй .Это разбивает проблему на две подзадачи примерно одинакового размера, а затем объединяет их решения.Требуемая глубина стека значительно уменьшается и увеличивается логарифмически, а не линейно относительно размера ввода.Хитрость заключается в том, чтобы сделать первый размер подстроки кратным 76 символам, чтобы избежать вставки дополнительных символов новой строки.
<xsl:template name="splitBinaryData">
<xsl:param name="txt"/>
<xsl:param name="width"/>
<xsl:variable name="len" select="string-length($txt)" />
<xsl:choose>
<xsl:when test="$len > 76 ">
<!-- process the text in two parts of about the same size,
the length of the first part should be a multiple of
the needed width -->
<xsl:variable name="idx" select="ceiling($len div 76 div 2) * 76" />
<xsl:call-template name="splitBinaryData">
<xsl:with-param select="substring($txt, 1, $idx)" name="txt"/>
<xsl:with-param select="$width" name="width"/>
</xsl:call-template>
<xsl:text> </xsl:text>
<xsl:call-template name="splitBinaryData">
<xsl:with-param select="substring($txt, $idx+1)" name="txt"/>
<xsl:with-param select="$width" name="width"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$txt" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>