XSLT转换。乘以然后求和

时间:2013-02-18 07:21:38

标签: xslt xslt-1.0 xslt-2.0

我需要通过添加订单价格总和将我的XML从一种格式转换为另一种格式。计算结果为Sum total (itemPrice*itemQty)。我的请求XML如下:

 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
       <soap:Body>
          <ns2:fetchOrderListResponse xmlns:ns2="http://impl.lob.xyz.com/">
             <return>
                <customerOrderNumber>1</customerOrderNumber>
                <orderDetails>
                   <itemPrice>2.0</itemPrice>
  <itemQty>1</itemQty>
                   <orderDetailsId>37516016-D71B-4790-951F-55D00B0CC159</orderDetailsId>
                </orderDetails>
                <orderDetails>
                   <itemPrice>5.0</itemPrice>
                   <itemQty>3</itemQty>
                   <itemUnit>0</itemUnit>
                </orderDetails>
                <orderId>84EC371D-40CA-455E-A0FA-7EA733E9BFD3</orderId>
             </return>
             <return>
                <customerOrderNumber>1</customerOrderNumber>
                <deliverydate>2013-02-06T00:00:00+05:30</deliverydate>
                <orderDetails>
                   <itemPrice>7.0</itemPrice>
                   <itemQty>1</itemQty>
                   <orderDetailsId>9A5030BE-F95F-4C62-B5A2-41FF85423218</orderDetailsId>
                </orderDetails>
                <orderDetails>
                   <itemPrice>9.0</itemPrice>
                   <itemQty>5</itemQty>
                   <orderDetailsId>65A8B3BE-D407-43D8-8754-EA1E26AA56E4</orderDetailsId>
                </orderDetails>
                <orderId>0BDCB222-0117-47A9-8813-DF03A1D19E5E</orderId>
             </return>
          </ns2:fetchOrderListResponse>
       </soap:Body>
    </soap:Envelope>

我需要在广告添加后将其转换为以下格式吗?使用XSLT的元素。转换后的XML应如下所示。请在这里提供帮助。

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns2:fetchOrderListResponse xmlns:ns2="http://impl.lob.xyz.com/">
         <return>
            <customerOrderNumber>1</customerOrderNumber>
            <orderDetails>
               <itemPrice>2.0</itemPrice>
               <itemQty>1</itemQty>
               <orderDetailsId>37516016-D71B-4790-951F-55D00B0CC159</orderDetailsId>
            </orderDetails>
            <orderDetails>
               <itemPrice>5.0</itemPrice>
               <itemQty>3</itemQty>
            </orderDetails>
            <orderId>84EC371D-40CA-455E-A0FA-7EA733E9BFD3</orderId>
            **<ordertotal>17.0</ordertotal>**
         </return>
         <return>
            <customerOrderNumber>1</customerOrderNumber>
            <deliverydate>2013-02-06T00:00:00+05:30</deliverydate>
            <orderDetails>
               <itemPrice>7.0</itemPrice>
               <itemQty>1</itemQty>
               <orderDetailsId>9A5030BE-F95F-4C62-B5A2-41FF85423218</orderDetailsId>
            </orderDetails>
            <orderDetails>
               <itemPrice>9.0</itemPrice>
               <itemQty>5</itemQty>
               <orderDetailsId>65A8B3BE-D407-43D8-8754-EA1E26AA56E4</orderDetailsId>
            </orderDetails>
            <orderId>0BDCB222-0117-47A9-8813-DF03A1D19E5E</orderId>
            **<ordertotal>52.0</ordertotal>**
         </return>
      </ns2:fetchOrderListResponse>
   </soap:Body>
</soap:Envelope>

2 个答案:

答案 0 :(得分:1)

XSLT 2.0解决方案将是:

<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" />

    <!-- Identity template : elements and attributes are copied by default -->
    <xsl:template match="*|@*">
        <xsl:copy>
            <xsl:apply-templates select="*|@*" />
        </xsl:copy>
    </xsl:template>

    <!-- When matching return we add the order total as its last child -->
    <xsl:template match="return">
        <xsl:copy>
            <xsl:copy-of select="@*|*" />
            <ordertotal>
                <xsl:value-of select="sum(orderDetails/(itemPrice*itemQty))" />
            </ordertotal>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

如果您使用的是XSLT 1.0(没有扩展功能),您必须使用递归来实现您想要的目标:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" />

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

    <xsl:template match="return">
        <xsl:copy>
            <xsl:copy-of select="@*|*" />
            <ordertotal><xsl:call-template name="calculate-total" /></ordertotal>
        </xsl:copy>
    </xsl:template>

    <!-- Recursive template -->
    <xsl:template name="calculate-total">
        <!-- Select by default the set of orderDetails from the current context -->
        <xsl:param name="orderDetails"
                   select="orderDetails" />
        <!-- Param which is going to keep track of the result step by step -->
        <xsl:param name="total"
                   select="'0'" />

        <xsl:choose>
            <!-- If we have remaining order details, recurse -->
            <xsl:when test="$orderDetails">
                <xsl:call-template name="calculate-total">
                    <!-- Remove the current element for the next step -->
                    <xsl:with-param name="orderDetails"
                                    select="$orderDetails[position() > 1]" />
                    <!-- Do the partial operation for the current element, and continue to the next step -->
                    <xsl:with-param name="total"
                                    select="$total + ($orderDetails[1]/itemPrice * $orderDetails[1]/itemQty)" />
                </xsl:call-template>        
            </xsl:when>
            <!-- Output the result -->
            <xsl:otherwise>
                <xsl:value-of select="$total" />
            </xsl:otherwise>
        </xsl:choose>

    </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

您已经标记了XSLT2.0这个问题,这意味着它可以直接进行求和。假设您位于返回元素上,您只需执行此操作即可获得ordertotal

<ordertotal>
   <xsl:value-of select="sum(orderDetails/(itemPrice * itemQty))"/>
</ordertotal>

所有其他元素都可以通过XSLT标识转换进行复制。

这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="return">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
         <ordertotal>
            <xsl:value-of select="sum(orderDetails/(itemPrice * itemQty))"/>
         </ordertotal>
      </xsl:copy>
   </xsl:template>

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

第一个返回元素的订单总数应为17,第二个元素的订单总数为52.