XSLT 按特定标签分组

XSLT grouping by specific tag

我有这个 XML 文档:

<?xml version="1.0" encoding="utf-8"?>
<Document>
  <InvoiceLines>
    <Lines>
      <LineNume>1</LineNume>
      <Description>Test1</Description>
      <Quantity>200</Quantity>
      <UnitPrice>500</UnitPrice>
      <Amounts>
        <Net>100000</Net>
        <VATRate>
          <Percent>2</Percent>
        </VATRate>
        <VATAmount>2000</VATAmount>
        <Gross>102000</Gross>
      </Amounts>
    </Lines>
    <Lines>
      <LineNume>2</LineNume>
      <Description>Test2</Description>
      <Quantity>300</Quantity>
      <UnitPrice>1000</UnitPrice>
      <Amounts>
        <Net>300000</Net>
        <VATRate>
          <Percent>3</Percent>
        </VATRate>
        <VATAmount>9000</VATAmount>
        <Gross>309000</Gross>
      </Amounts>
    </Lines>
    <Lines>
      <LineNume>3</LineNume>
      <Description>Test3</Description>
      <Quantity>100</Quantity>
      <UnitPrice>500</UnitPrice>
      <Amounts>
        <Net>50000</Net>
        <VATRate>
          <Percent>3</Percent>
        </VATRate>
        <VATAmount>1500</VATAmount>
        <Gross>51500</Gross>
      </Amounts>
    </Lines>
    <Lines>
      <LineNume>4</LineNume>
      <Description>Test4</Description>
      <Quantity>100</Quantity>
      <UnitPrice>500</UnitPrice>
      <Amounts>
        <Net>50000</Net>
        <VATRate>
          <Excempt>0</Excempt>
        </VATRate>
        <VATAmount>0</VATAmount>
        <Gross>50000</Gross>
      </Amounts>
    </Lines>
  </InvoiceLines>
</Document>

并使用此 XSLT 1.0 代码(更新):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>

  <xsl:key name ="kVAT" match="Amounts" use ="concat(generate-id(..), VATRate/Percent | VATRate/Excempt)" />

  <xsl:template match="Document/InvoiceLines">
    <xsl:variable name="NetAmount" select="Lines/Amounts/Net" />
    <xsl:variable name="VATAmount" select="Lines/Amounts/VATAmount" />
    <xsl:variable name="GrossAmount" select="Lines/Amounts/Gross" />
    <Summary>
      <xsl:for-each select=
                "//Amounts[generate-id() = 
                        generate-id(
                          key('kVAT', 
                              concat(generate-id(..), VATRate/Percent | VATRate/Excempt)
                          )[1]
                        )
                     ]">

        <xsl:variable name="keyGroup" select ="key('kVAT', concat(generate-id(..), VATRate/Percent | VATRate/Excempt))" />
        <Rate>
          <VATRate>
            <xsl:choose>
              <xsl:when test="$keyGroup/VATRate/Percent">
                <Percent>
                  <xsl:value-of select ="$keyGroup/VATRate/Percent"/>
                </Percent>
              </xsl:when>
              <xsl:otherwise>
                <Excempt>
                  <xsl:value-of select ="$keyGroup/VATRate/Excempt"/>
                </Excempt>
              </xsl:otherwise>
            </xsl:choose>
          </VATRate>
          <Net>
            <xsl:value-of select ="$keyGroup/Net" />
          </Net>
          <VATAmount>
            <xsl:value-of select ="$keyGroup/VATAmount" />
          </VATAmount>
          <Gross>
            <xsl:value-of select ="$keyGroup/Gross" />
          </Gross>
        </Rate>
      </xsl:for-each>
      <NetAmount>
        <xsl:value-of select ="sum($NetAmount)"/>
      </NetAmount>
      <VATAmount>
        <xsl:value-of select ="sum($VATAmount)"/>
      </VATAmount>
    </Summary>
    <GrossAmount>
      <xsl:value-of select ="sum($GrossAmount)"/>
    </GrossAmount>
  </xsl:template>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

我有这个结果(更新):

<?xml version="1.0" encoding="utf-8"?>
<Document>
  <Summary>
    <Rate>
      <VATRate>
        <Percent>2</Percent>
      </VATRate>
      <Net>100000</Net>
      <VATAmount>2000</VATAmount>
      <Gross>102000</Gross>
    </Rate>
    <Rate>
      <VATRate>
        <Percent>3</Percent>
      </VATRate>
      <Net>300000</Net>
      <VATAmount>9000</VATAmount>
      <Gross>309000</Gross>
    </Rate>
    <Rate>
      <VATRate>
        <Percent>3</Percent>
      </VATRate>
      <Net>50000</Net>
      <VATAmount>1500</VATAmount>
      <Gross>51500</Gross>
    </Rate>
    <Rate>
      <VATRate>
        <Excempt>0</Excempt>
      </VATRate>
      <Net>50000</Net>
      <VATAmount>0</VATAmount>
      <Gross>50000</Gross>
    </Rate>
    <NetAmount>500000</NetAmount>
    <VATAmount>12500</VATAmount>
  </Summary>
  <GrossAmount>512500</GrossAmount>
</Document>

但我需要根据增值税税率分组,结果如下:

<?xml version="1.0" encoding="utf-8"?>
<Document>
  <Summary>
    <Rate>
      <Net>100000</Net>
      <VATRate>
        <Percent>2</Percent>
      </VATRate>
      <VATAmount>2000</VATAmount>
      <Gross>102000</Gross>
    </Rate>
    <Rate>
      <Net>350000</Net>
      <VATRate>
        <Percent>3</Percent>
      </VATRate>
      <VATAmount>10500</VATAmount>
      <Gross>360500</Gross>
    </Rate>
    <Rate>
      <Net>50000</Net>
      <VATRate>
        <Excempt>0</Excempt>
      </VATRate>
      <VATAmount>0</VATAmount>
      <Gross>50000</Gross>
    </Rate>
    <NetAmount>500000</NetAmount>
    <VATAmount>12500</VATAmount>
  </Summary>
  <GrossAmount>512500</GrossAmount>
</Document>

请注意 <Rate/VATRate> 标签可以包含 <percent><Excempt> 等的子标签。

我花了几天时间通过查找类似的主题来解决这个问题,但似乎可以找到。

任何人都可以帮助我解决我使用 XSLT 1.0 的这个问题,因为我们无法访问其他版本。

谢谢

怎么样:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="amt-by-rate" match="Amounts" use="VATRate/*" />

<xsl:template match="/Document">
    <xsl:variable name="amounts" select="InvoiceLines/Lines/Amounts" />
    <xsl:copy>
        <Summary>
            <xsl:for-each select="$amounts[count(. | key('amt-by-rate', VATRate/*)[1]) = 1]">
                <xsl:variable name="current-group" select="key('amt-by-rate', VATRate/*)" />
                <Rate>
                    <Net>
                        <xsl:value-of select="sum($current-group/Net)"/>
                    </Net>
                    <xsl:copy-of select="VATRate"/>
                    <VATAmount>
                        <xsl:value-of select="sum($current-group/VATAmount)"/>
                    </VATAmount>
                    <Gross>
                        <xsl:value-of select="sum($current-group/Gross)"/>
                    </Gross>
                </Rate>
            </xsl:for-each>
        </Summary>
        <NetAmount>
            <xsl:value-of select="sum($amounts/Net)"/>
        </NetAmount>
        <VATAmount>
            <xsl:value-of select="sum($amounts/VATAmount)"/>
        </VATAmount>
        <GrossAmount>
            <xsl:value-of select="sum($amounts/Gross)"/>
        </GrossAmount>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>