I need to transform below input XML to output XML. Can you please provide any ideas for this.
I need to transform below input XML to output XML. Can you please provide any ideas for this.
Input XML :
<GenericCollection ParamValue="ParamValue1" xmlns="http://www.example.org">
<Generic>
<store>Store1</store>
<metricName>Metric1</metricName>
<metricValue>1</metricValue>
</Generic>
<Generic>
<store>Store1</store>
<metricName>Metric2</metricName>
<metricValue>1</metricValue>
</Generic>
<Generic>
<store>Store2</store>
<metricName>Metric1</metricName>
<metricValue>1</metricValue>
</Generic>
<Generic>
<store>Store2</store>
<metricName>Metric1</metricName>
<metricValue>2</metricValue>
</Generic>
<Generic>
<store>Store2</store>
<metricName>Metric2</metricName>
<metricValue>1</metricValue>
</Generic>
<Generic>
<store>Store3</store>
<metricName>Metric1</metricName>
<metricValue>1</metricValue>
</Generic>
<Generic>
<store>Store3</store>
<metricName>Metric1</metricName>
<metricValue>2</metricValue>
</Generic>
</GenericCollection>
output:
<?xml version = '1.0' encoding = 'UTF-8'?>
<ns4:EnterpriseDocument>
<ns4:DataSet>
<ns4:Dimension ref_name="bu_code" value="Store1">
<ns4:Metric ref_name="Metric1">
<ns4:Data value="1"/>
</ns4:Metric>
<ns4:Metric ref_name="Metric2">
<ns4:Data value="1"/>
</ns4:Metric>
</ns4:Dimension>
<ns4:Dimension ref_name="bu_code" value="Store2">
<ns4:Metric ref_name="Metric1">
<ns4:Data value="1"/>
<ns4:Data value="2"/>
</ns4:Metric>
<ns4:Metric ref_name="Metric2">
<ns4:Data value="1"/>
</ns4:Metric>
</ns4:Dimension>
<ns4:Dimension ref_name="bu_code" value="Store3">
<ns4:Metric ref_name="Metric1">
<ns4:Data value="1"/>
<ns4:Data value="2"/>
</ns4:Metric>
</ns4:Dimension>
</ns4:DataSet>
</ns4:EnterpriseDocument>
Thanks,
Ramesh
If you are able to use XSLT 2.0, then you should probably be using xsl:for-each-group here, rather than xsl:for-each because you are trying to group the elements here.
Firstly you are grouping by Generic elements by their store value, so you would write this.
<xsl:for-each-group select="Generic" group-by="store">
Then within this, you would output the *Dimension * element for the group like so:
<Dimension ref_name="bu_code" value="{current-grouping-key()}">
Next, you want to further group the elements in this group by their metricName value
<xsl:for-each-group select="current-group()" group-by="metricName">
Note the use of current-group() here. You are only iterating over the elements in the current "store" group, and not over all generic elements.
Finally, to output all your Data elements, you would do this
<xsl:for-each select="current-group()">
Try the following XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://www.example.org">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/*">
<EnterpriseDocument>
<DataSet>
<xsl:for-each-group select="Generic" group-by="store">
<Dimension ref_name="bu_code" value="{current-grouping-key()}">
<xsl:for-each-group select="current-group()" group-by="metricName">
<Metric ref_name="{current-grouping-key()}">
<xsl:for-each select="current-group()">
<Data value="{metricValue}"/>
</xsl:for-each>
</Metric>
</xsl:for-each-group>
</Dimension>
</xsl:for-each-group>
</DataSet>
</EnterpriseDocument>
</xsl:template>
</xsl:stylesheet>
When run on your XML sample, the following is output (Note, in my sample I am not including any namespaces, just for clarity)
<EnterpriseDocument>
<DataSet>
<Dimension ref_name="bu_code" value="Store1">
<Metric ref_name="Metric1">
<Data value="1"/>
</Metric>
<Metric ref_name="Metric2">
<Data value="1"/>
</Metric>
</Dimension>
<Dimension ref_name="bu_code" value="Store2">
<Metric ref_name="Metric1">
<Data value="1"/>
<Data value="2"/>
</Metric>
<Metric ref_name="Metric2">
<Data value="1"/>
</Metric>
</Dimension>
<Dimension ref_name="bu_code" value="Store3">
<Metric ref_name="Metric1">
<Data value="1"/>
<Data value="2"/>
</Metric>
</Dimension>
</DataSet>
</EnterpriseDocument>