He aquí una solución utilizando XSLT2, en el que conjuntos de nodos son objetos de primera clase. En XSLT1 necesitaría usar una extensión de conjunto de nodos.
Explicación continuación:
<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>
El enfoque aquí es el uso de una "identidad transformar" para copiar el documento, mientras que la realización de los cálculos e insertar el resultado en la plantilla QuantityTotal salida. La primera plantilla copia la entrada al resultado, pero se reemplaza por una plantilla más específica para QuantityTotal en la parte inferior. La primera declaración de variable crea una lista de costos extendidos, y la segunda definición de variable suma los costos para producir el total. El total se inserta en el nodo QuantityTotal.
La clave para entender XSL es que es de carácter declarativo. El error conceptual más común que cometen casi todos los principiantes es suponer que la hoja de estilo es un programa secuencial que procesa el documento XML de entrada. En realidad, es al revés. El motor XSL lee el documento XML. y para cada nueva etiqueta que encuentra se ve en la hoja de estilo para la "mejor" coincidencia, ejecutando esa plantilla.
EDIT:
Aquí hay una versión que funciona con xslt1.1 Saxon 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>
+1 buena pregunta –
Buena pregunta (+1). Vea mi respuesta para las soluciones en XSLT 1.0 (no se requieren extensiones) y XSLT 2.0 –
Vea también http://stackoverflow.com/questions/436998/multiply-2-numeros-y- luego-sum-with-xslt y http ://desbordamiento de pila.com/questions/1333558/xslt-to-suma-producto-de-dos-atributos – harpo