I'm trying to produce an XML from the original one that will be grouping the same Item/@Id
while skipping the child duplicates within item
Source XML:
<products>
<item id="1">
<content desc="laptop"/>
<content desc="charger"/>
</item>
<item id="1">
<content desc="laptop"/>
<content desc="charger"/>
<content desc="mouse"/>
</item>
<item id="2">
<content desc="laptop"/>
<content desc="charger"/>
</item>
</products>
I've been checking several posts with similar question, but I'm stuck with below XSLT 1.0 code I'm trying my own:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="itemKey" match="item" use="@id"/>
<xsl:template match="products">
<output>
<xsl:for-each select="item[generate-id() = generate-id(key('itemKey', @id)[1])]">
<product>
<id>
<xsl:value-of select="@id"/>
</id>
<content>
<xsl:for-each select="content">
<desc>
<xsl:value-of select="@desc"/>
</desc>
</xsl:for-each>
</content>
</product>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
From the source XML, there are in total 2 item ids (1 and 2) and the group with item id="1"
has laptop
and charger
repeated in both, so those should appear only once, and mouse
will complete that group. The expected output is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<product>
<id>1</id>
<detail>
<item>laptop</item>
<item>charger</item>
<item>mouse</item>
</detail>
</product>
<product>
<id>2</id>
<detail>
<item>laptop</item>
<item>charger</item>
</detail>
</product>
</output>
I was reading that I probably have to first do a group by item/@id
and then for each group do another group by content/@desc
but not sure how to accomplish that. Can you please let me know what changes do I need to do to in my XSLT in order to achieve the expected result? Solution is expected in XSLT 1.0, but I'd also consider XSLT 2.0.
Using XSLT 2.0 again I'm not sure how to capture the unique content
for each group
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<output>
<xsl:for-each-group select="item" group-by="@id">
<product>
<id>
<xsl:value-of select="@id"/>
</id>
<content>
</content>
</product>
</xsl:for-each-group>
</output>
</xsl:template>
</xsl:stylesheet>