2

I'm using XSLT 2.0 to do this i also came across a similar question but the answers given are not working properly. Similar One

XML

<Users>
 <User id="1" name="TYE" Division="Admin"/> 
 <User id="2" name="ANN" Division="HR"/> 
 <User id="3" name="LAR" Division="Marketing"/> 
 <User id="4" name="JSN" Division="Admin"/> 
</Users>

Need an ouput like this;

<AllUsers>
 <Division value="HR">
  <User> 
   <id>2</id>
   <name>TYE</name>
  </User> 
  <User> 
   <id>5</id>
   <name>JSN</name>
  </User>
 </Division>
 <Division value="ADMIN">
  <User> 
   <id>3</id>
   <name>ANN</name>
  </User> 
 </Division>
 <Division value="Marketing">
  <User> 
   <id>4</id>
   <name>LAR</name>
  </User> 
 </Division>
</AllUsers>

Need to group by division.. Thanks.

Community
  • 1
  • 1
  • Please, when you post a question, tell us what you did and tell us how it failed. If we know where you went wrong, then we can explain it and help you to avoid making the same mistakes again. – Michael Kay Nov 04 '13 at 09:13
  • i tried an answer in other question it didnt work..It was because `` was incorrect..now its working. –  Nov 05 '13 at 08:36

2 Answers2

2

Here's another option that is more of a push style...

XML Input

<Users>
 <User id="1" name="TYE" Division="Admin"/> 
 <User id="2" name="ANN" Division="HR"/> 
 <User id="3" name="LAR" Division="Marketing"/> 
 <User id="4" name="JSN" Division="Admin"/> 
</Users>

XSLT 2.0

<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="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/*">
        <AllUsers>
            <xsl:for-each-group select="User" group-by="@Division">
                <Division value="{current-grouping-key()}">
                    <xsl:apply-templates select="current-group()"/>
                </Division>
            </xsl:for-each-group>
        </AllUsers>
    </xsl:template>

    <xsl:template match="User/@*">
        <xsl:element name="{name()}">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="@Division" priority="1"/>

</xsl:stylesheet>

Output

<AllUsers>
   <Division value="Admin">
      <User>
         <id>1</id>
         <name>TYE</name>
      </User>
      <User>
         <id>4</id>
         <name>JSN</name>
      </User>
   </Division>
   <Division value="HR">
      <User>
         <id>2</id>
         <name>ANN</name>
      </User>
   </Division>
   <Division value="Marketing">
      <User>
         <id>3</id>
         <name>LAR</name>
      </User>
   </Division>
</AllUsers>
Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
1

This is what i would do,

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="yes" />
   <xsl:key name="division" match="User" use="@Division" />
   <xsl:template match="Users">
      <xsl:element name="AllUsers">
         <xsl:for-each-group select="*" group-by="@Division">
            <xsl:element name="Division">
               <xsl:attribute name="value">
                  <xsl:value-of select="@Division" />
               </xsl:attribute>
               <xsl:for-each select="current-group()">
                  <xsl:element name="User">
                     <xsl:element name="id">
                        <xsl:value-of select="@id" />
                     </xsl:element>
                     <xsl:element name="name">
                        <xsl:value-of select="@name" />
                     </xsl:element>
                  </xsl:element>
               </xsl:for-each>
            </xsl:element>
         </xsl:for-each-group>
      </xsl:element>
   </xsl:template>
</xsl:stylesheet>

Let me know if this works? It should as i know.

Hash
  • 7,726
  • 9
  • 34
  • 53