This is my XML-
<?xml version="1.0" encoding="UTF-8"?>
<update-all-attributes>
<document name="http://blah">
<price>111 USD</price>
<color>red</color>
<size>comfort</size>
<cost>00012-40</cost>
<shipping>US::Ground:0.00</shipping>
<cost>00012-40</cost>
<price>111 USD</price>
<color>red</color>
<size>comfort</size>
<cost>00012-40</cost>
<shipping>US::Ground:0.00</shipping>
<cost>00012-40</cost>
<price>111 USD</price>
<color>red</color>
<size>comfort</size>
<shipping>US::Ground:0.00</shipping>
<price>111 USD</price>
<color>red</color>
<size>comfort</size>
</document>
<document name="http://blahblah">
<price>110 USD</price>
<color>blue</color>
<size>super</size>
<cost>00012-41</cost>
<shipping>US::Ground:0.01</shipping>
<cost>00012-41</cost>
<price>110 USD</price>
<color>blue</color>
<size>super</size>
<shipping>US::Ground:0.01</shipping>
<cost>00012-41</cost>
<price>110 USD</price>
<color>blue</color>
<size>super</size>
<shipping>US::Ground:0.01</shipping>
<price>110 USD</price>
<color>blue</color>
<size>super</size>
</document>
</update-all-attributes>
I want my final XML as
<?xml version="1.0" encoding="UTF-8"?>
<document name="http://blah">
<price>111 USD</price>
<color>red</color>
<size>comfort</size>
<cost>00012-40,00012-40,00012-40,00012-40</cost>
<shipping>US::Ground:0.00,US::Ground:0.00,US::Ground:0.00</shipping>
</document>
<document name="http://blahblah">
<price>110 USD</price>
<color>blue</color>
<size>super</size>
<cost>00012-41,00012-41,00012-41,00012-41</cost>
<shipping>US::Ground:0.01,US::Ground:0.01,US::Ground:0.01</shipping>
</document>
This is the XSLT used (thanks to Thomas W)-
<?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" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="element-by-name" match="document/*" use="local-name()"/>
<!-- Copy everything, unless other templates say otherwise -->
<xsl:template match="*|@*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<!-- Skip elements if there are elements of the same name earlier in the document.
Priority is set to 1 so that this template overrides other templates
and we don't accidentally still get duplicates. -->
<xsl:template match="*[count(. | key('element-by-name', local-name())[1]) > 1]" priority="1"/>
<!-- This template is for elements we want to be multi-value -->
<xsl:template match="shipping | cost">
<xsl:copy>
<!-- We step through all elements of the same name -->
<xsl:for-each select="key('element-by-name', local-name())">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">,</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This is working fine for just one document element, I have multiple document element so how can this work for all the document elements?
You can do this by changing the key so that it uses both the name of the element and the unique id of its
document
parent for the lookup value.Output (the root element is the same as in the input XML; the output that you asked for in the question has no root element):