XSLT 1.0 Grouping

后端 未结 3 1295
半阙折子戏
半阙折子戏 2021-01-27 17:45

I need to apply XSLT 1.0 transformation to following XML:


  
    2013
    

        
相关标签:
3条回答
  • 2021-01-27 18:31

    Please try this:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
      <xsl:key name="kFinancialByYear"
               match="*[self::ProfitLossFinancial or self::BalanceSheetFinancial]"
               use="Year" />
      <xsl:variable name="af" 
                    select="//*[self::ProfitLossFinancial or 
                                self::BalanceSheetFinancial]"/>
    
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="/*">
        <Financials>
          <xsl:apply-templates select="$af[generate-id() = 
                                          generate-id(key('kFinancialByYear', Year)[1])]"
                               mode="group" />
        </Financials>
      </xsl:template>
    
      <xsl:template match="*" mode="group">
        <xsl:variable name="thisYearValues" select="key('kFinancialByYear', Year)" />
        <Financial>
          <xsl:apply-templates select="Year" />
          <Turnover>
            <xsl:value-of select="$thisYearValues/Turnover"/>
          </Turnover>
          <Profit>
            <xsl:value-of select="$thisYearValues/Profit"/>
          </Profit>
          <FixedAssets>
            <xsl:value-of select="$thisYearValues/FixedAssets"/>
          </FixedAssets>
        </Financial>
      </xsl:template>
    </xsl:stylesheet>
    

    When run on this input:

    <n>
      <ProfitLossFinancials>
        <ProfitLossFinancial>
          <Year>2013</Year>
          <Turnover>13</Turnover>
          <Profit>13</Profit>
        </ProfitLossFinancial>
        <ProfitLossFinancial>
          <Year>2012</Year>
          <Turnover>12</Turnover>
          <Profit>12</Profit>
        </ProfitLossFinancial>
      </ProfitLossFinancials>
      <BalanceSheetFinancials>
        <BalanceSheetFinancial>
          <Year>2013</Year>
          <FixedAssets>13</FixedAssets>
        </BalanceSheetFinancial>
        <BalanceSheetFinancial>
          <Year>2011</Year>
          <FixedAssets>11</FixedAssets>
        </BalanceSheetFinancial>
      </BalanceSheetFinancials>
    </n>
    

    The result is:

    <Financials>
      <Financial>
        <Year>2013</Year>
        <Turnover>13</Turnover>
        <Profit>13</Profit>
        <FixedAssets>13</FixedAssets>
      </Financial>
      <Financial>
        <Year>2012</Year>
        <Turnover>12</Turnover>
        <Profit>12</Profit>
        <FixedAssets></FixedAssets>
      </Financial>
      <Financial>
        <Year>2011</Year>
        <Turnover></Turnover>
        <Profit></Profit>
        <FixedAssets>11</FixedAssets>
      </Financial>
    </Financials>
    
    0 讨论(0)
  • 2021-01-27 18:39

    Here are more straightforward solution using for-each and key:

    <?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" indent="yes"/>
        <xsl:key match="Year" name="kyears" use="."/>
    
        <xsl:template match="/*">
            <Financials>
                <xsl:for-each select="//Year[generate-id() = 
                                        generate-id(key('kyears', .)[1])]"  >
                    <xsl:variable name="year" select="." />
                    <xsl:variable name="yearData" select="key('kyears', $year)/.." />
                    <Financial>
                        <xsl:copy-of select="$year"/>
                        <Turnover>
                            <xsl:value-of select="$yearData/Turnover"/>
                        </Turnover>
                        <Profit>
                            <xsl:value-of select="$yearData/Profit"/>
                        </Profit>
                        <FixedAssets>
                            <xsl:value-of select="$yearData/FixedAssets"/>
                        </FixedAssets>
                    </Financial>
                </xsl:for-each>
            </Financials>
        </xsl:template>
    
    </xsl:stylesheet>
    

    Which generate the following output:

    <?xml version="1.0"?>
    <Financials>
      <Financial>
        <Year>2013</Year>
        <Turnover>13</Turnover>
        <Profit>13</Profit>
        <FixedAssets>13</FixedAssets>
      </Financial>
      <Financial>
        <Year>2012</Year>
        <Turnover>12</Turnover>
        <Profit>12</Profit>
        <FixedAssets/>
      </Financial>
      <Financial>
        <Year>2011</Year>
        <Turnover/>
        <Profit/>
        <FixedAssets>11</FixedAssets>
      </Financial>
    </Financials>
    
    0 讨论(0)
  • 2021-01-27 18:41
    <xsl:template match="ProfitLossFinancials">
        <Financials>
            <xsl:apply-templates select="ProfitLossFinancial"/>
        </Financials>
    </xsl:template>
    
    <xsl:template match="ProfitLossFinancial">
        <Financial>
            <xsl:copy-of select="./*"/>
            <xsl:copy-of select="../../BalanceSheetFinancials/BalanceSheetFinancial[Year = current()/Year]/FixedAssets"/>
        </Financial>
    </xsl:template>
    
    0 讨论(0)
提交回复
热议问题