2010-05-13 7 views
3

J'utilise le code XSL 2.0 ci-dessous pour trouver les identifiants des nœuds de texte contenant la liste d'indices que je donne en entrée. Le code fonctionne parfaitement, mais en termes de performances, il prend beaucoup de temps pour les fichiers volumineux. Même pour les gros fichiers si les valeurs d'index sont petites, le résultat est rapide en quelques ms. J'utilise le processeur Java saxon9he pour exécuter le XSL.Amélioration des performances de 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> 

Dans la solution ci-dessus si la valeur de l'indice est trop grand alors le dire 270962 temps pris pour l'exécuter est XSL pour 83427ms. Dans les fichiers énormes si la valeur de l'index est énorme, disons 4605415, 4605431, il faut plusieurs minutes pour l'exécuter. Semble le calcul de la variable "insert-data" prend du temps mais c'est une variable globale et calculée une seule fois. Faut-il ajouter le XSL ou le processeur? Comment puis-je améliorer les performances du XSL.

Répondre

2

Je suppose que le problème est la génération de text-id, à savoir l'expression

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

Vous Recalcul potentiellement beaucoup de sommes ici. Je pense que le chemin le plus simple ici serait d'inverser votre approche: recurse à travers les nœuds de texte dans le document, agréger la longueur de la chaîne jusqu'à présent, et data éléments de sortie chaque fois qu'un nouveau @index est atteint. L'exemple suivant illustre l'approche. Notez que chaque @index unique et chaque nœud de texte n'est visité qu'une seule fois.

<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

Merci pour votre reposnse. Je vais essayer cela et mettre à jour bientôt. – Rachel

+1

Super, la réponse est en quelques ms. Il a été réduit de 82242 à 813. Merci beaucoup! La valeur du noeud "data" seul ne figure pas dans le résultat. Ligne: qui est en cours de lecture, . – Rachel

+1

@Rachel: C'est bon d'entendre que votre temps de réponse s'est amélioré. Il y avait un bogue dans ma définition de clé originale, vous devez utiliser '' pour obtenir des résultats corrects. – markusk

Questions connexes