2017-04-12 32 views
1

我有一个包含带注释的语音转录本的大型xml文档。以下是一个简短的片段。generate-id()对于大文档来说太慢

<?xml version="1.0" encoding="UTF-8"?> 
<U> 
    <A/> 
    <C type="start" id="cb01s"/> 
    <P/> 
    <T>a</T> 
    <T>woman</T> 
    <P/> 
    <T>took</T> 
    <T>off</T> 
    <T>the</T> 
    <T>train</T> 
    <C type="end" id="cb02e"/> 
    <P/> 
    <T>but</T> 
    <P/> 
    <F/> 
    <RT> 
     <O> 
      <C type="start" id="cb03s"/> 
      <T>her</T> 
      <T>bag</T> 
      <P/> 
      <T>are</T> 
     </O> 
     <P/> 
     <E> 
      <C type="start" id="cb04s"/> 
      <T>her</T> 
      <T>bag</T> 
      <T>are</T> 
     </E> 
    </RT> 
    <P/> 
    <T>still</T> 
    <P/> 
    <T>in</T> 
    <T>the</T> 
    <T>train</T> 
    <C type="end" id="cb05e"/> 
    <PC>.</PC> 
</U> 

的基本任务,我需要做的是让某些对<C>节点之间<T>节点的数量。我已经使用下面的样式表片段来做到这一点(用一对特定的<C>节点来说明)。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" encoding="UTF-8"/> 

    <xsl:template match="U"> 
     <xsl:variable name="start-node" select="descendant::C[@id = 'cb01s']"/> 
     <xsl:variable name="end-node" select="descendant::C[@id = 'cb02e']"/> 
     <xsl:text>Result: </xsl:text> 
     <xsl:value-of select="count($start-node/following::T[following::C[generate-id(.) = generate-id($end-node)]])"/> 
    </xsl:template> 

</xsl:stylesheet> 

这适用于诸如上述短XML片段罚款,并给出正确的结果:Result: 6

但是,实际的XML文档包含成千上万个节点<C>甚至更​​多<T>节点。所以当我尝试在其上运行样式表时,结果慢慢地返回非常。 (这可能需要几天时间才能完成)。我想这个问题必须是在每次运行<xsl:value-of...行时,处理器(Saxon)正在检查所有<T>节点并为<C>节点生成id的倍数(即指数级)和这会降低一切。

有没有办法加快进程,同时仍然使用generate-id()?或者我需要使用一些替代方法来获取<T>节点的数量?

+0

所有''是否属于同一个''? – Tomalak

+0

是的。那将是最小的封装节点。在大多数情况下,一个''节点可能由几十个'节点组成。 – fildpauz

+1

是撒克逊9或6,或者你认为你为什么需要生成id,并且它是性能问题的罪魁祸首。如果您使用Saxon 9,那么问题来自代码的配置文件(请参阅http://saxonica.com/html/documentation/using-xsl/performanceanalysis/)。当然,在XSLT 2中,检查'following :: C [generate-id(。)= generate-id($ end-node)]'可以被写为'following :: C [1]'是$ end-node' 。对于其他方法,XSLT 2.0也具有'<<' and '>>'运算符和'对于每个组的组'开始/结束'。 –

回答

1

您不需要generate-id()只是为了避免匹配<C>元素插入开始和结束节点之间。您首先匹配<C>元素的id属性,我认为没有理由不直接使用它。例如,

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" encoding="UTF-8"/> 

    <xsl:template match="U"> 
     <xsl:variable name="start-id" select="cb01s"/> 
     <xsl:variable name="end-id" select="cb02e"/> 

     <xsl:text>Result: </xsl:text> 
     <xsl:value-of select="count(descendant::C[@id = $start-id]/following::T[following::C[@id = $end-id][1]])"/> 
    </xsl:template> 

</xsl:stylesheet> 

您可以通过删除[1]位置谓词,如果你能依靠<C>元素@id使他能在文档中独一无二的简化。

如果generate-id()确实是您的性能问题的主要原因,那么完全避免它应该提供一个很大的提升。

相关问题