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

Use XSLT to group and sum a value

我有一个 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>

请指教

如果您想根据 ContainerIDsuppliernumbercustomernumner 按每个 PackedItem 进行分组,那么键应该如下所示....

<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函数对当前key

中的所有相关组求和
<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>