Вот решение, использующее XSLT2, в котором наборы узлов являются объектами первого класса.В XSLT1 вам необходимо использовать расширение набора узлов.
Объяснение ниже:
<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>
Подход здесь заключается в использовании «преобразования идентичности» для копирования документа во время выполнениярасчеты и вставка результата в выходной шаблон QuantityTotal.Первый шаблон копирует входные данные в выходные данные, но переопределяется более конкретным шаблоном для QuantityTotal внизу.Объявление первой переменной создает список расширенных затрат, а определение второй переменной суммирует затраты для получения итоговой суммы.Затем итоговое значение вставляется в узел QuantityTotal.
Ключом к пониманию XSL является его декларативный характер.Наиболее распространенная концептуальная ошибка, допущенная почти всеми новичками, заключается в предположении, что таблица стилей является последовательной программой, которая обрабатывает входной XML-документ.На самом деле все наоборот.Механизм XSL читает документ XML.и для каждого нового тега он ищет в таблице стилей «лучшее» соответствие, выполняя этот шаблон.
РЕДАКТИРОВАНИЕ:
Вот версия 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>