如何使用XSLT进行分组和求和

时间:2013-03-27 21:39:16

标签: xslt bpel

如何在以下情况下使用XSLT 而不使用xsl:for-each-group

我的要求:如果Field1 ..迭代的Field6匹配组中任何迭代的Field1 .. Field6,那么我们需要对数量求和并获取该组的最低ID。

输入

<Shipment>
    <ID>1</ID>
    <Field1>abcd</Field1>
    <Field2>1234</Field2>
    <Field3>efgh</Field4>
    <Field4>5678</Field4>
    <Field5>ijkl</Field5>
    <Field6>90mn</Field6>
    <Amount>200.00</Amount>
</Shipment>
<Shipment>
    <ID>2</ID>
    <Field1>abcd</Field1>
    <Field2>1234</Field2>
    <Field3>efgh</Field4>
    <Field4>5678</Field4>
    <Field5>ijkl</Field5>
    <Field6>90mn</Field6>
    <Amount>600.00</Amount>
</Shipment>
<Shipment>
    <ID>3</ID>
    <Field1>1234</Field1>
    <Field2>abcd</Field2>
    <Field3>efgh</Field4>
    <Field4>5678</Field4>
    <Field5>2345</Field5>
    <Field6>80mn</Field6>
    <Amount>600.00</Amount>
</Shipment>

预期的OutPut

<Shipment>
    <ID>1</ID>  
    <Field1>abcd</Field1>
    <Field2>1234</Field2>
    <Field3>efgh</Field4>
    <Field4>5678</Field4>
    <Field5>ijkl</Field5>
    <Field6>90mn</Field6>
    <Amount>800.00</Amount> 
</Shipment>
<Shipment>
    <ID>2</ID>
    <Field1>1234</Field1>
    <Field2>abcd</Field2>
    <Field3>efgh</Field4>
    <Field4>5678</Field4>
    <Field5>2345</Field5>
    <Field6>80mn</Field6>
    <Amount>600.00</Amount>
</Shipment>

2 个答案:

答案 0 :(得分:1)

不使用xsl:for-each-group的要求明确表明XSLT 2.0处理器不可用

这是一个XSLT 1.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="kAllFields" match="Shipment" use=
 "concat(Field1,'+',Field2,'+',Field3,'+',Field4,'+',Field5,'+',Field6)"/>

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

 <xsl:template match=
  "Shipment
     [not(generate-id()
     =
      generate-id(key('kAllFields',
                      concat(Field1,'+',Field2,'+',Field3,'+',Field4,'+',Field5,'+',Field6))[1]))]
 "/>

 <xsl:template match="Shipment">
  <xsl:variable name="vGroup" select=
  "key('kAllFields', concat(Field1,'+',Field2,'+',Field3,'+',Field4,'+',Field5,'+',Field6))"/>

  <Shipment>
    <ID>
      <xsl:call-template name="min">
        <xsl:with-param name="pItems" select="$vGroup/ID"/>
      </xsl:call-template>
    </ID>
    <xsl:apply-templates select="*[starts-with(name(), 'Field')]"/>
    <Amount><xsl:value-of select="sum($vGroup/Amount)"/></Amount>
  </Shipment>
 </xsl:template>

 <xsl:template name="min">
  <xsl:param name="pItems" select="/.."/>
  <xsl:param name="pDataType" select="'number'"/>

  <xsl:for-each select="$pItems">
    <xsl:sort data-type="{$pDataType}"/>
    <xsl:if test="position() =1"><xsl:value-of select="."/></xsl:if>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档(提供的严重格式错误的片段 - 更正并包装到单个顶部元素中以使其成为格式良好的XML文档):

<t>
    <Shipment>
        <ID>1</ID>
        <Field1>abcd</Field1>
        <Field2>1234</Field2>
        <Field3>efgh</Field3>
        <Field4>5678</Field4>
        <Field5>ijkl</Field5>
        <Field6>90mn</Field6>
        <Amount>200.00</Amount>
    </Shipment>
    <Shipment>
        <ID>2</ID>
        <Field1>abcd</Field1>
        <Field2>1234</Field2>
        <Field3>efgh</Field3>
        <Field4>5678</Field4>
        <Field5>ijkl</Field5>
        <Field6>90mn</Field6>
        <Amount>600.00</Amount>
    </Shipment>
    <Shipment>
        <ID>3</ID>
        <Field1>1234</Field1>
        <Field2>abcd</Field2>
        <Field3>efgh</Field3>
        <Field4>5678</Field4>
        <Field5>2345</Field5>
        <Field6>80mn</Field6>
        <Amount>600.00</Amount>
    </Shipment>
</t>

产生了想要的正确结果

<t>
   <Shipment>
      <ID>1</ID>
      <Field1>abcd</Field1>
      <Field2>1234</Field2>
      <Field3>efgh</Field3>
      <Field4>5678</Field4>
      <Field5>ijkl</Field5>
      <Field6>90mn</Field6>
      <Amount>800</Amount>
   </Shipment>
   <Shipment>
      <ID>3</ID>
      <Field1>1234</Field1>
      <Field2>abcd</Field2>
      <Field3>efgh</Field3>
      <Field4>5678</Field4>
      <Field5>2345</Field5>
      <Field6>80mn</Field6>
      <Amount>600</Amount>
   </Shipment>
</t>

答案 1 :(得分:0)

您需要选择在Field1到Field6中未使用的分隔符。

<xsl:param name="separator" select="'-'"/>
<xsl:template match="/shipments">
    <xsl:for-each-group select="Shipment" group-by="concat(Field1,$separator,Field2,$separator,Field3,$separator,Field4,$separator,Field5,$separator,Field6)">
        <xsl:copy-of select="current-group()[ID=min(current-group()/ID)]"/>
    </xsl:for-each-group>
</xsl:template>

W orking example