Reputation: 23
I tried using XSL with "for-each" I need to group the value based on CATEGORY and TYPE.
Any help?
Input RAW xml:
<?xml version = '1.0' encoding = 'UTF-8'?>
<ROWSET>
<ROW>
<ID>12345</ID>
<TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>1</VALUE>
<LABEL>ISO1</LABEL>
</ROW>
<ROW>
<ID>12345</ID>
<TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>2</VALUE>
<LABEL>ISO2</LABEL>
</ROW>
<ROW>
<ID>12345</ID>
<TYPE>TYP1</TYPE>
<SUBTYPE>SUBTYP2</SUBTYP>
<CATEGORY>A1</CATEGORY>
<VALUE>3</VALUE>
<LABEL>ISO3</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>1</VALUE>
<LABEL>ISO1</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>1</VALUE>
<LABEL>ISO1</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>2</VALUE>
<LABEL>ISO2</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP2</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>3</VALUE>
<LABEL>ISO3</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP2</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>2</VALUE>
<LABEL>ISO2</LABEL>
</ROW>
<ROW>
<ID>67890</ID>
<TYPE>TYP2</TYPE>
<CATEGORY>A1</CATEGORY>
<VALUE>3</VALUE>
<LABEL>ISO1</LABEL>
</ROW>
</ROWSET>
Expected Result: I need to group the values based on Category and TYPE (see below)
<?xml version = '1.0' encoding = 'UTF-8'?>
<ROWSET>
<ROW>
<ID>12345</ID>
<TYPE>TYP1</TYPE>
<CATEGORY>A1</CATEGORY>
<GRP1>
<VALUE>1</VALUE>
<LABEL>ISO1</LABEL>
<VALUE>2</VALUE>
<LABEL>ISO2</LABEL>
<VALUE>3</VALUE>
<LABEL>ISO3</LABEL>
</GRP1>
</ROW>
<ROW>
<ID>67890</ID>
<TYP>
<TYPE>TYP1</TYPE>
<TYPE>TYP2</TYPE>
</TYP>
<CATEGORY>A1</CATEGORY>
<GRP1>
<VALUE>1</VALUE>
<LABEL>ISO1</LABEL>
<VALUE>2</VALUE>
<LABEL>ISO2</LABEL>
<VALUE>3</VALUE>
<LABEL>ISO3</LABEL>
</GRP1>
XSL used: It needs some corrections. (Thanks to @Parfait for the code)
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="categkey" match="ROW" use="CATEGORY" />
<xsl:template match="ROWSET">
<xsl:copy>
<xsl:for-each select="ROW[generate-id()= generate-id(key('categkey', CATEGORY)[1])]">
<xsl:copy>
<xsl:copy-of select="ID"/>
<xsl:copy-of select="TYPE"/>
<xsl:copy-of select="CATEGORY"/>
<GRP1>
<xsl:for-each select="key('categkey', CATEGORY)">
<xsl:copy-of select="VALUE"/>
<xsl:copy-of select="LABEL"/>
</xsl:for-each>
</GRP1>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:transform>
Thanks! Carthyc
Upvotes: 2
Views: 213
Reputation: 107687
For grouping in XSLT 1.0, consider the Muenchian Method which indexes the document according to a key and can run various operations with that key:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="categkey" match="ROW" use="CATEGORY" />
<xsl:template match="ROWSET">
<xsl:copy>
<xsl:for-each select="ROW[generate-id()= generate-id(key('categkey', CATEGORY)[1])]">
<xsl:copy>
<xsl:copy-of select="ID"/>
<xsl:copy-of select="TYPE"/>
<xsl:copy-of select="CATEGORY"/>
<GRP1>
<xsl:for-each select="key('categkey', CATEGORY)">
<xsl:copy-of select="VALUE"/>
<xsl:copy-of select="LABEL"/>
</xsl:for-each>
</GRP1>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:transform>
UPDATE
Borrowing from @Tim C's previous answer (the XSLT guru who first edited your post), for multiple keys such as on ID
and its siblings, consider the below:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="idkey" match="ROW" use="ID" />
<xsl:key name="typekey" match="ROW" use="concat(ID, TYPE)"/>
<xsl:key name="categkey" match="ROW" use="concat(ID, CATEGORY)" />
<xsl:key name="valuekey" match="ROW" use="concat(ID, VALUE)" />
<xsl:key name="labelkey" match="ROW" use="concat(ID, LABEL)" />
<xsl:template match="ROWSET">
<xsl:copy>
<xsl:for-each select="ROW[generate-id()= generate-id(key('idkey', ID)[1])]">
<xsl:copy>
<xsl:copy-of select="ID"/>
<TYP>
<xsl:for-each select="key('idkey', ID)[generate-id()= generate-id(key('typekey', concat(ID, TYPE))[1])]">
<xsl:copy-of select="TYPE"/>
</xsl:for-each>
</TYP>
<xsl:copy-of select="CATEGORY"/>
<GRP1>
<xsl:for-each select="key('idkey', ID)[generate-id()= generate-id(key('valuekey', concat(ID, VALUE))[1])]">
<xsl:copy-of select="VALUE"/>
<xsl:copy-of select="LABEL"/>
</xsl:for-each>
</GRP1>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:transform>
Upvotes: 1