XSLT的改进

时间:2014-04-04 08:38:06

标签: xml performance xslt xslt-1.0 muenchian-grouping

我有2个示例xml文件

<?xml version="1.0" encoding="UTF-8"?> 
<foobar>
<foo>ONE</foo>  
<bar>a</bar> 
</foobar>

<?xml version="1.0" encoding="UTF-8"?> 
<foobar>
<foo>ONE</foo>
<foo>two</foo>  
<bar>a</bar> 
</foobar>

第一个xml的所需输出与输入相同。 第二个xml示例是

<foobar>
<s>
<s>
<foo>ONE</foo>
<foo>two<foo> 
</s>
<s>
<bar>a</bar>
</s>
</s>
</foobar>

我有一个xslt文件,它将元素序列放在&#34; s&#34;否则输出相同的xml文件。

我的xslt是 -

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output indent="yes"/>

 <xsl:key name="kGroupLeader" match="*" 
         use="generate-id(self::*[name() != name(preceding-sibling::*[1])])" />

 <xsl:key name ="checkgroup" match="*" use ="self::*[name() = name(preceding-sibling::*[1])]" />

<xsl:template match="*[*]">
    <xsl:copy>

   <xsl:choose>
<xsl:when test="(key('checkgroup',*))">
    <s>
     <xsl:for-each select="*[key('kGroupLeader', generate-id())]">
          <s>
            <xsl:apply-templates select=". | following-sibling::*[
                  name() = name(current())
                  and generate-id(current()) = generate-id(
                    preceding-sibling::*[key('kGroupLeader', generate-id())][1]
                  )
                ]" />
          </s>
        </xsl:for-each>
   </s>
   </xsl:when>
    <xsl:otherwise>
  <xsl:copy-of select="."/>
    </xsl:otherwise>
  </xsl:choose>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

它运行正常。但是它占用了大量内存并且需要花费大量时间来处理大型xml文件。如何提高性能以使我的xslt更快?

1 个答案:

答案 0 :(得分:1)

不是使用密钥,另一种方法可能是使用尾递归模板来实现一种&#34; while循环&#34;:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes" />

  <!-- normal case - identity transform -->
  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
  </xsl:template>

  <!-- for elements that contain adjacent child elements with the same name -->
  <xsl:template match="*[*[name() = name(preceding-sibling::*[1])]]">
    <xsl:copy>
      <!-- wrap contents in an s -->
      <s>
        <!-- wrap each "run" of consecutive elements with the same name in
             another s.  We do this by applying "seq" mode templates to
             the _first_ element in each run. -->
        <xsl:for-each select="*[name() != name(preceding-sibling::*[1])]">
          <s><xsl:apply-templates select="." mode="seq" /></s>
        </xsl:for-each>
      </s>
    </xsl:copy>
  </xsl:template>

  <!-- tail recursion - process self with normal mode templates, then recurse
       with this template for next sibling if its name matches mine -->
  <xsl:template match="*" mode="seq">
    <xsl:apply-templates select="." />
    <xsl:apply-templates mode="seq"
       select="following-sibling::*[1][name() = name(current())]" />
  </xsl:template>
</xsl:stylesheet>

尾递归seq模式模板实际上是一个循环,用于保持处理元素(使用默认模式模板),直到找到具有不同名称的模板。