XSL中的零宽度空间给出了stackoverflow错误

时间:2017-10-26 07:39:49

标签: java xml xslt xsl-fo apache-fop

我正在使用FOP 1.1,我有一个文本,最多可以包含20,000个字符,因为文本中不包含任何空格,修改了xsl以使用零宽度空间。如果xml标记包含大约1500个字符,它可以正常工作,如果它超过我的堆栈溢出错误。 weblogic服务器中的堆空间也是2 GB。 任何人都可以通过可能的解决方法或xsl中存在任何缺陷来帮助解决这个问题。

以下是xsl代码示例 -

    <xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fo="http://www.w3.org/1999/XSL/Format"
    xmlns:locale="xalan://java.util.Locale" 
    xmlns:arrayList="xalan://java.util.ArrayList" 
    xmlns:func="http://exslt.org/functions" extension-element-prefixes="func"
    version="1.0">

..................




     <fo:block>
        <xsl:value-of select="func:callTemplate(summaryData)"/>
        </fo:block>

..................
    <xsl:template name="zero_width_space_1">
            <xsl:param name="data"/>
            <xsl:param name="counter" select="0"/>
            <xsl:choose>
                <xsl:when test="$counter &lt; (string-length($data))">
                    <xsl:value-of select='concat(substring($data,$counter,1),"&#8203;")'/>
                    <xsl:call-template name="zero_width_space_2">
                        <xsl:with-param name="data" select="$data"/>
                        <xsl:with-param name="counter" select="$counter+1"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>

        <xsl:template name="zero_width_space_2">
            <xsl:param name="data"/>
            <xsl:param name="counter"/>
            <xsl:value-of select='concat(substring($data,$counter,1),"&#8203;")'/>
            <xsl:call-template name="zero_width_space_1">
                <xsl:with-param name="data" select="$data"/>
                <xsl:with-param name="counter" select="$counter+1"/>
            </xsl:call-template>
    </xsl:template>


        <func:function name="func:callTemplate">
            <xsl:param name="string1"/>
            <xsl:call-template name="zero_width_space_1">
                <xsl:with-param name="data" select="$string1"/>
            </xsl:call-template>
            <func:result/>
        </func:function>
</xsl:stylesheet>

以下是我得到的错误 -

  

引起:java.lang.StackOverflowError at   org.apache.xml.utils.FastStringBuffer.append(FastStringBuffer.java:499)     在   org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.getNodeData(DOM2DTM.java:935)     在   org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.getNodeData(DOM2DTM.java:928)     在   org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.getStringValue(DOM2DTM.java:827)     在   org.apache.xpath.objects.XNodeSet.getStringFromNode(XNodeSet.java:217)     在org.apache.xpath.objects.XNodeSet.xstr(XNodeSet.java:256)at   org.apache.xpath.functions.FunctionDef1Arg.getArg0AsString(FunctionDef1Arg.java:97)     在   org.apache.xpath.functions.FuncStringLength.execute(FuncStringLength.java:45)     在org.apache.xpath.Expression.execute(Expression.java:155)at   org.apache.xpath.operations.Operation.execute(Operation.java:110)at   org.apache.xpath.Expression.bool(Expression.java:186)at   org.apache.xpath.XPath.bool(XPath.java:412)at   org.apache.xalan.templates.ElemChoose.execute(ElemChoose.java:126)at at   org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2400)     在   org.apache.xalan.templates.ElemTemplate.execute(ElemTemplate.java:394)     在   org.apache.xalan.templates.ElemCallTemplate.execute(ElemCallTemplate.java:248)

1 个答案:

答案 0 :(得分:1)

我对这里需要两个模板感到困惑,因为你可以将逻辑组合成一个,就像这样

<xsl:template name="zero_width_space_1">
    <xsl:param name="data"/>
    <xsl:param name="counter" select="0"/>
    <xsl:if test="$counter &lt;= (string-length($data))">
        <xsl:value-of select='concat(substring($data,$counter,1),"&#8203;")'/>
        <xsl:call-template name="zero_width_space_1">
            <xsl:with-param name="data" select="$data"/>
            <xsl:with-param name="counter" select="$counter+1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

另请注意,您的功能不太正确,它应该看起来像这样......

<func:function name="func:callTemplate">
    <xsl:param name="string1"/>
    <xsl:variable name="result">
        <xsl:call-template name="zero_width_space_1">
            <xsl:with-param name="data" select="$string1"/>
        </xsl:call-template>
    </xsl:variable>
    <func:result select="$result" />
</func:function>    

我不确定这是否能解决您的堆栈溢出问题。但是,如果目的是在每个字符前插入&#8203;,那么您可以使用exslt中提供的tokenize函数

<func:function name="func:callTemplate">
    <xsl:param name="string1"/>
    <xsl:variable name="result">
        <xsl:for-each select="str:tokenize($string1, '')">
            <xsl:value-of select="concat('&#8203;', .)" />
        </xsl:for-each>
        <xsl:text>&#8203;</xsl:text>
    </xsl:variable>
    <func:result select="$result" />
</func:function>