Reputation: 687
I'm afraid I have to bother you again with a problem I can't solve myself :( I have an xml where I need an xsl for to do 2 things:
I hope you can help me with this?
Input xml
<?xml version="1.0" encoding="UTF-8"?>
<n0:MT_SmarTour_MultiTripOverview xmlns:n0="urn:deli.com:deli:erp:smartour_shipmentlist" xmlns:prx="urn:sap.com:proxy:SHQ:/1SAI/TASB581ED56DDF13679B0AC:754">
<ShipmentDate>20231020</ShipmentDate>
<ReportType>6</ReportType>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000319003</ShipmentNumber>
</HeaderDetails>
</TripOverview>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000319004</ShipmentNumber>
</HeaderDetails>
</TripOverview>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000400044</ShipmentNumber>
<DropItems>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082063404</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>02</DropNr>
<DeliveryNr>0082063406</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>02</DropNr>
<DeliveryNr>0082063405</DeliveryNr>
</DropItem>
</DropItems>
</HeaderDetails>
</TripOverview>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000400551</ShipmentNumber>
<DropItems>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0084118934</DeliveryNr>
</DropItem>
</DropItems>
</HeaderDetails>
</TripOverview>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000400552</ShipmentNumber>
<DropItems>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067282</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067283</DeliveryNr>
</DropItem>
</DropItems>
</HeaderDetails>
</TripOverview>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000400553</ShipmentNumber>
<DropItems>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067285</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067284</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067286</DeliveryNr>
</DropItem>
</DropItems>
</HeaderDetails>
</TripOverview>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000400555</ShipmentNumber>
<DropItems>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067285</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067284</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067286</DeliveryNr>
</DropItem>
</DropItems>
</HeaderDetails>
</TripOverview>
</n0:MT_SmarTour_MultiTripOverview>
Current xsl:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Preserve indentation -->
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="step1">
<xsl:apply-templates mode="step1"/>
</xsl:variable>
<!-- Skip DropItems with duplicate deliveries (where the same deliverynr exist in multiple TripOverview -->
<xsl:template mode="step1" match="DropItem[DeliveryNr = following::DeliveryNr]"/>
<xsl:variable name="step2">
<xsl:apply-templates select="$step1/node()" mode="step2"/>
</xsl:variable>
<!-- Skip TripOverview elements without DropItems/DropItem -->
<xsl:template mode="step2" match="TripOverview[not(HeaderDetails/DropItems/DropItem)]"/>
<xsl:variable name="step3">
<xsl:apply-templates select="$step2/node()" mode="step3"/>
</xsl:variable>
<!-- Skip TripOverview elements without DropItems -->
<xsl:template mode="step3" match="TripOverview[not(HeaderDetails/DropItems)]"/>
<xsl:variable name="step4">
<xsl:apply-templates select="$step3/node()" mode="step4"/>
</xsl:variable>
<!-- Remove whitespace-only text nodes -->
<xsl:template mode="step4" match="text()[not(parent::*) and not(normalize-space())]"/>
</xsl:stylesheet>
I don't know if the chaining is required, I'm aware that after trying for quite some time I've made a mess of my efforts / xsl. The current output equals the input.
If I don't chain and my xsl looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Preserve indentation -->
<xsl:output method="xml" indent="yes"/>
<!-- Copy all nodes as is except for TripOverview elements without DropItems -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Skip DropItems with duplicate deliveries (where the same deliverynr exist in multiple TripOverview -->
<xsl:template match="DropItem[DeliveryNr = following::DeliveryNr]"/>
<!-- Skip TripOverview elements without DropItems/DropItem -->
<xsl:template match="TripOverview[not(HeaderDetails/DropItems/DropItem)]"/>
<!-- Skip TripOverview elements without DropItems -->
<xsl:template match="TripOverview[not(HeaderDetails/DropItems)]"/>
</xsl:stylesheet>
The duplicate deliverynr elements are removed but I'm stuck with the (empty) TripOverview with no DropItems..
<?xml version="1.0" encoding="UTF-8"?>
<n0:MT_SmarTour_MultiTripOverview xmlns:n0="urn:deli.com:deli:erp:smartour_shipmentlist" xmlns:prx="urn:sap.com:proxy:SHQ:/1SAI/TASB581ED56DDF13679B0AC:754">
<ShipmentDate>20231020</ShipmentDate>
<ReportType>6</ReportType>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000400044</ShipmentNumber>
<DropItems>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082063404</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>02</DropNr>
<DeliveryNr>0082063406</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>02</DropNr>
<DeliveryNr>0082063405</DeliveryNr>
</DropItem>
</DropItems>
</HeaderDetails>
</TripOverview>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000400551</ShipmentNumber>
<DropItems>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0084118934</DeliveryNr>
</DropItem>
</DropItems>
</HeaderDetails>
</TripOverview>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000400552</ShipmentNumber>
<DropItems>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067282</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067283</DeliveryNr>
</DropItem>
</DropItems>
</HeaderDetails>
</TripOverview>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000400553</ShipmentNumber>
<DropItems/>
</HeaderDetails>
</TripOverview>
<TripOverview>
<HeaderDetails>
<ShipmentNumber>0000400555</ShipmentNumber>
<DropItems>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067285</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067284</DeliveryNr>
</DropItem>
<DropItem>
<DropNr>01</DropNr>
<DeliveryNr>0082067286</DeliveryNr>
</DropItem>
</DropItems>
</HeaderDetails>
</TripOverview>
</n0:MT_SmarTour_MultiTripOverview>
My code / example xml might be more confusing than helping so I'll repeat my goal: From the input xml check for DeliveryNr elements which exist multiple times over X TripOverView elements and only keep the first. If the result has no DropItems or DropItems has no children delete the TripOverview elements.
Kind regards,
Mike
Upvotes: 0
Views: 40
Reputation: 167641
Add
<xsl:template match="/">
<xsl:sequence select="$step4"/>
</xsl:template>
and make sure you identity transformation template is "mode" safe:
<xsl:template match="@*|node()" mode="#all">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="#current"/>
</xsl:copy>
</xsl:template>
Upvotes: 1