Mike
Mike

Reputation: 35

Required Transformation xslt code

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

Answers (2)

michael.hor257k
michael.hor257k

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

Martin Honnen
Martin Honnen

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

Related Questions