Reputation: 17
I have the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<Orders>
<Order Weight="1.00">
<Items>
<Item ItemLength="5.00" ItemQty="1">
<ItemCharge Description="Chair" Amount="5.50"></ItemCharge>
</Item>
</Items>
</Order>
<Order Weight="2.50">
<Items>
<Item Length="5.00" ItemQty="1">
<ItemCharge Description="Chair" Amount="8.50"></ItemCharge>
</Item>
</Items>
</Order>
</Orders>
I need the attributes and values in the "Order" element (e.g. Weight="1.00") moved to the "Item" element. The number of "Order" elements and the value in the "Weight" attribute will vary from time to time. The desired result should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<Orders>
<Order>
<Items>
<Item ItemLength="5.00" ItemQty="1" Weight="1.00">
<ItemCharge Description="Chair" Amount="5.50"></ItemCharge>
</Item>
</Items>
</Order>
<Order>
<Items>
<Item Length="5.00" ItemQty="1" Weight="2.50">
<ItemCharge Description="Chair" Amount="8.50"></ItemCharge>
</Item>
</Items>
</Order>
</Orders>
I currently have this XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*[not(name() = 'Weight')] | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I greatly appreciate your help!!!
Upvotes: 0
Views: 1192
Reputation: 70648
You need to think of this as two separate changes, rather than a single "move"
1) Remove the Weight
attribute for the Order
element. Or rather, do not copy the Weight
attribute to the output
<xsl:template match="@Weight" />
2) Add a Weight
attribute to the Item
element when copying it to the output
<xsl:template match="Item">
<Item Weight="{../../@Weight}">
<xsl:apply-templates select="@* | node()"/>
</Item>
</xsl:template>
Note the use of "Attribute Value Templates" in creating the new attribute.
Also note you should avoid changing the identity template in such transformations. The two templates above, because they use specific names, get a higher priority than the identity template.
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@Weight" />
<xsl:template match="Item">
<Item Weight="{../../@Weight}">
<xsl:apply-templates select="@* | node()"/>
</Item>
</xsl:template>
</xsl:stylesheet>
Upvotes: 3