Это гораздо более короткое преобразование:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="text()" name="sumStringList">
<xsl:param name="pText" select="."/>
<xsl:param name="pSum" select="0"/>
<xsl:param name="pDelim" select="','"/>
<xsl:choose>
<xsl:when test="not(string-length($pText) >0)">
<xsl:value-of select="$pSum"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vnewList"
select="concat($pText,$pDelim)"/>
<xsl:variable name="vHead" select=
"substring-before($vnewList, $pDelim)"/>
<xsl:call-template name="sumStringList">
<xsl:with-param name="pText" select=
"substring-after($pText, $pDelim)"/>
<xsl:with-param name="pSum" select="$pSum+$vHead"/>
<xsl:with-param name="pDelim" select="$pDelim"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
при применении к следующему документу XML :
<t>1,2,5,12,3</t>
дает желаемый, правильный результат :
23
Объяснение : рекурсивно вызванный именованный шаблон, который также соответствует текстовому узлу. Часовой (добавленная запятая) добавлен для ускорения и оптимизации обработки.
II. Решение XSLT 2.0 :
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:param name="pDelim" select="','"/>
<xsl:template match="text()">
<xsl:sequence select=
"sum(for $s in tokenize(.,$pDelim)
return number($s)
)
"/>
</xsl:template>
</xsl:stylesheet>
При применении к одному и тому же XML-документу (см. Выше) это преобразование дает тот же требуемый правильный ответ :
23
Здесь мы используем стандартную функцию XPath 2.0 tokenize()
, и мы должны преобразовать каждый полученный токен в число (используя number()
) до окончательного применения стандартной функции XPath sum()
.