Гость
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / XSLT. group by + sum / 4 сообщений из 4, страница 1 из 1
10.06.2019, 10:26
    #39824812
tion69
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
XSLT. group by + sum
Добрый день!
Давно не занимался с XSLT.
Раньше много задач с помощью него делал, а сейчас подзабыл.
Вроде задача простая, а решить уже второй день не могу.

Вот XML на входе:
Код: 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.
76.
77.
78.
<?xml version='1.0' encoding='UTF-8'?>
<read_stock_response>
	<info>выполнено</info>
	<items>
		<item>
			<client_key>90001</client_key>
			<article>14000002031004</article>
			<name>ТЕСТОВЫЙ МАТЕРИАЛ 1004</name>
			<external_id/>
			<base_uom>шт</base_uom>
			<batch/>
			<stock_type>годный</stock_type>
			<exp_date/>
			<lgtyp>WSP2</lgtyp>
			<doctype>OUTB</doctype>
			<qnt>0.0</qnt>
			<qnt1>0.0</qnt1>
			<qnt2>20.0</qnt2>
			<qnt4>18.0</qnt4>
			<qnt5>25.0</qnt5>
			<qnt7>0.0</qnt7>
		</item>
		<item>
			<client_key>90001</client_key>
			<article>14000002031004</article>
			<name>ТЕСТОВЫЙ МАТЕРИАЛ 1004</name>
			<external_id/>
			<base_uom>шт</base_uom>
			<batch/>
			<stock_type>годный</stock_type>
			<exp_date/>
			<lgtyp>WSP2</lgtyp>
			<doctype>ZSOB</doctype>
			<qnt>0.0</qnt>
			<qnt1>0.0</qnt1>
			<qnt2>3.0</qnt2>
			<qnt4>2.0</qnt4>
			<qnt5>3.0</qnt5>
			<qnt7>0.0</qnt7>
		</item>
		<item>
			<client_key>90001</client_key>
			<article>14000002031004</article>
			<name>ТЕСТОВЫЙ МАТЕРИАЛ 1004</name>
			<external_id/>
			<base_uom>шт</base_uom>
			<batch/>
			<stock_type>годный</stock_type>
			<exp_date/>
			<lgtyp>WSP2</lgtyp>
			<doctype/>
			<qnt>1078.0</qnt>
			<qnt1>100.0</qnt1>
			<qnt2>0.0</qnt2>
			<qnt4>0.0</qnt4>
			<qnt5>0.0</qnt5>
			<qnt7>0.0</qnt7>
		</item>
		<item>
			<client_key>90001</client_key>
			<article>5060145741669</article>
			<name>1511, ЗОНТ, ДЕТСКИЕ, ПВХ, ЦВЕТНОЙ, 1</name>
			<external_id>N:876f4e7b-25f4-11e7-a218-000c29bf15f9</external_id>
			<base_uom>шт</base_uom>
			<batch/>
			<stock_type>брак</stock_type>
			<exp_date/>
			<lgtyp>BLOC</lgtyp>
			<doctype/>
			<qnt>2.0</qnt>
			<qnt1>0.0</qnt1>
			<qnt2>0.0</qnt2>
			<qnt4>0.0</qnt4>
			<qnt5>0.0</qnt5>
			<qnt7>0.0</qnt7>
		</item>
	</items>
</read_stock_response>



Вот XSLT, который я пытаюсь научить:
Код: 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.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:fn="http://www.w3.org/2005/xpath-functions"
	exclude-result-prefixes="fn xs">
	<xsl:output method="xml" encoding="UTF-8"  indent="yes"/>
	<xsl:template match="/">
		<read_stock_response>
			<items>
                        <xsl:for-each-group select="/read_stock_response/items/item" group-by="article">
			<xsl:value-of select="current-grouping-key()"/>
			<xsl:for-each select="current-group()">
					<item>
						<article>
							<xsl:value-of select="article"/>
						</article>
						<name>
							<xsl:value-of select="name"/>
						</name>
						<stock_type>
							<xsl:value-of select="stock_type"/>
						</stock_type>
						<qnt>
							<xsl:value-of select="sum(qnt)"/>
						</qnt>
					</item>
				</xsl:for-each>
                           </xsl:for-each-group>
			</items>
		</read_stock_response>		
	</xsl:template>
</xsl:stylesheet>



Но выходит совершенно не то, что я хотел:
Код: 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.
<?xml version="1.0" encoding="UTF-8"?>
<read_stock_response>
   <items>14000002031004<item>
         <article>14000002031004</article>
         <name>ТЕСТОВЫЙ МАТЕРИАЛ 1004</name>
         <stock_type>годный</stock_type>
         <qnt>0</qnt>
      </item>
      <item>
         <article>14000002031004</article>
         <name>ТЕСТОВЫЙ МАТЕРИАЛ 1004</name>
         <stock_type>годный</stock_type>
         <qnt>0</qnt>
      </item>
      <item>
         <article>14000002031004</article>
         <name>ТЕСТОВЫЙ МАТЕРИАЛ 1004</name>
         <stock_type>годный</stock_type>
         <qnt>1078</qnt>
      </item>5060145741669<item>
         <article>5060145741669</article>
         <name>1511, ЗОНТ, ДЕТСКИЕ, ПВХ, ЦВЕТНОЙ, 1</name>
         <stock_type>брак</stock_type>
         <qnt>2</qnt>
      </item>
   </items>
</read_stock_response>



А хотел получить вот это:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
<?xml version="1.0" encoding="UTF-8"?>
<read_stock_response>
   <items>
      <item>
         <article>14000002031004</article>
         <name>ТЕСТОВЫЙ МАТЕРИАЛ 1004</name>
         <stock_type>годный</stock_type>
         <qnt>1078</qnt>
      </item>
      <item>
         <article>5060145741669</article>
         <name>1511, ЗОНТ, ДЕТСКИЕ, ПВХ, ЦВЕТНОЙ, 1</name>
         <stock_type>брак</stock_type>
         <qnt>2</qnt>
      </item>
   </items>
</read_stock_response>



Прошу вашей помощи, как правильно составить XSLT, чтобы работало по моей потребности.
Заранее при много благодарен.
...
Рейтинг: 0 / 0
10.06.2019, 13:01
    #39824914
tion69
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
XSLT. group by + sum
Так, продвинулся, с группировкой.
Сумма как то странно собирается:

Код: 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.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:fn="http://www.w3.org/2005/xpath-functions"
	exclude-result-prefixes="fn xs">
	<xsl:output method="xml" encoding="UTF-8"  indent="yes"/>
<xsl:template match="/">
<read_stock_response>
<items>
  <xsl:for-each-group select="read_stock_response/items/item" group-by="article">
<item>
    <article> <xsl:value-of select="current-grouping-key()"/></article>
      <xsl:for-each-group select="current-group()" group-by="name">
       <name> <xsl:value-of select="current-grouping-key()"/></name>
          <qnt>          
            <xsl:for-each select="current-group()">

                   <xsl:value-of select="sum(xs:double (qnt))"/>

            </xsl:for-each>
          </qnt>
      </xsl:for-each-group>
   </item>
  </xsl:for-each-group>
</items>
</read_stock_response>
</xsl:template>
</xsl:stylesheet>



Получилось:
<qnt> 5.301078.1 </qnt>
Вместо:
<qnt> 1083.4 </qnt>
Ответ:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
<?xml version="1.0" encoding="UTF-8"?>
<read_stock_response>
   <items>
      <item>
         <article>14000002031004</article>
         <name>ТЕСТОВЫЙ МАТЕРИАЛ 1004</name>
         <qnt>5.301078.1</qnt>
      </item>
      <item>
         <article>5060145741669</article>
         <name>1511, ЗОНТ, ДЕТСКИЕ, ПВХ, ЦВЕТНОЙ, 1</name>
         <qnt>2</qnt>
      </item>
   </items>
</read_stock_response>
...
Рейтинг: 0 / 0
10.06.2019, 13:53
    #39824940
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
XSLT. group by + sum
Классическая группировка делается так
Код: xml
1.
<xsl:if test="not(preceding-sibling::*[article = current()/article])">


делая такую проверку внутри xsl:for-each или xsl:template мы обрабатываем уникальные значения. Ну а дальше все просто
Код: 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.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" encoding="UTF-8"/>
  
  <xsl:template match="item">
    <xsl:if test="not(preceding-sibling::*[article = current()/article])">
      <!-- До этого момента нам не встречался item с таким article -->
      <xsl:copy>
        <xsl:apply-templates select="article"/>
        <xsl:apply-templates select="name"/>
        <xsl:apply-templates select="stock_type"/>
        <qnt>
           <!-- считаем сумму по всем item с таким article -->
          <xsl:value-of select="sum(../item[article = current()/article]/qnt)"/>
        </qnt>
      </xsl:copy>
    </xsl:if>
  </xsl:template>
  
  <xsl:template match="*">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
...
Рейтинг: 0 / 0
10.06.2019, 14:36
    #39824965
tion69
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
XSLT. group by + sum
_Vasilisk_,

Огромное спасибо!
...
Рейтинг: 0 / 0
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / XSLT. group by + sum / 4 сообщений из 4, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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