使用XSLT对值进行分组和求和

时间:2015-02-05 17:10:21

标签: xml xslt key

我有一个看起来像这样的xml:

 <?xml version="1.0" encoding="windows-1252" ?>
<Shipment xmlns="http://oracle.com/EbizGateway/NA/SynchASN/V2">
    <containerDetails>
        <ContainerID>C123</ContainerID>
        <DeliveryContainer>
            <ContainerType>Plastic</ContainerType>
            <PackedOrder>
                <OrderNumber>O1234</OrderNumber>
                <PackedItem>
                    <controldata>
                        <suppliernumber>A123</suppliernumber>
                        <customernumner>123</customernumner>
                    </controldata>
                    <ShipmentDetails>
                        <ShippedQuantity>3</ShippedQuantity>
                    </ShipmentDetails>
                </PackedItem>
                <PackedItem>
                    <controldata>
                        <suppliernumber>A123</suppliernumber>
                        <customernumner>123</customernumner>
                    </controldata>
                    <ShipmentDetails>
                        <ShippedQuantity>2</ShippedQuantity>
                    </ShipmentDetails>
                </PackedItem>
                <PackedItem>
                    <controldata>
                        <suppliernumber>A234</suppliernumber>
                        <customernumner>234</customernumner>
                    </controldata>
                    <ShipmentDetails>
                        <ShippedQuantity>2</ShippedQuantity>
                    </ShipmentDetails>
                </PackedItem>
            </PackedOrder>
    </DeliveryContainer>
    </containerDetails>
</Shipment>

我需要根据ContainerID,suppliernumber,customernumner,ShippedQuantity对每个PackedItem进行分组。

分组后,我需要为PackedItem的所有重复出现添加发货数量。例如:

ContainerID     suppliernumber      customernumber      ShippedQuantity
C123                A123                    123                     3
C123                A123                    123                     2
C123                A234                    234                     2

由于前两次出现重复,因此需要添加数量 这必须转换如下

ContainerID     suppliernumber      customernumber       ShippedQuantity
C123                A123                    123                     5
C123                A234                    234                     2

在我将所需的数量相加后,我需要在两个重复的事件中更新ShippedQuantity,如下面的xml所示。除了ShippedQuantity之外,其他值将按原样复制。

    <?xml version="1.0" encoding="windows-1252" ?>
<Shipment xmlns="http://oracle.com/EbizGateway/NA/SynchASN/V2">
    <containerDetails>
        <ContainerID>C123</ContainerID>
        <DeliveryContainer>
            <ContainerType>Plastic</ContainerType>
            <PackedOrder>
                <OrderNumber>O1234</OrderNumber>
                <PackedItem>
                    <controldata>
                        <suppliernumber>A123</suppliernumber>
                        <customernumner>123</customernumner>
                    </controldata>
                    <ShipmentDetails>
                        <ShippedQuantity>5</ShippedQuantity>
                    </ShipmentDetails>
                </PackedItem>
                <PackedItem>
                    <controldata>
                        <suppliernumber>A123</suppliernumber>
                        <customernumner>123</customernumner>
                    </controldata>
                    <ShipmentDetails>
                        <ShippedQuantity>5</ShippedQuantity>
                    </ShipmentDetails>
                </PackedItem>
                <PackedItem>
                    <controldata>
                        <suppliernumber>A234</suppliernumber>
                        <customernumner>234</customernumner>
                    </controldata>
                    <ShipmentDetails>
                        <ShippedQuantity>2</ShippedQuantity>
                    </ShipmentDetails>
                </PackedItem>
            </PackedOrder>
    </DeliveryContainer>
    </containerDetails>
</Shipment>

我尝试了很多选项,但是不能真正理解如何填充每个重复的packedItem中的出货量的总和。 :( PFB xslt下面我尝试了相同..它虽然不起作用..

<xsl:key name="ContRef" match="tns:PackedItem"
    use="concat(../../../tns:ContainerID,../../tns:ContainerType,./tns:controldata/tns:suppliernumber,./tns:controldata/tns:customernumner,./tns:ShipmentDetails/tns:ShippedQuantity,' ',generate-id(./ancestor::tns:containerDetails))"/>
  <xsl:template match="/">
    <tns:Shipment>
      <xsl:for-each select="/tns:Shipment">
        <xsl:for-each select="./tns:containerDetails/tns:DeliveryContainer/tns:PackedOrder/tns:PackedItem[generate-id(.)=generate-id(key('ContRef',concat(../../../tns:ContainerID,../../tns:ContainerType,./tns:controldata/tns:suppliernumber,./tns:controldata/tns:customernumner,./tns:ShipmentDetails/tns:ShippedQuantity,' ',generate-id(./ancestor::tns:containerDetails))))]">
          <xsl:variable name="ContID"
            select="../../../tns:ContainerID"/>
          <xsl:variable name="CustPartNumber"
            select="./tns:controldata/tns:customernumner"/>

          <xsl:variable name="SuppPartNumber"
            select="./tns:controldata/tns:suppliernumber"/>

          <xsl:variable name="ShippedQty"
            select="./tns:ShipmentDetails/tns:ShippedQuantity"/>

          <!-- calculate total shipped quantity-->
           <xsl:variable name="TotalShippedQuantity"
            select="sum(key('ContRef',concat(../../../tns:ContainerID,../../tns:ContainerType,./tns:controldata/tns:suppliernumber,./tns:controldata/tns:customernumner,./tns:ShipmentDetails/tns:ShippedQuantity,' ',generate-id(./ancestor::tns:containerDetails)))/tns:ShipmentDetails/tns:ShippedQuantity)"/>

          <!-- populate the total shipped quantity in each duplicate packed item -->
          <xsl:for-each select="../tns:PackedItem[./tns:controldata/tns:customernumner=$CustPartNumber and ./tns:controldata/tns:suppliernumber=$SuppPartNumber and ./tns:ShipmentDetails/tns:ShippedQuantity=$ShippedQty]/tns:ShipmentDetails/tns:ShippedQuantity">
                        <xsl:text>inside for</xsl:text>
                        <xsl:value-of select="$TotalShippedQuantity"/>
                    </xsl:for-each>
        </xsl:for-each>
      </xsl:for-each>
    </tns:Shipment>
  </xsl:template>

请建议。

1 个答案:

答案 0 :(得分:0)

如果您希望根据PackedItemContainerIDsuppliernumber对每个customernumner进行分组,那么密钥应该如下所示....

<xsl:key name="ContRef"  
     match="tns:PackedItem"
     use="concat(../../../tns:ContainerID, '|', tns:controldata/tns:suppliernumber, '|', tns:controldata/tns:customernumner)"/>

然后,要获取组中的不同项目,请执行以下操作:

<xsl:for-each 
     select="//tns:PackedItem
             [generate-id(.) = generate-id(key('ContRef',concat(../../../tns:ContainerID, '|', tns:controldata/tns:suppliernumber, '|', tns:controldata/tns:customernumner)[1]))]">

要获得ShippedQuantity的总和,您可以使用sum函数对当前密钥中的所有相关组进行求和

<xsl:value-of 
     select="sum(key('ContRef',concat(../../../tns:ContainerID, '|', tns:controldata/tns:suppliernumber, '|', tns:controldata/tns:customernumner))/tns:ShipmentDetails/tns:ShippedQuantity)" />

尝试使用此XSLT作为初学者

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:tns="http://oracle.com/EbizGateway/NA/SynchASN/V2">
    <xsl:output method="xml" indent="yes" />

<xsl:key name="ContRef" 
         match="tns:PackedItem"
         use="concat(../../../tns:ContainerID, '|', tns:controldata/tns:suppliernumber, '|', tns:controldata/tns:customernumner)"/>

  <xsl:template match="/">
    <tns:Shipment>
    <xsl:for-each select="//tns:PackedItem[generate-id(.)=generate-id(key('ContRef',concat(../../../tns:ContainerID, '|', tns:controldata/tns:suppliernumber, '|', tns:controldata/tns:customernumner)[1]))]">
      <!-- populate the total shipped quantity in each duplicate packed item -->
      <tns:PackedItems>
        <tns:ContainerID>
            <xsl:value-of select="../../../tns:ContainerID" />
        </tns:ContainerID>
        <tns:suppliernumber>
            <xsl:value-of select="tns:controldata/tns:suppliernumber" />
        </tns:suppliernumber>
        <tns:customernumner>
            <xsl:value-of select="tns:controldata/tns:customernumner" />
        </tns:customernumner>
        <tns:ShippedQuantity>
            <xsl:value-of select="sum(key('ContRef',concat(../../../tns:ContainerID, '|', tns:controldata/tns:suppliernumber, '|', tns:controldata/tns:customernumner))/tns:ShipmentDetails/tns:ShippedQuantity)" />
        </tns:ShippedQuantity>
      </tns:PackedItems>
    </xsl:for-each>
    </tns:Shipment>
  </xsl:template>
</xsl:transform>