xslt中的二维分组和求和

时间:2012-09-04 19:12:27

标签: xslt xslt-1.0 xslt-grouping

我的输入xml就像

<Reports>
  <Report>  
    <ReportHeader>
      <Name>ABC</Name>
      <ReportNo>123</ReportNo>
    </ReportHeader>
    <ReportLine>
      <ReportNo>123</ReportNo>
      <LineGroup>XYZ</LineGroup>
      <LineAmount>10</LineAmount>
    <ReportLine>
    <ReportLine>
      <ReportNo>123</ReportNo>
      <LineGroup>PQR</LineGroup>
      <LineAmount>20</LineAmount>
    <ReportLine>
    <ReportLine>
    <ReportNo>123</ReportNo>
      <LineGroup>XYZ</LineGroup>
      <LineAmount>30</LineAmount>
    <ReportLine>
  </Report>
  <Report>
    <ReportHeader>
      <Name>DEF</Name>
      <ReportNo>456</ReportNo>
    </ReportHeader>
    <ReportLine>
      <ReportNo>456</ReportNo>
      <LineGroup>IJK</LineGroup>
      <LineAmount>40</LineAmount>
    <ReportLine>
    <ReportLine>
      <ReportNo>456</ReportNo>
      <LineGroup>XYZ</LineGroup>
      <LineAmount>50</LineAmount>
    <ReportLine>
    <ReportLine>
      <ReportNo>456</ReportNo>
      <LineGroup>IJK</LineGroup>
      <LineAmount>60</LineAmount>
    <ReportLine>
  </Report>
</Reports>

我的输出xml就像

<NewReport>
  <Header>
    <Name>ABC</Name>
    <HeaderNo>456</HeaderNo>
  </Header>
  <Line>
    <LineGroup>XYZ</LineGroup>
    <Amount>40</Amount>
  </Line>
  <Line>
    <LineGroup>PQR</LineGroup>
    <Amount>20</Amount>
  </Line>
</NewReport>
<NewReport>
  <Header>
    <Name>DEF</Name>
    <HeaderNo>456</HeaderNo>
  </Header>
  <Line>
    <LineGroup>IJK</LineGroup>
    <Amount>100</Amount>
  </Line>
  <Line>
    <LineGroup>XYZ</LineGroup>
    <Amount>50</Amount>
  </Line>
</NewReport>

我正在使用的XSL是

<xsl:key name="KLinesByGroup" match="/Reports/Report/ReportLine" use="LineGroup"/>
<xsl:key name="KLinesByReportNo" match="/Reports/Report/ReportLine" use="ReportNo"/>
<xsl:template match="/">
  <xsl:for-each select="/ns2:Reports/ns2:Report">
     <xsl:variable name="HeaderReportNo"><xsl:value-of select="ReportHeader/ReportNo"/></xsl:variable>
     <Header>
       <Name><xsl:value-of select="ReportHeader/Name"/></Name>
       <HeaderNo><xsl:value-of select="ReportHeader/ReportNo"/></HeaderNo>
       <xsl:apply-templates select="key('KLinesByReportNo', $HeaderReportNo)[1]" mode="reportno-mode"/>
     </Header>
  </xsl:for-each>
</xsl:template>

<xsl:template match="ReportLine" mode="reportno-mode">
  <xsl:apply-templates select="key('KLinesByReportNo', ReportNo)[generate-id() = generate-id(key('KLinesByGroup', LineGroup)[1])]" mode="group-mode"/>
</xsl:template>

<xsl:template match="ReportLine" mode="group-mode">
  <Line>
    <xsl:value-of select="sum(key('KLinesByGroup', LineGroup)/LineAmount)"/>
  </Line>
</xsl:template>

但输出并不是我所期待的。我得到的输出是在组级别或行级别添加所有金额,但不是在行级别和组级别。请任何人帮忙。

由于

1 个答案:

答案 0 :(得分:0)

此转化

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

 <xsl:key name="kLine" match="ReportLine"
  use="concat(../ReportHeader/Name, '+',
              ../ReportHeader/ReportNo, '+',
              ReportNo, '+',
              LineGroup
              )"/>

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

 <xsl:template match=
    "ReportLine
      [not(generate-id()
          =
           generate-id(key('kLine',
                           concat(../ReportHeader/Name, '+',
                                  ../ReportHeader/ReportNo, '+',
                                  ReportNo, '+',
                                   LineGroup
                                  )
                          )
                          [1])
           )
      ]"/>

  <xsl:template match="LineAmount">
   <Amount>
     <xsl:value-of select=
     "sum(key('kLine',
              concat(../../ReportHeader/Name, '+',
                     ../../ReportHeader/ReportNo, '+',
                     ../ReportNo, '+',
                     ../LineGroup
                     )
             )
              /LineAmount
         )"/>
   </Amount>
  </xsl:template>

  <xsl:template match="ReportLine/ReportNo"/>

  <xsl:template match="/*"><xsl:apply-templates/></xsl:template>
  <xsl:template match="Report">
   <NewReport><xsl:apply-templates/></NewReport>
  </xsl:template>

  <xsl:template match="ReportHeader">
   <Header><xsl:apply-templates/></Header>
  </xsl:template>

  <xsl:template match="ReportNo">
   <HeaderNo><xsl:apply-templates/></HeaderNo>
  </xsl:template>

  <xsl:template match="ReportLine">
   <Line><xsl:apply-templates/></Line>
  </xsl:template>
</xsl:stylesheet>

应用于提供的XML(从多个格式错误的标记更正)文档:

<Reports>
  <Report>
    <ReportHeader>
      <Name>ABC</Name>
      <ReportNo>123</ReportNo>
    </ReportHeader>
    <ReportLine>
      <ReportNo>123</ReportNo>
      <LineGroup>XYZ</LineGroup>
      <LineAmount>10</LineAmount>
    </ReportLine>
    <ReportLine>
      <ReportNo>123</ReportNo>
      <LineGroup>PQR</LineGroup>
      <LineAmount>20</LineAmount>
    </ReportLine>
    <ReportLine>
    <ReportNo>123</ReportNo>
      <LineGroup>XYZ</LineGroup>
      <LineAmount>30</LineAmount>
    </ReportLine>
  </Report>
  <Report>
    <ReportHeader>
      <Name>DEF</Name>
      <ReportNo>456</ReportNo>
    </ReportHeader>
    <ReportLine>
      <ReportNo>456</ReportNo>
      <LineGroup>IJK</LineGroup>
      <LineAmount>40</LineAmount>
    </ReportLine>
    <ReportLine>
      <ReportNo>456</ReportNo>
      <LineGroup>XYZ</LineGroup>
      <LineAmount>50</LineAmount>
    </ReportLine>
    <ReportLine>
      <ReportNo>456</ReportNo>
      <LineGroup>IJK</LineGroup>
      <LineAmount>60</LineAmount>
    </ReportLine>
  </Report>
</Reports>

生成想要的正确结果

<NewReport>
   <Header>
      <Name>ABC</Name>
      <HeaderNo>123</HeaderNo>
   </Header>
   <Line>
      <LineGroup>XYZ</LineGroup>
      <Amount>40</Amount>
   </Line>
   <Line>
      <LineGroup>PQR</LineGroup>
      <Amount>20</Amount>
   </Line>
</NewReport>
<NewReport>
   <Header>
      <Name>DEF</Name>
      <HeaderNo>456</HeaderNo>
   </Header>
   <Line>
      <LineGroup>IJK</LineGroup>
      <Amount>100</Amount>
   </Line>
   <Line>
      <LineGroup>XYZ</LineGroup>
      <Amount>50</Amount>
   </Line>
</NewReport>

<强>解释

使用复合键和 Muenchian Grouping method 正确使用 identity rule