对于大型文档

时间:2017-04-12 11:56:09

标签: xslt

我有一个包含带注释的语音记录的大型xml文档。以下是一个简短的片段。

<?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>

我需要做的基本任务是获取某些<T>个节点对之间<C>个节点的数量。我使用了以下样式表片段来执行此操作(使用一对特定的<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>个节点并为{{生成id' 1}}节点倍数倍(即指数),这会减慢一切。

有没有办法在使用generate-id()的同时加快进程?或者我是否需要使用其他方法获取<C>个节点的数量?

1 个答案:

答案 0 :(得分: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()确实是导致性能问题的主要原因,那么完全避免它应该会提供很大的推动力。