XSLT2.0:如何使用嵌套的for-each-group压缩xml记录

时间:2019-07-15 09:11:02

标签: xml xslt xslt-2.0 xslt-grouping

我正在尝试使用嵌套的for-each-group和for-each与current-group()基于两个键将类似的数据压缩到一个xml记录中。第一个键是ID,第二个键是Inv_Link

当我使用// Record时,我得到了外循环的预期结果,但得到了内循环,我得到了每个结果中的所有键,用。我只得到第一个数据元素。什么是合适的选择器才能在父键中获取所有嵌套键?

感谢您的帮助!

XML数据集

<Data>
    <Record>
        <ID>01_2019</ID>
        <Link>ICE2</Link>
        <Component_ID>DEBT</Component_ID>
        <Amt>1500</Amt>
    </Record>
    <Record>
        <ID>01_2019</ID>
        <Link>ICE1</Link>
        <Component_ID>EQT</Component_ID>
        <Amt>200</Amt>
    </Record>
    <Record>
        <ID>01_2019</ID>
        <Link>ICE1</Link>
        <Component_ID>CASH</Component_ID>
        <Amt>100</Amt>
    </Record>
    <Record>
        <ID>01_2020</ID>
        <Link>ICE3</Link>
        <Component_ID>CASH</Component_ID>
        <Amt>100</Amt>
    </Record>
</Data>

我正在使用的XSLT:

   <xsl:template match="Data">
        <xsl:for-each-group select="Record" group-by="ID">
        <xsl:for-each select="current-group()">
          <Record>
            <groupkey><xsl:value-of select="current-grouping-key()"/></groupkey>
            <AssetEvent>
                <ID> <xsl:copy> <xsl:value-of select="ID/text()" /> </xsl:copy> </ID>
                <DecompositionSequence>
                    <xsl:for-each-group select="Record" group-by="Link">
                    <groupkey><xsl:value-of select="current-grouping-key()"/></groupkey>
                    <xsl:for-each select="current-group()">
                        <Decompositions>
                            <Link> 
                              <ID><xsl:copy><xsl:value-of select="Link/text()" /> </xsl:copy> <ID> 
                            </Link>
                            <DecompositionDataSequence>
                                <DecompositionData>
                                    <Component>
                                        <ID> <xsl:copy> <xsl:value-of select="Component_ID/text()" /> </xsl:copy> </ID> 
                                    </Component>
                                    <Amt> <xsl:copy> <xsl:value-of select="Amt/text()" /> </xsl:copy> </Amt>
                                </DecompositionData>
                            </DecompositionDataSequence>
                        </Decompositions>   
                    </xsl:for-each>
                    </xsl:for-each-group>
              </DecompositionSequence>
            </AssetEvent>
          </Record>
        </xsl:for-each>
        </xsl:for-each-group>
  </xsl:template>

当前结果,我总共获得2条记录,但没有任何内部分组(如果我使用// Record,那么我将得到所有两个结果记录):

    <Record>
      <groupkey>ICE 01_2019</groupkey>
      <AssetEvent>
        <ID>ICE 01_2019</ID>
        <DecompositionSequence />
      </AssetEvent>
    </Record>
    <Record>
      <groupkey>01_2020</groupkey>
      <AssetEvent>
        <ID>01_2020</ID>
        <DecompositionSequence />
      </AssetEvent>
    </Record>


我期望的是

    <Record>
      <groupkey>01_2019</groupkey>
      <AssetEvent>
        <ID>01_2019</ID>
        <DecompositionSequence>
          <groupkey>ICE2</groupkey>
          <Decompositions>
            <InvestmentLink>ICE2</InvestmentLink>
            <DecompositionDataSequence>
              <DecompositionData>
                <Component>
                  <ID>DEBT</ID>
                </Component>
                <Amt>150</Amt>
              </DecompositionData>
            </DecompositionDataSequence>
          </Decompositions>
          <groupkey>ICE1</groupkey>
          <Decompositions>
            <InvestmentLink>ICE1</InvestmentLink>
            <DecompositionDataSequence>
              <DecompositionData>
                <Component>
                  <ID>EQT</ID>
                </Component>
                <Amt>150</Amt>
              </DecompositionData>
              <DecompositionData>
                <Component>
                  <ID>CASH</ID>
                </Component>
                <Amt>150</Amt>
              </DecompositionData>
            </DecompositionDataSequence>
          </Decompositions>
        </DecompositionSequence>
      </AssetEvent>
    </Record>
    <Record>
      <groupkey>01_2020</groupkey>
      <AssetEvent>
        <ID>01_2020</ID>
        <DecompositionSequence>
          <groupkey>ICE3</groupkey>
          <Decompositions>
            <InvestmentLink>ICE3</InvestmentLink>
            <DecompositionDataSequence>
              <DecompositionData>
                <Component>
                  <ID>CASH</ID>
                </Component>
                <Amt>100</Amt>
              </DecompositionData>
            </DecompositionDataSequence>
          </Decompositions>
        </DecompositionSequence>
      </AssetEvent>
    </Record>

1 个答案:

答案 0 :(得分:0)

假设您输入的样本是

<Data>
    <Record>
        <ID>01_2019</ID>
        <Link>ICE2</Link>
        <Component_ID>DEBT</Component_ID>
        <Amt>1500</Amt>
    </Record>
    <Record>
        <ID>01_2019</ID>
        <Link>ICE1</Link>
        <Component_ID>EQT</Component_ID>
        <Amt>200</Amt>
    </Record>
    <Record>
        <ID>01_2019</ID>
        <Link>ICE1</Link>
        <Component_ID>CASH</Component_ID>
        <Amt>100</Amt>
    </Record>
    <Record>
        <ID>01_2020</ID>
        <Link>ICE3</Link>
        <Component_ID>CASH</Component_ID>
        <Amt>100</Amt>
    </Record>
</Data>

然后输入代码

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="Data">
    <xsl:for-each-group select="Record" group-by="ID">
        <xsl:copy>
            <groupkey>
                <xsl:value-of select="current-grouping-key()"/>
            </groupkey>
            <AssetEvent>
                <xsl:copy-of select="ID"/>
                <DecompositionSequence>
                  <xsl:for-each-group select="current-group()" group-by="Link">
                      <groupkey>
                          <xsl:value-of select="current-grouping-key()"/>
                      </groupkey>
                      <Decompositions>
                          <InvestmentLink>
                              <xsl:value-of select="current-grouping-key()"/>
                          </InvestmentLink>
                          <DecompositionDataSequence>
                              <xsl:apply-templates select="current-group()"/>
                          </DecompositionDataSequence>
                      </Decompositions>
                  </xsl:for-each-group>
                </DecompositionSequence>
            </AssetEvent>

        </xsl:copy>
      </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="Record">
        <DecompositionData>
            <xsl:apply-templates select="* except (ID, Link)"/>
        </DecompositionData>
    </xsl:template>

    <xsl:template match="Component_ID">
        <Component>
            <ID>
                <xsl:value-of select="."/>
            </ID>
        </Component>
    </xsl:template>

</xsl:stylesheet>

提供输出

<?xml version="1.0" encoding="UTF-8"?>
<Record>
   <groupkey>01_2019</groupkey>
   <AssetEvent>
      <ID>01_2019</ID>
      <DecompositionSequence>
         <groupkey>ICE2</groupkey>
         <Decompositions>
            <InvestmentLink>ICE2</InvestmentLink>
            <DecompositionDataSequence>
               <DecompositionData>
                  <Component>
                     <ID>DEBT</ID>
                  </Component>
                  <Amt>1500</Amt>
               </DecompositionData>
            </DecompositionDataSequence>
         </Decompositions>
         <groupkey>ICE1</groupkey>
         <Decompositions>
            <InvestmentLink>ICE1</InvestmentLink>
            <DecompositionDataSequence>
               <DecompositionData>
                  <Component>
                     <ID>EQT</ID>
                  </Component>
                  <Amt>200</Amt>
               </DecompositionData>
               <DecompositionData>
                  <Component>
                     <ID>CASH</ID>
                  </Component>
                  <Amt>100</Amt>
               </DecompositionData>
            </DecompositionDataSequence>
         </Decompositions>
      </DecompositionSequence>
   </AssetEvent>
</Record>
<Record>
   <groupkey>01_2020</groupkey>
   <AssetEvent>
      <ID>01_2020</ID>
      <DecompositionSequence>
         <groupkey>ICE3</groupkey>
         <Decompositions>
            <InvestmentLink>ICE3</InvestmentLink>
            <DecompositionDataSequence>
               <DecompositionData>
                  <Component>
                     <ID>CASH</ID>
                  </Component>
                  <Amt>100</Amt>
               </DecompositionData>
            </DecompositionDataSequence>
         </Decompositions>
      </DecompositionSequence>
   </AssetEvent>
</Record>

它使用XSLT 3声明<xsl:mode on-no-match="shallow-copy"/>,但是如果您使用XSLT 2处理器,则可以用身份转换模板替换它。