xmlxsl-xslt-eclipse仅替换/返回1个值



大家好,我一直在尝试使用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在其他方面与输入相同,只是对某些节点进行了一些特定的更改,最简单的方法是创建如下样式表:

  1. 使用标识转换将输入原样复制到输出,然后
  2. 有选择地覆盖要更改的节点的模板

在这种情况下,将输入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>

最新更新