Добавление чисел в строку с использованием XSLT - PullRequest
3 голосов
/ 01 мая 2011

У меня есть строка (в переменной), в которой есть список чисел, разделенных пробелом или запятой. Мне нужно сложить числа в строке. пример строки "1,2,5,12,3" или "1 2 5 12 3"

Есть ли способ добавить числа в строку и вернуть сумму?

Ответы [ 3 ]

3 голосов
/ 01 мая 2011

Это гораздо более короткое преобразование:

<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().

0 голосов
/ 01 мая 2011

Вот решение XSLT 1.0

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:template match="/">

        <xsl:variable name="listOfValues" select="'1,2,5,12,3'" />

        <xsl:call-template name="splitAndAdd">
            <xsl:with-param name="list" select="$listOfValues"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="splitAndAdd">
        <xsl:param name="list" />
        <xsl:param name="delimiter" select="','"/>
        <xsl:param name="total" select="0" />

        <xsl:variable name="newList">
            <xsl:choose>
                <xsl:when test="contains($list, $delimiter)">
                    <xsl:value-of select="normalize-space($list)"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="concat(normalize-space($list),$delimiter)" />
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>

        <xsl:variable name="token" 
                      select="substring-before($newList, $delimiter)" />
        <xsl:variable name="remaining" 
                      select="normalize-space(substring-after($newList, $delimiter))" />

        <xsl:variable name="newTotal" select="$total + number($token)" />

        <xsl:choose>
            <xsl:when test="$remaining">
                <xsl:call-template name="splitAndAdd">
                    <xsl:with-param name="delimiter" select="$delimiter"/>
                    <xsl:with-param name="list" select="$remaining"/>
                    <xsl:with-param name="total" select="$newTotal" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$newTotal" />
            </xsl:otherwise>
        </xsl:choose>     

    </xsl:template>

</xsl:stylesheet>
0 голосов
/ 01 мая 2011

Я не знаю XSLT, но обычно вы разделяете строку, используя пробелы и запятые в качестве разделителей.
После быстрого поиска я обнаружил, что вы можете использовать tokenize (string, separator) в качестве функции разделения, если вы используете XSLT 2.0. Эта страница содержит пример использования tokenize .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...