2017-04-12 2 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>ノードの1つの特定のペアを図示)。

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

はい。これは、最小のカプセル化ノードになります。ほとんどの場合、 ''ノードは数十12個の ''ノードで構成されています。 – fildpauz

+1

サクソン9または6か、なぜgenerate-idが必要だと思うのですか?それがパフォーマンスの問題の原因です。 Saxon 9を使用する場合は、問題の原因となるコード(http://saxonica.com/html/documentation/using-xsl/performanceanalysis/を参照)をプロファイルしてください。もちろん、XSLT 2の ':: C [generate-id(。)= generate-id($ end-node)] 'というチェックは、' following :: C [1] is $ end-node'と書くことができます。 XSLT 2.0には、他のアプローチでは '<<' and '>>'演算子と 'for-each-group group-starting/ending-with'があります。 –

答えて

1

要素を開始ノードと終了ノードの間に挿入することを避けるために、generate-id()は必要ありません。あなたはidの属性で最初に<C>要素をマッチさせています。もっと直接的にそれを使用しない理由はありません。ドキュメント内で一意であることが<C>要素@id Sに頼ることができるかどうかたとえば、

<?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]位置述語を除去することによって、これを簡素化することができます。

実際にgenerate-id()がパフォーマンス上の問題の第1の原因である場合は、それを避けることが大いに重要です。

関連する問題