Kiran
Kiran

Reputation: 13

How to apply for-each-group in XSLT with Apache Camel

I am trying to use group by in Apache Camel XSLT but when using for-each-group with sytlesheet version 2.0 ending up with exception "javax.xml.transform.TransformerException: "select" attribute is not allowed on the xsl:for-each-group element!". Below is my updated code.

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:template match="/">
        <MESSAGES>
            <xsl:for-each-group
                select="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent"
                group-by="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/WebOrderId">
                <COMMANDSTATUS>
                    <xsl:attribute name="ID">SHIPPED</xsl:attribute>
                    <xsl:attribute name="DESCRIPTION">Goods Shipped</xsl:attribute>
                    <ORDER>
                        <xsl:attribute name="O_ID"><xsl:value-of
                            select='distinct-values(/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/WebOrderId)' /></xsl:attribute>
                        <xsl:choose>
                        <xsl:when
                            test="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderSource = 'STORE-ORDER'">
                            <xsl:attribute name="TRACKING_URL">https://www.fedex.com/apps/fedextrack/?tracknumbers=<xsl:value-of
                                select='distinct-values(/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderShipmentDetails/OrderShipmentDetail/ShippingTrackingNumber)' /></xsl:attribute>
                        </xsl:when>
                        <xsl:when
                            test="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderSource != 'STORE-ORDER'">
                            <xsl:attribute name="TRACKING_URL">http://wwwapps.<xsl:value-of
                                select='distinct-values(/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderShipmentDetails/OrderShipmentDetail/ShippingCarrier)' />.com/WebTracking/track?track=yes&amp;trackNums=<xsl:value-of
                                select='distinct-values(/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderShipmentDetails/OrderShipmentDetail/ShippingTrackingNumber)' /></xsl:attribute>
                        </xsl:when>
                        </xsl:choose>
                        <xsl:for-each
                            select="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent">
                            <ORDER_LINE>
                                <xsl:attribute name="OL_ID"><xsl:value-of
                                    select='OrderLineId' /></xsl:attribute>
                                <xsl:choose>
                                    <xsl:when test="substring(ItemId, 0, 6) = '88-00'">
                                        <xsl:attribute name="SKU"><xsl:value-of
                                            select='substring(ItemId, 6)' /></xsl:attribute>
                                    </xsl:when>
                                    <xsl:otherwise>
                                        <xsl:attribute name="SKU"><xsl:value-of
                                            select='ItemId' /></xsl:attribute>
                                    </xsl:otherwise>
                                </xsl:choose>
                                <xsl:attribute name="QUANTITY"><xsl:value-of
                                    select='distinct-values(/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderStatusDetails/OrderStatusDetail/Qty)' /></xsl:attribute>
                            </ORDER_LINE>
                        </xsl:for-each>
                    </ORDER>
                </COMMANDSTATUS>
            </xsl:for-each-group>
        </MESSAGES>
    </xsl:template>
</xsl:stylesheet>

Input XML:

<?xml version="1.0" encoding="utf-8"?>
<OrderStatusUpdate fileType="Order Status Update" fileStartTime="2021-10-13 06:20:18 " fileEndTime=" 2021-10-13 07:35:26">
    <MessageHeader>
        <Standard>eBay_Enterprise</Standard>
        <HeaderVersion>EWS_eb2c_1.1</HeaderVersion>
        <VersionReleaseNumber>EWS_eb2c_1.1</VersionReleaseNumber>
        <SourceData>
            <SourceId>OMS</SourceId>
            <SourceType>OrderManagementSystem</SourceType>
        </SourceData>
        <DestinationData>
            <DestinationId>EE_OrderRTStatusXML</DestinationId>
            <DestinationType>MAILBOX</DestinationType>
        </DestinationData>
        <EventType>OrderStatus</EventType>
        <MessageData>
            <MessageId>20211013073625</MessageId>
            <CorrelationId>0</CorrelationId>
        </MessageData>
        <CreateDateAndTime>2021-10-13 07:36:25</CreateDateAndTime>
    </MessageHeader>
    <OrderStatusEvents>
        <OrderStatusEvent>
            <StoreCode>R21_US</StoreCode>
            <OrderId>101425120920</OrderId>
            <ExternalOrderId/>
            <WebOrderId>002010003694706_1</WebOrderId>
            <OrderSource type=""/>
            <OrderLineId>1</OrderLineId>
            <OriginalOrderId/>
            <OriginalWebOrderId/>
            <OriginalOrderLineId/>
            <ItemId>88-0028547859</ItemId>
            <OrderStatusDetails>
                <OrderStatusDetail>
                    <OrderStatusEventTimeStamp>2021-10-13 07:20:23</OrderStatusEventTimeStamp>
                    <StatusName>Fulfilled and Invoiced</StatusName>
                    <ReturnReason/>
                    <Qty>1</Qty>
                    <CancelReason/>
                    <CancelReasonText/>
                </OrderStatusDetail>
            </OrderStatusDetails>
            <OrderShipmentDetails>
                <OrderShipmentDetail>
                    <ShippingCarrier>UPS</ShippingCarrier>
                    <ShippingServiceLevel>PBX01</ShippingServiceLevel>
                    <ShippingTrackingNumber>1ZEW3567YW46706215</ShippingTrackingNumber>
                    <ShippingTimestamp>2021-10-13 07:12:00</ShippingTimestamp>
                </OrderShipmentDetail>
            </OrderShipmentDetails>
        </OrderStatusEvent>
        <OrderStatusEvent>
            <StoreCode>R21_US</StoreCode>
            <OrderId>101425120920</OrderId>
            <ExternalOrderId/>
            <WebOrderId>002010003694706_1</WebOrderId>
            <OrderSource type=""/>
            <OrderLineId>3</OrderLineId>
            <OriginalOrderId/>
            <OriginalWebOrderId/>
            <OriginalOrderLineId/>
            <ItemId>88-0028461473</ItemId>
            <OrderStatusDetails>
                <OrderStatusDetail>
                    <OrderStatusEventTimeStamp>2021-10-13 07:20:23</OrderStatusEventTimeStamp>
                    <StatusName>Fulfilled and Invoiced</StatusName>
                    <ReturnReason/>
                    <Qty>1</Qty>
                    <CancelReason/>
                    <CancelReasonText/>
                </OrderStatusDetail>
            </OrderStatusDetails>
            <OrderShipmentDetails>
                <OrderShipmentDetail>
                    <ShippingCarrier>UPS</ShippingCarrier>
                    <ShippingServiceLevel>PBX01</ShippingServiceLevel>
                    <ShippingTrackingNumber>1ZEW3567YW46706215</ShippingTrackingNumber>
                    <ShippingTimestamp>2021-10-13 07:12:00</ShippingTimestamp>
                </OrderShipmentDetail>
            </OrderShipmentDetails>
        </OrderStatusEvent>
        <OrderStatusEvent>
            <StoreCode>R21_US</StoreCode>
            <OrderId>101425254810</OrderId>
            <ExternalOrderId/>
            <WebOrderId>002010003698153_1</WebOrderId>
            <OrderSource type=""/>
            <OrderLineId>1</OrderLineId>
            <OriginalOrderId/>
            <OriginalWebOrderId/>
            <OriginalOrderLineId/>
            <ItemId>88-0028353647</ItemId>
            <OrderStatusDetails>
                <OrderStatusDetail>
                    <OrderStatusEventTimeStamp>2021-10-13 06:40:15</OrderStatusEventTimeStamp>
                    <StatusName>Fulfilled and Invoiced</StatusName>
                    <ReturnReason/>
                    <Qty>1</Qty>
                    <CancelReason/>
                    <CancelReasonText/>
                </OrderStatusDetail>
            </OrderStatusDetails>
            <OrderShipmentDetails>
                <OrderShipmentDetail>
                    <ShippingCarrier>UPS</ShippingCarrier>
                    <ShippingServiceLevel>PBX03</ShippingServiceLevel>
                    <ShippingTrackingNumber>1ZEW3571YW13958113</ShippingTrackingNumber>
                    <ShippingTimestamp>2021-10-13 06:30:00</ShippingTimestamp>
                </OrderShipmentDetail>
            </OrderShipmentDetails>
        </OrderStatusEvent>
        <OrderStatusEvent>
            <StoreCode>R21_US</StoreCode>
            <OrderId>101425254810</OrderId>
            <ExternalOrderId/>
            <WebOrderId>002010003698153_1</WebOrderId>
            <OrderSource type=""/>
            <OrderLineId>2</OrderLineId>
            <OriginalOrderId/>
            <OriginalWebOrderId/>
            <OriginalOrderLineId/>
            <ItemId>88-0028635431</ItemId>
            <OrderStatusDetails>
                <OrderStatusDetail>
                    <OrderStatusEventTimeStamp>2021-10-13 06:40:15</OrderStatusEventTimeStamp>
                    <StatusName>Fulfilled and Invoiced</StatusName>
                    <ReturnReason/>
                    <Qty>1</Qty>
                    <CancelReason/>
                    <CancelReasonText/>
                </OrderStatusDetail>
            </OrderStatusDetails>
            <OrderShipmentDetails>
                <OrderShipmentDetail>
                    <ShippingCarrier>UPS</ShippingCarrier>
                    <ShippingServiceLevel>PBX03</ShippingServiceLevel>
                    <ShippingTrackingNumber>1ZEW3571YW13958113</ShippingTrackingNumber>
                    <ShippingTimestamp>2021-10-13 06:30:00</ShippingTimestamp>
                </OrderShipmentDetail>
            </OrderShipmentDetails>
        </OrderStatusEvent>
    </OrderStatusEvents>
</OrderStatusUpdate>

Expected XML:

<?xml version='1.0' encoding='UTF-8'?>
<MESSAGES>
  <COMMANDSTATUS ID="SHIPPED" DESCRIPTION="Goods Shipped">
    <ORDER O_ID="002010003694706_1" TRACKING_URL="http://wwwapps.UPS.com/WebTracking/track?track=yes&amp;trackNums=1ZEW3567YW46706215">
      <ORDER_LINE OL_ID="1" SKU="28547859" QUANTITY="1"/>
      <ORDER_LINE OL_ID="3" SKU="28461473" QUANTITY="1"/>
    </ORDER>
  </COMMANDSTATUS>
  <COMMANDSTATUS ID="SHIPPED" DESCRIPTION="Goods Shipped">
    <ORDER O_ID="002010003698153_1" TRACKING_URL="http://wwwapps.UPS.com/WebTracking/track?track=yes&amp;trackNums=1ZEW3571YW13958113">
      <ORDER_LINE OL_ID="1" SKU="28353647" QUANTITY="1"/>
      <ORDER_LINE OL_ID="2" SKU="28635431" QUANTITY="1"/>
    </ORDER>
  </COMMANDSTATUS>
</MESSAGES>

I tried with 1.0 version as well but didn't get through, below is the code for the same.

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:key name="webOrderId"
        match="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent"
        use="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/WebOrderId" />
    <xsl:variable name="uppercase"
        select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
    <xsl:variable name="lowercase"
        select="'abcdefghijklmnopqrstuvwxyz'" />
    <xsl:template match="/">
        <MESSAGES>
            <xsl:for-each
                select="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent[count(. | key('webOrderId', /OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/WebOrderId)[1]) = 1]">
                <xsl:for-each select="key('webOrderId', /OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/WebOrderId)">
                    <COMMANDSTATUS>
                        <xsl:attribute name="ID">SHIPPED</xsl:attribute>
                        <xsl:attribute name="DESCRIPTION">Goods Shipped</xsl:attribute>
                        <ORDER>
                            <xsl:choose>
                                <xsl:when
                                    test="substring(/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/WebOrderId, 0, 6) = '00201'">
                                    <xsl:attribute name="O_ID"><xsl:value-of
                                        select='substring(/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/WebOrderId, 6)' /></xsl:attribute>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:attribute name="O_ID"><xsl:value-of
                                        select='/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/WebOrderId' /></xsl:attribute>
                                </xsl:otherwise>
                            </xsl:choose>
                            <xsl:choose>
                                <xsl:when
                                    test="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderSource = 'STORE-ORDER'">
                                    <xsl:attribute name="TRACKING_URL">https://www.fedex.com/apps/fedextrack/?tracknumbers=<xsl:value-of
                                        select='/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderShipmentDetails/OrderShipmentDetail/ShippingTrackingNumber' /></xsl:attribute>
                                </xsl:when>
                                <xsl:when
                                    test="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderSource != 'STORE-ORDER'">
                                    <xsl:attribute name="TRACKING_URL">http://wwwapps.<xsl:value-of
                                        select='/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderShipmentDetails/OrderShipmentDetail/ShippingCarrier' />.com/WebTracking/track?track=yes&amp;trackNums=<xsl:value-of
                                        select='/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderShipmentDetails/OrderShipmentDetail/ShippingTrackingNumber' /></xsl:attribute>
                                </xsl:when>
                            </xsl:choose>
                            <xsl:for-each
                                select="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent">
                                <ORDER_LINE>
                                    <xsl:attribute name="OL_ID"><xsl:value-of
                                        select='OrderLineId' /></xsl:attribute>
                                    <xsl:choose>
                                        <xsl:when test="substring(ItemId, 0, 6) = '88-00'">
                                            <xsl:attribute name="SKU"><xsl:value-of
                                                select='substring(ItemId, 6)' /></xsl:attribute>
                                        </xsl:when>
                                        <xsl:otherwise>
                                            <xsl:attribute name="SKU"><xsl:value-of
                                                select='ItemId' /></xsl:attribute>
                                        </xsl:otherwise>
                                    </xsl:choose>
                                    <xsl:attribute name="QUANTITY"><xsl:value-of
                                        select='/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderStatusDetails/OrderStatusDetail/Qty' /></xsl:attribute>
                                </ORDER_LINE>
                            </xsl:for-each>
                        </ORDER>
                    </COMMANDSTATUS>
                </xsl:for-each>
            </xsl:for-each>
        </MESSAGES>
    </xsl:template>
</xsl:stylesheet>

Below is the output received with above code which is not expected.

<?xml version="1.0" encoding="UTF-8"?>
<MESSAGES>
   <COMMANDSTATUS ID="SHIPPED" DESCRIPTION="Goods Shipped">
      <ORDER O_ID="002010003694706_1 002010003698153_1"
             TRACKING_URL="http://wwwapps.UPS.com/WebTracking/track?track=yes&amp;trackNums=1ZEW3567YW46706215 1ZEW3571YW13958113">
         <ORDER_LINE OL_ID="1" SKU="28547859" QUANTITY="1"/>
         <ORDER_LINE OL_ID="3" SKU="28461473" QUANTITY="1"/>
         <ORDER_LINE OL_ID="1" SKU="28353647" QUANTITY="1"/>
         <ORDER_LINE OL_ID="2" SKU="28635431" QUANTITY="1"/>
      </ORDER>
   </COMMANDSTATUS>
   <COMMANDSTATUS ID="SHIPPED" DESCRIPTION="Goods Shipped">
      <ORDER O_ID="002010003694706_1 002010003698153_1"
             TRACKING_URL="http://wwwapps.UPS.com/WebTracking/track?track=yes&amp;trackNums=1ZEW3567YW46706215 1ZEW3571YW13958113">
         <ORDER_LINE OL_ID="1" SKU="28547859" QUANTITY="1"/>
         <ORDER_LINE OL_ID="3" SKU="28461473" QUANTITY="1"/>
         <ORDER_LINE OL_ID="1" SKU="28353647" QUANTITY="1"/>
         <ORDER_LINE OL_ID="2" SKU="28635431" QUANTITY="1"/>
      </ORDER>
   </COMMANDSTATUS>
</MESSAGES>

Upvotes: 0

Views: 263

Answers (2)

Kiran
Kiran

Reputation: 13

Here is the XSLT code which is working for my use case.

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:template match="/">
        <MESSAGES>
            <xsl:for-each-group
                select="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent"
                group-by="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/WebOrderId">
                <COMMANDSTATUS>
                    <xsl:attribute name="ID">SHIPPED</xsl:attribute>
                    <xsl:attribute name="DESCRIPTION">Goods Shipped</xsl:attribute>
                    <ORDER>
                        <xsl:choose>
                            <xsl:when
                                test="substring(current-grouping-key(), 0, 6) = '00201'">
                                <xsl:attribute name="O_ID"><xsl:value-of
                                    select='substring(current-grouping-key(), 6)' /></xsl:attribute>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:attribute name="O_ID"><xsl:value-of
                                    select='current-grouping-key()' /></xsl:attribute>
                            </xsl:otherwise>
                        </xsl:choose>
                        <xsl:for-each
                            select="current-group()[WebOrderId = current-grouping-key()]">
                            <xsl:choose>
                                <xsl:when
                                    test="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderSource = 'STORE-ORDER'">
                                    <xsl:attribute name="TRACKING_URL">https://www.fedex.com/apps/fedextrack/?tracknumbers=<xsl:value-of
                                        select='./OrderShipmentDetails/OrderShipmentDetail/ShippingTrackingNumber' /></xsl:attribute>
                                </xsl:when>
                                <xsl:when
                                    test="/OrderStatusUpdate/OrderStatusEvents/OrderStatusEvent/OrderSource != 'STORE-ORDER'">
                                    <xsl:attribute name="TRACKING_URL">http://wwwapps.<xsl:value-of
                                        select='./OrderShipmentDetails/OrderShipmentDetail/ShippingCarrier' />.com/WebTracking/track?track=yes&amp;trackNums=<xsl:value-of
                                        select='./OrderShipmentDetails/OrderShipmentDetail/ShippingTrackingNumber' /></xsl:attribute>
                                </xsl:when>
                            </xsl:choose>
                        </xsl:for-each>
                        <xsl:for-each
                            select="current-group()[WebOrderId = current-grouping-key()]">
                            <ORDER_LINE>
                                <xsl:attribute name="OL_ID"><xsl:value-of
                                    select='OrderLineId' /></xsl:attribute>
                                <xsl:choose>
                                    <xsl:when test="substring(ItemId, 0, 6) = '88-00'">
                                        <xsl:attribute name="SKU"><xsl:value-of
                                            select='substring(ItemId, 6)' /></xsl:attribute>
                                    </xsl:when>
                                    <xsl:otherwise>
                                        <xsl:attribute name="SKU"><xsl:value-of
                                            select='ItemId' /></xsl:attribute>
                                    </xsl:otherwise>
                                </xsl:choose>
                                <xsl:attribute name="QUANTITY"><xsl:value-of
                                    select='./OrderStatusDetails/OrderStatusDetail/Qty' /></xsl:attribute>
                            </ORDER_LINE>
                        </xsl:for-each>
                    </ORDER>
                </COMMANDSTATUS>
            </xsl:for-each-group>
        </MESSAGES>
    </xsl:template>
</xsl:stylesheet>

Thanks!

Upvotes: 0

burki
burki

Reputation: 7035

You don't show how your route code how the XSL is called, but I suppose it is executed with the standard Java XSL processor (who does not support XSL 2).

You need to explicitly tell Camel to use Saxon as XSL processor to be able to use XSL 2.

In Camel 3.x there is a dedicated Saxon component

to("xslt-saxon:path/to/yourStylesheet.xsl");

In Camel 2.x this was done with a URL option

.to("xslt:path/to/yourStylesheet.xsl?saxon=true")

Of course you also have to add Saxon as a dependency.

Upvotes: 0

Related Questions