分割字符串函数导致堆栈溢出
我有一个函数可以将字符串分割成长度不超过 76 个字符的行。该函数的输入是二进制数据,我想由于二进制数据的长度,我经常收到“堆栈溢出”错误。有什么方法可以防止这种情况,或者有更好的方法来分割字符串吗?这需要使用 XSL 1.0 来完成。
<xsl:template name="splitBinaryData">
<xsl:param name="txt"/>
<xsl:param name="width"/>
<xsl:choose>
<xsl:when test="string-length($txt) > 76 ">
<xsl:value-of select="substring($txt, 1, 76)"/><xsl:text> </xsl:text>
<xsl:call-template name="splitBinaryData">
<xsl:with-param select="substring($txt, 77)" name="txt"/>
<xsl:with-param select="$width" name="width"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="string-length($txt) < 76 or string-length($txt) = 76">
<xsl:value-of select="$txt"/>
</xsl:when>
</xsl:choose>
</xsl:template>
提前致谢。
I have a function to split a sting into lines that are 76 characters in length or less. The input to this function is binary data, and I suppose due to the length of the binary data I often get a "stack overflow" error. Any way to prevent this, or is there a better way to split a string? This needs to be done using XSL 1.0.
<xsl:template name="splitBinaryData">
<xsl:param name="txt"/>
<xsl:param name="width"/>
<xsl:choose>
<xsl:when test="string-length($txt) > 76 ">
<xsl:value-of select="substring($txt, 1, 76)"/><xsl:text>
</xsl:text>
<xsl:call-template name="splitBinaryData">
<xsl:with-param select="substring($txt, 77)" name="txt"/>
<xsl:with-param select="$width" name="width"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="string-length($txt) < 76 or string-length($txt) = 76">
<xsl:value-of select="$txt"/>
</xsl:when>
</xsl:choose>
</xsl:template>
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一种可能是将算法转换为尾递归,并希望您的 xslt 处理器能够识别该模式并将其变成一个循环。除了 saxon 之外,我找不到其他 xslt 处理器支持尾递归的任何信息。该转换通过引入包含分割文本的累加器变量来进行。 call-template 指令将成为模板必须执行的最后一个操作,并且可以转换为相当于 goto 的操作,而无需消耗任何堆栈。
编辑:另一种选择是应用分而治之类型算法。这将问题分成两个大小大致相等的子问题,然后组合它们的解决方案。所需的堆栈深度大大减少,并且与输入大小呈对数增长,而不是线性增长。这里的技巧是使第一个子字符串的大小为 76 个字符的倍数,以避免插入额外的换行符。
One possibility might be to translate the algorithm to be tail recursive and hope your xslt processor recognizes the pattern and turns it into a loop. Except for saxon, I could not find any information which other xslt processors support tail recursion. The transformation works by introducing an accumulator variable that contains the splitted text. The
call-template
instruction will then be the last operation the template has to do and can be turned into the equivalent of a goto without consuming any stack.Edit: Another option would be to apply a divide and conquer type of algorithm. This splits the problem into two sub-problems of about equal size and then combines their solutions. The required stack depth is greatly reduced and grows logarithmically instead of linearly regarding to the input size. The trick here is to make the first sub-string size be a multiple of 76 characters to avoid inserting additional newlines.
使用“分而治之”模式,例如:
注意:MSXSL 4 在 XHTML 格式 (1.4 MB) 在我的机器上只需 2 秒。
Use "Divide and Conquer" pattern like:
Note: MSXSL 4 splits XSLT 2.0 spec in XHTML format (1.4 MB) in 2 seconds on my machine.