Domanda

Sto usando il codice XSL 2.0 di seguito per trovare gli ID dei nodi di testo che contiene l'elenco degli indici che do come input. Il codice funziona perfettamente ma in termini di prestazioni impiega molto tempo per file enormi. Anche per file enormi se i valori dell'indice sono piccoli, quindi il risultato è rapido in pochi ms. Sto usando il processore Saxon9He Java per eseguire 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> 

Nella soluzione sopra se il valore dell'indice è troppo enorme, diciamo 270962, il tempo impiegato per l'esecuzione di XSL è di 83427ms. In file enormi se il valore dell'indice è enorme per esempio 4605415, 4605431 ci vogliono diversi minuti per essere eseguiti. Sembra che il calcolo della variabile "Insert-Data" richiede tempo sebbene sia una variabile globale e calcolata una sola volta. L'XSL dovrebbe essere aggiunto o il processore? Come posso migliorare le prestazioni dell'XSL.

È stato utile?

Soluzione

Immagino che il problema sia la generazione di text-id, cioè l'espressione

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

Stai potenzialmente ricalcolando molte somme qui. Penso che il percorso più semplice qui sarebbe quello di invertire il tuo approccio: ricorrere attraverso i nodi di testo nel documento, aggregare la lunghezza della stringa finora e output data elementi ogni volta che un nuovo @index è raggiunto. Il seguente esempio illustra l'approccio. Nota che ogni unico @index e ogni nodo di testo viene visitato una sola volta.

<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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top