Reputation: 35
I have below input
<?xml version="1.0" encoding="UTF-8"?>
<Input>
<Userlist>
<name>ABC</name>
<division>1</division>
<method>online</method>
<subject>M</subject>
<fee>10k</fee>
</Userlist>
<Userlist>
<name>BCD</name>
<division>2</division>
<method>Distance</method>
<fee>5k</fee>
<subject>C</subject>
</Userlist>
<Userlist>
<name>CDF</name>
<division>2</division>
<method>Direct</method>
<fee>15k</fee>
<subject>P</subject>
</Userlist>
<Userlist>
<name>FGH</name>
<division>55</division>
<method>Direct</method>
<fee>25k</fee>
<subject>E</subject>
</Userlist>
<Userlist>
<name>HKM</name>
<division>55</division>
<method>Direct</method>
<fee>40k</fee>
<subject>H</subject>
</Userlist>
</Input>
And Below is Expected Output: Requirement is, Based on Method values (Those are Predefined values) loop thru them, if more than occurence comes we need to put relative values under Filters. Inside filters if we have same divisions also comes under one details element like below. I cannot able to even put code because it is giving no where closer. Thanks for your help advance.
<?xml version="1.0" encoding="UTF-8"?>
<Output>
<AllUserslist>
<User>
<Methodtype>online</Methodtype>
<Filters>
<Filter>
<Section>1</Section>
<Details>
<Detail>
<Studentname>ABC</Studentname>
<Fee>10k</Fee>
<subject>M</subject>
</Detail>
</Details>
</Filter>
</Filters>
</User>
<User>
<Methodtype>Distance</Methodtype>
<Filters>
<Filter>
<Section>2</Section>
<Details>
<Detail>
<Studentname>BCD</Studentname>
<Fee>5k</Fee>
<subject>C</subject>
</Detail>
</Details>
</Filter>
</Filters>
</User>
<User>
<Methodtype>Direct</Methodtype>
<Filters>
<Filter>
<Section>2</Section>
<Details>
<Detail>
<Studentname>CDF</Studentname>
<Fee>15K</Fee>
<subject>P</subject>
</Detail>
</Details>
</Filter>
<Filter>
<Section>55</Section>
<Details>
<Detail>
<Studentname>FGH</Studentname>
<Fee>25K</Fee>
<subject>E</subject>
</Detail>
<Detail>
<Studentname>HKM</Studentname>
<Fee>40K</Fee>
<subject>H</subject>
</Detail>
</Details>
</Filter>
</Filters>
</User>
</AllUserslist>
</Output>
Upvotes: 0
Views: 97
Reputation: 117003
Try it this way?
XSLT 1.0
<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:key name="group-method" match="Userlist" use="method" />
<xsl:key name="group-division" match="Userlist" use="concat(method, '|', division)" />
<xsl:template match="/Input">
<Output>
<AllUserslist>
<xsl:for-each select="Userlist[generate-id() = generate-id(key('group-method', method)[1])]">
<User>
<Methodtype><xsl:value-of select="method"/></Methodtype>
<Filters>
<xsl:for-each select="key('group-method', method)[generate-id() = generate-id(key('group-division', concat(method, '|', division))[1])]">
<Filter>
<Section><xsl:value-of select="current()/division"/></Section>
<Details>
<xsl:for-each select="key('group-division', concat(method, '|', division))">
<Detail>
<Studentname><xsl:value-of select="name"/></Studentname>
<Fee><xsl:value-of select="fee"/></Fee>
<subject><xsl:value-of select="subject"/></subject>
</Detail>
</xsl:for-each>
</Details>
</Filter>
</xsl:for-each>
</Filters>
</User>
</xsl:for-each>
</AllUserslist>
</Output>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 167571
Assuming you can use XSLT 2.0 you can solve it using two nested for-each-group group-by
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"></xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="Input">
<Output>
<AllUserslist>
<xsl:for-each-group select="Userlist" group-by="method">
<User>
<Methodtype>
<xsl:value-of select="current-grouping-key()"/>
</Methodtype>
<Filters>
<xsl:for-each-group select="current-group()" group-by="division">
<Filter>
<Section>
<xsl:value-of select="current-grouping-key()"/>
</Section>
<Details>
<xsl:apply-templates select="current-group()"/>
</Details>
</Filter>
</xsl:for-each-group>
</Filters>
</User>
</xsl:for-each-group>
</AllUserslist>
</Output>
</xsl:template>
<xsl:template match="Userlist">
<Detail>
<xsl:apply-templates select="* except (method, division)"/>
</Detail>
</xsl:template>
<xsl:template match="name">
<Studentname>
<xsl:value-of select="."/>
</Studentname>
</xsl:template>
<xsl:template match="fee">
<Fee>
<xsl:value-of select="."/>
</Fee>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0