2009-03-15 3 views
2

У меня есть файл XML, где число разделяются запятойСуммирование чисел с запятой в виде десятичного разделителя в XSLT?

<foo> 
    <bar val="1,23"/> 
    <bar val="4,56"/> 
    <bar val="7,89"/> 
</foo> 

Я хотел бы сделать сумму более /foo/bar/@val значений в XSLT, но я немного застрял форматирование. Кто-нибудь знает, какой будет правильный синтаксис?

ответ

6

Я предполагаю, что значение, указанное в атрибуте "val", представляет собой число, которое имеет запятую вместо десятичной точки.

несколько решений возможны:

И. XSLT 1.0

Это преобразование:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common" 
> 
    <xsl:output method="text"/> 
<!--           --> 
    <xsl:template match="foo"> 
     <xsl:variable name="vrtfBars"> 
     <xsl:for-each select="bar"> 
      <bar val="{translate(@val, ',', '.')}"/> 
     </xsl:for-each> 
     </xsl:variable> 
<!--           --> 
     <xsl:value-of select= 
     "sum(ext:node-set($vrtfBars)/*/@val)"/> 
    </xsl:template> 
</xsl:stylesheet> 

при нанесении на первоначально предоставленного XML документа:

<foo> 
    <bar val="1,23"/> 
    <bar val="4,56"/> 
    <bar val="7,89"/> 
</foo> 

производит желаемого результата:

13.68 

II. XSLT-2,0

Это преобразование:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
exclude-result-prefixes="f xs" 
> 
<xsl:output method="text"/> 
<!--           --> 
<xsl:template match="foo"> 
    <xsl:sequence select= 
    "sum(bar/@val/number(translate(., ',', '.')))" 
    /> 
</xsl:template> 
</xsl:stylesheet> 

при нанесении на том же самом документе XML, производит тот же самый правильный результат:

13,68

III. FXSL 2.x

Это преобразование:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:f="http://fxsl.sf.net/" 
xmlns:my="my:fun" 
exclude-result-prefixes="my f xs" 
> 
    <xsl:import href="../f/func-transform-and-sum.xsl"/> 
<!--           --> 
<xsl:output method="text"/> 
<!--           --> 
<xsl:template match="foo"> 
    <xsl:sequence select= 
    "sum(
     f:transform-and-sum(my:makeNum(), bar/@val) 
     )" 
    /> 
</xsl:template> 
<!--           --> 
<xsl:function name="my:makeNum" as="xs:double"> 
    <xsl:param name="psNum" as="xs:string"/> 
<!--           --> 
    <xsl:sequence select="number(translate($psNum, ',', '.'))"/> 
</xsl:function> 
<!--           --> 
<xsl:function name="my:makeNum" as="element()"> 
    <my:makeNum/> 
</xsl:function> 
<!--           --> 
<xsl:template match="my:makeNum" as="xs:double" mode="f:FXSL"> 
    <xsl:param name="arg1" as="xs:string"/> 
<!--           --> 
    <xsl:sequence select="my:makeNum($arg1)"/> 
</xsl:template> 
</xsl:stylesheet> 

при нанесении на том же самом документе XML производит тот же самый правильный результат:

13,68

Последнее решение является более гибким и может быть успешно использован, когда более Для суммирования требуется преобразование значений plex.

+0

Большое спасибо за очень точный ответ :-) –

2

Я чувствую, что говорю это много, но он повторяет: вся суть XML заключается в том, что он предоставляет данные в легко анализируемой форме. XML, который содержит данные, которые не могут быть проанализированы как XML, не имеет смысла; если это вообще возможно, вы должны либо исправить свой XML, либо использовать другой формат.

+1

Но много в мире использует для десятичного разделителя. Почему . быть единственным, разрешенным? –

+0

Роберт, я полностью согласен с тобой. Тем не менее, в моем случае файлы XML создаются сторонним приложением, которое я не контролирую. –

+1

Единственный десятичный разделитель, поддерживаемый функцией XSLT number(), равен «.». –

3

Предполагая то же, что и Dimitre, это означает, что запятая используется как разделитель десятичной дроби, а не как разделитель для списка целых чисел.

Pure XSLT 1.0 без EXSLT узла расширения множества:

<xsl:template match="foo"> 
    <xsl:call-template name="sum"> 
    <xsl:with-param name="node" select="bar[1]"/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="sum"> 
    <xsl:param name="node"/> 
    <xsl:param name="sum" select="0"/> 
    <xsl:choose> 
    <xsl:when test="$node"> 
     <xsl:call-template name="sum"> 
     <xsl:with-param name="node" select="$node/following-sibling::bar[1]"/> 
     <xsl:with-param name="sum" select="$sum + translate($node/@val, ',', '.')"/> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="$sum"/> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
Смежные вопросы