XSL 中的零宽度 space 给出计算器错误
Zero width space in XSL gives stackoverflow error
我使用的是 FOP 1.1,我的文本最多可以包含 20,000 个字符,并且由于中间的文本不包含任何 space,因此修改了 xsl 以使用零宽度 space。如果 xml 标签包含大约 1500 个字符,它工作正常,如果超过这个数量,我将收到堆栈溢出错误。 weblogic 服务器中的堆 Space 也是 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 < (string-length($data))">
<xsl:value-of select='concat(substring($data,$counter,1),"​")'/>
<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),"​")'/>
<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>
下面是我遇到的错误 -
Caused by: java.lang.WhosebugError at
org.apache.xml.utils.FastStringBuffer.append(FastStringBuffer.java:499)
at
org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.getNodeData(DOM2DTM.java:935)
at
org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.getNodeData(DOM2DTM.java:928)
at
org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.getStringValue(DOM2DTM.java:827)
at
org.apache.xpath.objects.XNodeSet.getStringFromNode(XNodeSet.java:217)
at org.apache.xpath.objects.XNodeSet.xstr(XNodeSet.java:256) at
org.apache.xpath.functions.FunctionDef1Arg.getArg0AsString(FunctionDef1Arg.java:97)
at
org.apache.xpath.functions.FuncStringLength.execute(FuncStringLength.java:45)
at 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
org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2400)
at
org.apache.xalan.templates.ElemTemplate.execute(ElemTemplate.java:394)
at
org.apache.xalan.templates.ElemCallTemplate.execute(ElemCallTemplate.java:248)
我对这里需要两个模板感到困惑,因为您可以将逻辑合二为一,就像这样
<xsl:template name="zero_width_space_1">
<xsl:param name="data"/>
<xsl:param name="counter" select="0"/>
<xsl:if test="$counter <= (string-length($data))">
<xsl:value-of select='concat(substring($data,$counter,1),"​")'/>
<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>
我不确定这是否能解决您的堆栈溢出问题。但是,如果目的是在每个字符前插入一个 ​
,那么您可以使用 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('​', .)" />
</xsl:for-each>
<xsl:text>​</xsl:text>
</xsl:variable>
<func:result select="$result" />
</func:function>
我使用的是 FOP 1.1,我的文本最多可以包含 20,000 个字符,并且由于中间的文本不包含任何 space,因此修改了 xsl 以使用零宽度 space。如果 xml 标签包含大约 1500 个字符,它工作正常,如果超过这个数量,我将收到堆栈溢出错误。 weblogic 服务器中的堆 Space 也是 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 < (string-length($data))">
<xsl:value-of select='concat(substring($data,$counter,1),"​")'/>
<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),"​")'/>
<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>
下面是我遇到的错误 -
Caused by: java.lang.WhosebugError at org.apache.xml.utils.FastStringBuffer.append(FastStringBuffer.java:499) at org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.getNodeData(DOM2DTM.java:935) at org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.getNodeData(DOM2DTM.java:928) at org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.getStringValue(DOM2DTM.java:827) at org.apache.xpath.objects.XNodeSet.getStringFromNode(XNodeSet.java:217) at org.apache.xpath.objects.XNodeSet.xstr(XNodeSet.java:256) at org.apache.xpath.functions.FunctionDef1Arg.getArg0AsString(FunctionDef1Arg.java:97) at org.apache.xpath.functions.FuncStringLength.execute(FuncStringLength.java:45) at 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 org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2400) at org.apache.xalan.templates.ElemTemplate.execute(ElemTemplate.java:394) at org.apache.xalan.templates.ElemCallTemplate.execute(ElemCallTemplate.java:248)
我对这里需要两个模板感到困惑,因为您可以将逻辑合二为一,就像这样
<xsl:template name="zero_width_space_1">
<xsl:param name="data"/>
<xsl:param name="counter" select="0"/>
<xsl:if test="$counter <= (string-length($data))">
<xsl:value-of select='concat(substring($data,$counter,1),"​")'/>
<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>
我不确定这是否能解决您的堆栈溢出问题。但是,如果目的是在每个字符前插入一个 ​
,那么您可以使用 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('​', .)" />
</xsl:for-each>
<xsl:text>​</xsl:text>
</xsl:variable>
<func:result select="$result" />
</func:function>