Stack Overflow Asked by Shuaipeng Zhang on January 9, 2021
Relatively new to XSLT.
Here’s a sample XML:
<Shipments>
<Shipment>
<ErpOrder>415580479</ErpOrder>
<Containers>
<ShippingContainer>
<TreeUnit>12211620</TreeUnit>
<WeightUm>L</WeightUm>
</ShippingContainer>
</Containers>
</Shipment>
<Shipment>
<ErpOrder>415580479</ErpOrder>
</Shipment>
<Shipment>
<ErpOrder>5124516</ErpOrder>
</Shipment>
</Shipments>
I want to copy the <Containers>
node and all child tag within that node to any <Shipment>
tag that matches the <ErpOrder>
value and is missing the <Containers>
node.
Output:
<Shipments>
<Shipment>
<ErpOrder>415580479</ErpOrder>
<Containers>
<ShippingContainer>
<TreeUnit>12211620</TreeUnit>
<WeightUm>L</WeightUm>
</ShippingContainer>
</Containers>
</Shipment>
<Shipment>
<ErpOrder>415580479</ErpOrder>
<Containers>
<ShippingContainer>
<TreeUnit>12211620</TreeUnit>
<WeightUm>L</WeightUm>
</ShippingContainer>
</Containers>
</Shipment>
<Shipment>
<ErpOrder>5124516</ErpOrder>
</Shipment>
</Shipments>
What I have so far, but I think is completely off [EDITED]:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="no" indent="yes" method="xml"/>
<xsl:key name = "erpordermatch" match = "Shipment" use = "@ErpOrder"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Shipment[not(Containers)]">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
<xsl:for-each select="key('erpordermatch', @ErpOrder)">
<xsl:if test="@ErpOrder = ErpOrder">
<xsl:copy-of select="Containers"/>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
See if this works for you:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="ship-by-erp" match="Shipment" use="ErpOrder" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Shipment[not(Containers)]">
<xsl:copy>
<xsl:apply-templates/>
<xsl:copy-of select="key('ship-by-erp', ErpOrder)/Containers"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note that this results in the first Shipment
being duplicated in the output (as shown also in your expected output). Are you sure you want this?
Answered by michael.hor257k on January 9, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP