Гость
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / Сумма непустых элементов в рекурсии / 8 сообщений из 8, страница 1 из 1
20.04.2017, 14:36
    #39441636
adar7
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сумма непустых элементов в рекурсии
Используется XSLT 1.0. есть XML:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
<root>
<SUM_1>10<SUM_1>
<SUM_2>7<SUM_2>
<SUM_5><SUM_5>
<SUM_6>3<SUM_6>
<SUM_11>1<SUM_11>
<SUM_15>12<SUM_15>
<root>


Всего элементов SUM_<N> может быть 15. Могут присутствовать все, могут отсутствовать некоторые, некоторые могут быть пустыми.
Нужно посчитать сумму всех элементов. Знаю, что решается задача c помощью рекурсии, но дальнейшие продвижения по этой теме результата не дали. Помогите, пожалуйста.
...
Рейтинг: 0 / 0
20.04.2017, 14:38
    #39441638
adar7
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сумма непустых элементов в рекурсии
adar7,

извиняюсь, XML такой:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
<root>
<SUM_1>10</SUM_1>
<SUM_2>7</SUM_2>
<SUM_5></SUM_5>
<SUM_6>3</SUM_6>
<SUM_11>1</SUM_11>
<SUM_15>12</SUM_15>
</root>
...
Рейтинг: 0 / 0
20.04.2017, 14:39
    #39441640
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сумма непустых элементов в рекурсии
Код: xml
1.
2.
3.
<xsl:template match="root">
  <xsl:value-of select="sum(*)"/>
</xsl:template>
...
Рейтинг: 0 / 0
20.04.2017, 15:08
    #39441666
adar7
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сумма непустых элементов в рекурсии
_Vasilisk_,

спасибо, но реальный ХМL содержит другие элементы, где тоже есть числа. Хочется выбрать только элементы вида SUM_<N>.


Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output method="xml" version="1.0" encoding="utf-8" omit-xml-declaration="yes" indent="yes"/> 
    <xsl:template match="/">
        <root>  
            <xsl:element name="eps">
                <xsl:attribute name="name">NAZN.TOTAL_SUM</xsl:attribute>
                <xsl:variable name="total_sum">
                    <xsl:call-template name="sumParam">
                        <xsl:with-param name="count_service" select="15"/>
                    </xsl:call-template>
                </xsl:variable>                
                <xsl:call-template name="format_number">
                    <xsl:with-param name="number" select="$total_sum"/>
                </xsl:call-template>
           </xsl:element>
        </root>
    </xsl:template>
    <xsl:template name="format_number">
        <xsl:param name="number"/>
        <xsl:choose>
            <xsl:when test="not (normalize-space($number)) or string($number)='NaN'">
                <xsl:value-of select="'0.00'"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="format-number(translate($number, ',', '.'), '0.00')"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template name="sumParam">
        <xsl:param name="count_service"/>
        <xsl:param name="pAccum" select="0"/>        
        <xsl:choose>
            <xsl:when test="number($count_service) > 0">              
                <xsl:call-template name="sumParam">
                    <xsl:with-param name="count_service" select="$count_service - 1"/>
                    <xsl:with-param name="pAccum" select="$pAccum+ number(concat('/SUM_',$count_service))"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$pAccum"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>



результат:
Код: xml
1.
2.
3.
<root>
   <eps name="NAZN.TOTAL_SUM">0.00</eps>
</root>
...
Рейтинг: 0 / 0
21.04.2017, 08:09
    #39442003
adar7
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сумма непустых элементов в рекурсии
adar7,

в общем собрал решение, может кому пригодиться, но оно некрасивое с дублированием кода и без динамического вызова тегов <SUM_[N]>.
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output method="xml" version="1.0" encoding="utf-8" omit-xml-declaration="yes" indent="yes"/> 
    <xsl:template match="/">
        <root>  
            <xsl:element name="eps">
                <xsl:attribute name="name">NAZN.TOTAL_SUM</xsl:attribute>
                <xsl:variable name="total_sum">
                    <xsl:call-template name="sumParam">
                        <xsl:with-param name="count_service" select="15"/>
                    </xsl:call-template>
                </xsl:variable>    
                <xsl:call-template name="format_number">
                    <xsl:with-param name="number" select="$total_sum"/>
                </xsl:call-template>
            </xsl:element>
        </root>
    </xsl:template>
    <xsl:template name="format_number">
        <xsl:param name="number"/>
        <xsl:choose>
            <xsl:when test="not (normalize-space($number)) or string($number)='NaN'">
                <xsl:value-of select="'0.00'"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="format-number(translate($number, ',', '.'), '0.00')"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template name="sumParam">
        <xsl:param name="count_service"/>
        <xsl:param name="pAccum" select="0"/>        
        <xsl:choose>
            <xsl:when test="number($count_service) &gt; 0">   
                <xsl:variable name="value">
                <xsl:choose>
                    <xsl:when test="$count_service = 1"><xsl:value-of select="//SUM_1"/></xsl:when>
                    <xsl:when test="$count_service = 2"><xsl:value-of select="//SUM_2"/></xsl:when>
                    <xsl:when test="$count_service = 3"><xsl:value-of select="//SUM_3"/></xsl:when>
                    <xsl:when test="$count_service = 4"><xsl:value-of select="//SUM_4"/></xsl:when>
                    <xsl:when test="$count_service = 5"><xsl:value-of select="//SUM_5"/></xsl:when>
                    <xsl:when test="$count_service = 6"><xsl:value-of select="//SUM_6"/></xsl:when>
                    <xsl:when test="$count_service = 7"><xsl:value-of select="//SUM_7"/></xsl:when>
                    <xsl:when test="$count_service = 8"><xsl:value-of select="//SUM_8"/></xsl:when>
                    <xsl:when test="$count_service = 9"><xsl:value-of select="//SUM_9"/></xsl:when>
                    <xsl:when test="$count_service = 10"><xsl:value-of select="//SUM_10"/></xsl:when>
                    <xsl:when test="$count_service = 11"><xsl:value-of select="//SUM_11"/></xsl:when>
                    <xsl:when test="$count_service = 12"><xsl:value-of select="//SUM_12"/></xsl:when>
                    <xsl:when test="$count_service = 13"><xsl:value-of select="//SUM_13"/></xsl:when>
                    <xsl:when test="$count_service = 14"><xsl:value-of select="//SUM_14"/></xsl:when>
                    <xsl:when test="$count_service = 15"><xsl:value-of select="//SUM_15"/></xsl:when>
                </xsl:choose>    
                </xsl:variable>
                <xsl:variable name="value_norm">
                <xsl:choose>
                    <xsl:when test="not (normalize-space($value)) or string($value)='NaN'">
                        <xsl:value-of select="'0.00'"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="format-number(translate($value, ',', '.'), '0.00')"/>
                    </xsl:otherwise>
                </xsl:choose>
                </xsl:variable>
                <xsl:variable name="cnt"><xsl:value-of select="concat('//SUM_',$count_service)"/></xsl:variable>
                <xsl:variable name="cnt2"><xsl:value-of select="$cnt"/></xsl:variable>
                <xsl:call-template name="sumParam">
                    <xsl:with-param name="count_service" select="$count_service - 1"/>
                    <xsl:with-param name="pAccum" select="$pAccum+$value_norm"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$pAccum"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>   
</xsl:stylesheet>
...
Рейтинг: 0 / 0
21.04.2017, 13:52
    #39442277
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сумма непустых элементов в рекурсии
adar7Хочется выбрать только элементы вида SUM_<N>.
Код: xml
1.
2.
3.
<xsl:template match="root">
  <xsl:value-of select="sum(*[starts-with(name(), 'SUM_')])"/>
</xsl:template>
...
Рейтинг: 0 / 0
12.05.2017, 13:34
    #39452089
adar7
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сумма непустых элементов в рекурсии
_Vasilisk_,

поправленьице
Код: xml
1.
2.
3.
<xsl:template match="root">
<xsl:value-of select="format-number(sum(//*[starts-with(name(), 'SUM_')]),'0.00')"/>
</xsl:template>
...
Рейтинг: 0 / 0
12.05.2017, 18:45
    #39452313
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сумма непустых элементов в рекурсии
adar7поправленьице НИКОГДА не используйте оператор // Он заставляет просматривать ВЕСЬ XML
...
Рейтинг: 0 / 0
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / Сумма непустых элементов в рекурсии / 8 сообщений из 8, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]