1

嗨,伙计们,我一直在尝试使用 eclipse 也使用 saxon 来转换这个 xml 数据,但是当我尝试使用 saxon xslt2.0 进行转换时,我得到一个内存错误,我在 eclipse.ini 中增加了内存,但没有看 xml 我试图如果我使用默认的 eclipse xslt 转换运行它,alter 为 500M,它运行打印完成且没有错误,我返回一个没有节点的 xml,并且一个 url 正确更改但没有在节点中,并且没有其他数据我在这里遗漏了什么吗?

这是 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>
4

2 回答 2

1

原始递归转换通常会以堆栈溢出异常结束(通常有 N 次嵌套递归调用,其中 N 约为 1000)。

在 XSLT 2.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 处理使用常规自动机,它只需要有限数量的内存(用于自动机),这与基于堆栈的处理不同,后者在堆栈上的每次“推送”时消耗更多内存。

于 2012-07-26T22:52:16.417 回答
1

如果您希望生成的 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>
于 2012-08-01T14:29:02.790 回答