Как я могу суммировать значения по каждой категории в xsl? - PullRequest
1 голос
/ 06 марта 2012

Мне нужно суммировать продажи по местоположениям от нашего партнера xml (не знаю, сколько мест заранее):

пример ввода:

<company>
    <deparment dept="001">
        <location>
            <locationCode>001</locationCode>
            <sales>10000</sales>
        </location>
        <location>
            <locationCode>0005</locationCode>
            <sales>12500</sales>
        </location>
    </deparment>
    <deparment dept="002">
        <location>
            <locationCode>001</locationCode>
            <sales>40000</sales>
        </location>
        <location>
            <locationCode>004</locationCode>
            <sales>30000</sales>
        </location>
    </deparment>
    <deparment dept="003">
        <location>
            <locationCode>004</locationCode>
            <sales>60000</sales>
        </location>
    </deparment>
</company>

Ожидаемый результат:

<location>
    <locationCode>001</locationCode>
    <totalSales>50000</locationCode>
<location>
<location>
    <locationCode>005</locationCode>
    <totalSales>12500</locationCode>
<location>
<location>
    <locationCode>004</locationCode>
    <totalSales>90000</locationCode>
<location>

Есть ли у xsl что-то вроде group-by? Я новичок в xsl и ценю любую помощь.

Спасибо.

Ответы [ 4 ]

1 голос
/ 07 марта 2012

Краткое, простое и эффективное решение XSLT 1.0 (без переменных, нет xsl:for-each) :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kLocById" match="location" use="locationCode"/>

 <xsl:template match=
  "location
    [generate-id()
    =
     generate-id(key('kLocById',locationCode)[1])
    ]">
  <location>
   <xsl:copy-of select="locationCode"/>
   <totalSales>
    <xsl:value-of select="sum(key('kLocById',locationCode)/sales)"/>
   </totalSales>
  </location>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному документу XML :

<company>
    <deparment dept="001">
        <location>
            <locationCode>001</locationCode>
            <sales>10000</sales>
        </location>
        <location>
            <locationCode>0005</locationCode>
            <sales>12500</sales>
        </location>
    </deparment>
    <deparment dept="002">
        <location>
            <locationCode>001</locationCode>
            <sales>40000</sales>
        </location>
        <location>
            <locationCode>004</locationCode>
            <sales>30000</sales>
        </location>
    </deparment>
    <deparment dept="003">
        <location>
            <locationCode>004</locationCode>
            <sales>60000</sales>
        </location>
    </deparment>
</company>

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

<location>
   <locationCode>001</locationCode>
   <totalSales>50000</totalSales>
</location>
<location>
   <locationCode>0005</locationCode>
   <totalSales>12500</totalSales>
</location>
<location>
   <locationCode>004</locationCode>
   <totalSales>90000</totalSales>
</location>

Объяснение : правильное использование мюнхенского метода для группировки и сопоставления с шаблоном.

1 голос
/ 06 марта 2012

Это будет решение с использованием XSLT 2.0:

Для следующего входного XML:

<?xml version="1.0" encoding="UTF-8"?>
<company>
    <department dept="001">
        <location>
            <locationCode>001</locationCode>
            <sales>10000</sales>
        </location>
        <location>
            <locationCode>0005</locationCode>
            <sales>12500</sales>
        </location>
    </department>
    <department dept="002">
        <location>
            <locationCode>001</locationCode>
            <sales>40000</sales>
        </location>
        <location>
            <locationCode>004</locationCode>
            <sales>30000</sales>
        </location>
    </department>
    <department dept="003">
        <location>
            <locationCode>004</locationCode>
            <sales>60000</sales>
        </location>
    </department>
</company>

Использование следующего XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />
<xsl:template match="/company">
<company>
    <xsl:for-each-group select="department/location" group-by="locationCode">
        <location>
            <locationCode><xsl:value-of select="current-grouping-key()"/></locationCode>
            <totalSales><xsl:value-of select="sum(current-group()/sales)"/></totalSales>
        </location>
    </xsl:for-each-group>
</company>
</xsl:template>
</xsl:stylesheet>

Я получаю вывод:

<?xml version="1.0" encoding="UTF-8"?>
<company xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <location>
        <locationCode>001</locationCode>
        <totalSales>50000</totalSales>
    </location>
    <location>
        <locationCode>0005</locationCode>
        <totalSales>12500</totalSales>
    </location>
    <location>
        <locationCode>004</locationCode>
        <totalSales>90000</totalSales>
    </location>
</company>
1 голос
/ 06 марта 2012

Я получил его для xslt 1.0 с этим.

<xsl:key name="Location" match="/company/deparment/location" use="locationCode"/>

<xsl:template match="company">
  <company>
  <xsl:for-each select="./deparment/location[generate-id() = generate-id(key('Location', ./locationCode)[1])]">
    <xsl:variable name="LocationCode" select="./locationCode"/>
    <location>
      <locationCode>
        <xsl:value-of select="$LocationCode"/>
      </locationCode>
      <totalSales>
        <xsl:value-of select="sum(//location[locationCode = $LocationCode]/sales)"/>
      </totalSales>
    </location>
  </xsl:for-each>
  </company>
</xsl:template>

Проверьте метод muenchian на наличие подобных проблем в будущем.

0 голосов
/ 06 марта 2012

Для Xslt 2,0 xsl: для каждой группы инструкция):

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0" >

    <xsl:output indent="yes" />

    <xsl:template match="/">
        <xsl:for-each-group select="company/deparment/location" group-by="locationCode">
            <location>
                <locationCode><xsl:value-of select="current-grouping-key()"/></locationCode>
                <totalSales><xsl:value-of select="sum(current-group()/sales)"/></totalSales>
            </location>
        </xsl:for-each-group>

    </xsl:template>  

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