大家好,我一直在尝试使用eclipse和saxon来转换这个xml数据,但当我尝试使用saxonxslt2.0进行转换时,我遇到了一个内存错误,我在eclipse.ini中增加了内存,但不看,我试图更改的xml是500M。如果我使用默认的eclipsexslt转换运行它,它会运行没有错误的打印,我会返回一个没有节点和一个url的xml修改正确,但没有在节点中,也没有其他数据,我是不是遗漏了什么?
这是xsl文件:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="replacedURL">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="/products/product/buy_link/text()"/>
<xsl:with-param name="replace" select="'[[PARTNERID]]'"/>
<xsl:with-param name="by" select="'12345'"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$replacedURL"/>
</xsl:template>
<xsl:template name="string-replace-all">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="by"/>
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:value-of select="$by"/>
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
基元递归转换通常会以堆栈溢出异常结束(通常使用N个嵌套递归调用,其中N约为1000)。
在XSLT2.0中,使用最高效的、基于RegEx的XPath 2.0函数replace()
。
这里有一个小例子:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<t><xsl:sequence select=
"replace(., '[[PARTNERID]]', '12345')"/>
</t>
</xsl:template>
</xsl:stylesheet>
当此转换应用于以下XML文档时:
<t>dadasdas [[PARTNERID]] sfsdfsffs [[PARTNERID]] sdsdfffsdf [[PARTNERID]]</t>
生成所需的正确结果:
<t>dadasdas 12345 sfsdfsffs 12345 sdsdfffsdf 12345</t>
解释:
RegEx处理使用常规自动机,它只需要有限的内存(用于自动机),而基于堆栈的处理则在堆栈上的每次"推送"时消耗更多的内存。
如果您希望得到的XML在其他方面与输入相同,只是对某些节点进行了一些特定的更改,最简单的方法是创建如下样式表:
- 使用标识转换将输入原样复制到输出,然后
- 有选择地覆盖要更改的节点的模板
在这种情况下,将输入XML原样复制到输出,只在匹配XPath表达式/products/product/buy_link/text()
的节点中应用字符串替换,如下所示:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- the identity template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/products/product/buy_link/text()">
<xsl:variable name="replacedURL">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="replace" select="'[[PARTNERID]]'"/>
<xsl:with-param name="by" select="'12345'"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$replacedURL"/>
</xsl:template>
<xsl:template name="string-replace-all">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="by"/>
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:value-of select="$by"/>
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>