Ecco una soluzione che utilizza XSLT2, nel quale nodo-set sono oggetti di prima classe. In XSLT1 avresti bisogno di usare un'estensione set-nodo.
Spiegazione di seguito:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="extendedItems" as="xs:integer*">
<xsl:for-each select="//Item">
<xsl:value-of select="./Price * ./Quantity"/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="total">
<xsl:value-of select="sum($extendedItems)"/>
</xsl:variable>
<xsl:template match="//QuantityTotal">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:value-of select="$total"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
L'approccio è quello di utilizzare un "Identità trasformare" per copiare il documento, durante l'esecuzione dei calcoli e inserire il risultato in uscita modello QuantityTotal. Il primo modello copia l'input nell'output ma viene sovrascritto da un modello più specifico per QuantityTotal nella parte inferiore. La prima dichiarazione di variabile crea un elenco di costi estesi e la seconda definizione di variabile somma i costi per produrre il totale. Il totale viene quindi inserito nel nodo Quantità totale.
La chiave per comprendere XSL è che è dichiarativa in natura. L'errore concettuale più comune fatto da quasi tutti i principianti è quello di assumere che il foglio di stile sia un programma sequenziale che elabora il documento XML di input. In realtà è il contrario. Il motore XSL legge il documento XML. e per ogni nuovo tag che incontra, appare nel foglio di stile per la corrispondenza "migliore", eseguendo quel modello.
EDIT:
Ecco una versione che funziona con xslt1.1 Sassone 6,5
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ex="http://exslt.org/common"
extension-element-prefixes="ex"
version="1.1">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="extendedItems">
<xsl:for-each select="//Item">
<extended>
<xsl:value-of select="./Price * ./Quantity"/>
</extended>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="total">
<xsl:value-of select="sum(ex:node-set($extendedItems/extended))"/>
</xsl:variable>
<xsl:template match="//QuantityTotal">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:value-of select="$total"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
fonte
2010-08-27 01:42:59
+1 bella domanda –
Buona domanda (+1). Vedere la mia risposta per le soluzioni sia in XSLT 1.0 (senza estensioni necessarie), sia XSLT 2.0 –
Vedere anche http://stackoverflow.com/questions/436998/multiply-2-numbers-and-then-sum-with-xslt e http : // StackOverflow.it/questions/1333558/xslt-to-sum-product-of-two-attributes – harpo