2010-05-13 30 views
3

我使用下面的XSL 2.0代码来查找包含我给出的索引列表的文本节点的ID。该代码完美地工作,但对于性能而言,对于大型文件来说花费很长时间。即使对于大文件,如果索引值很小,那么结果在几毫秒内就会很快。我正在使用saxon9he Java处理器来执行XSL。提高XSL的性能

<xsl:variable name="insert-data" as="element(data)*"> 
    <xsl:for-each-group 
    select="doc($insert-file)/insert-data/data" 
    group-by="xsd:integer(@index)"> 
    <xsl:sort select="current-grouping-key()"/> 
    <data 
     index="{current-grouping-key()}" 
     text-id="{generate-id(
     $main-root/descendant::text()[ 
      sum((preceding::text(), .)/string-length(.)) ge current-grouping-key() 
     ][1] 
    )}"> 
     <xsl:copy-of select="current-group()/node()"/> 
    </data> 
    </xsl:for-each-group> 
</xsl:variable> 

在上面的解决方案,如果该指标值过于庞大说270962则采取了XSL执行的时间为83427ms。在大文件中,如果索引值很大,则表示4605415,4605431需要几分钟才能执行。似乎计算变量“插入数据”需要时间,尽管它是一个全局变量并且只计算一次。 XSL应该被添加还是处理器?我如何提高XSL的性能?

回答

2

我想这个问题是text-id产生,即表达

 
generate-id(
    $main-root/descendant::text()[ 
     sum((preceding::text(), .)/string-length(.)) ge current-grouping-key() 
    ][1] 
) 

您可能重新计算了不少款项在这里。我认为这里最简单的路径是颠倒你的方法:遍历文档中的文本节点,将字符串长度聚合到目前为止,并在每次达到新的@index时输出data元素。以下示例说明了该方法。请注意,每个唯一的@index和每个文本节点只被访问一次。

<xsl:variable name="insert-doc" select="doc($insert-file)"/> 

<xsl:variable name="insert-data" as="element(data)*"> 
    <xsl:call-template name="calculate-data"/> 
</xsl:variable> 

<xsl:key name="index" match="data" use="xsd:integer(@index)"/> 

<xsl:template name="calculate-data"> 
    <xsl:param name="text-nodes" select="$main-root//text()"/> 
    <xsl:param name="previous-lengths" select="0"/> 
    <xsl:param name="indexes" as="xsd:integer*"> 
     <xsl:perform-sort 
      select="distinct-values(
        $insert-doc/insert-data/data/@index/xsd:integer(.))"> 
      <xsl:sort/> 
     </xsl:perform-sort> 
    </xsl:param> 
    <xsl:if test="$text-nodes"> 
     <xsl:variable name="total-lengths" 
      select="$previous-lengths + string-length($text-nodes[1])"/> 
     <xsl:choose> 
      <xsl:when test="$total-lengths ge number($indexes[1])"> 
       <data 
        index="{$indexes[1]}" 
        text-id="{generate-id($text-nodes[1])}"> 
        <xsl:copy-of select="key('index', $indexes[1], 
              $insert-doc)"/> 
       </data> 
       <!-- Recursively move to the next index. --> 
       <xsl:call-template name="calculate-data"> 
        <xsl:with-param 
         name="text-nodes" 
         select="$text-nodes"/> 
        <xsl:with-param 
         name="previous-lengths" 
         select="$previous-lengths"/> 
        <xsl:with-param 
         name="indexes" 
         select="subsequence($indexes, 2)"/> 
       </xsl:call-template>      
      </xsl:when> 
      <xsl:otherwise> 
       <!-- Recursively move to the text node. --> 
       <xsl:call-template name="calculate-data"> 
        <xsl:with-param 
         name="text-nodes" 
         select="subsequence($text-nodes, 2)"/> 
        <xsl:with-param 
         name="previous-lengths" 
         select="$total-lengths"/> 
        <xsl:with-param 
         name="indexes" 
         select="$indexes"/> 
       </xsl:call-template>      
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:if> 
</xsl:template> 
+0

感谢您的回购。将尽快尝试并更新。 – Rachel 2010-05-13 20:29:29

+1

太棒了,反应在几毫秒内。它已经从82242减少到813.非常感谢!结果中不包含“数据”节点的值。行:正在读取,。 – Rachel 2010-05-13 20:54:13

+1

@Rachel:很高兴听到您的回复时间有所改善。我的原始键定义中存在一个错误,您需要使用''来获得正确的结果。 – markusk 2010-05-13 21:07:16