2015-02-05 6 views
0

У меня есть XML, который выглядит следующим образом:Использование XSLT для группы и суммировать значения

<?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> 

Мне нужно сгруппировать каждый PackedItem на основе ContainerID, suppliernumber, customernumner, ShippedQuantity.

После сгруппировки мне нужно добавить количество отправленных для всех дубликатов в 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> 

Я пробовал много вариантов, но не могу понять, как заполнить сумму shippedquantities в каждом дубликата 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> 

Пожалуйста, советы.

+0

HTTP://stackoverflow.com/questions/28259342/how-to-group-data-from-one-xml-to-other-using-xslt#comment44879293_28259342 –

+0

PFA xslt (что я пытался) в моем вопросе выше. Я был бы очень благодарен за любые намеки на это. – moon

+0

Я могу рассчитать сумму теперь со следующей модификацией в моем xslt. Однако до сих пор не известно, как заполнить это значение в двух экземплярах PackedItems и скопировать остальную часть полезной нагрузки, как есть. moon

ответ

0

Если вы хотите сгруппировать по каждой PackedItem на основе ContainerID, suppliernumber и 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> 
+0

Привет Тим , Спасибо за ответ. Я попытался использовать xslt, как было предложено в вашем сообщении .. но это вызывает ошибку в операторе for-each, в котором указано: «Значение не является набором узлов» – moon

+0

Взгляните на http://xsltransform.net/gWmuiJm, который показывает, что XSLT в моем ответе работает счастливо. Благодаря! –

+0

Спасибо за ответ Тиму :) – moon

Смежные вопросы