2010-01-27 42 views
30

Necesito agrupar el valor basado en algún atributo y rellenarlo.cómo aplicar agrupar por elementos xslt

mencionado a continuación es i/p XML y si ves que hay 4 filas para los usuarios y para la Identificación del 2,4 División es decir, HR misma

mientras que la generación real de O/P necesito para agrupar por División .. . Alguna ayuda ???

I/P XML

<Users> 
<User id="2" name="ABC" Division="HR"/> 
<User id="3" name="xyz" Division="Admin"/> 
<User id="4" name="LMN" Division="Payroll"/> 
<User id="5" name="PQR" Division="HR"/> 
</Users> 

Resultado esperado: necesito para agrupar los valores basados ​​en la división y poblar es decir, el uso

<AllUsers> 
<Division value="HR"> 
    <User> 
    <id>2</id> 
    <name>ABC</name> 
    </User> 
    <User> 
    <id>5</id> 
    <name>PQR</name> 
    </User> 
</Division> 
<Division value="ADMIN"> 
    <User> 
    <id>3</id> 
    <name>XYZ</name> 
    </User> 
</Division> 
<Division value="Payroll"> 
    <User> 
    <id>4</id> 
    <name>LMN</name> 
    </User> 
</Division> 
</AllUsers> 

Respuesta

74

En XSLT 1.0, utilizando la agrupación Muenchian.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" indent="yes" /> 

    <xsl:key name="division" match="User" use="@Division" /> 

    <xsl:template match="Users"> 
     <AllUsers> 
      <xsl:apply-templates select="User[generate-id(.)=generate-id(key('division',@Division)[1])]"/> 
     </AllUsers> 
    </xsl:template> 

    <xsl:template match="User"> 
     <Division value="{@Division}"> 
      <xsl:for-each select="key('division', @Division)"> 
       <User> 
        <id><xsl:value-of select="@id" /></id> 
        <name><xsl:value-of select="@name" /></name> 
       </User> 
      </xsl:for-each> 
     </Division> 
    </xsl:template> 

</xsl:stylesheet> 

En XSLT 2.0, el uso XSL: foreach grupo

<xsl:output method="xml" indent="yes" /> 

<xsl:template match="Users"> 
    <AllUsers> 
     <xsl:for-each-group select="User" group-by="@Division"> 
      <Division value="{@Division}"> 
       <xsl:for-each select="current-group()"> 
        <User> 
         <id><xsl:value-of select="@id" /></id> 
         <name><xsl:value-of select="@name" /></name> 
        </User> 
       </xsl:for-each> 
      </Division> 
     </xsl:for-each-group> 
    </AllUsers> 
</xsl:template> 

+0

+1, éste sólo me salvó de dolor de cabeza :) – Damb

+0

le daría a este 10 si pudiera, gran ejemplo :-) – raffian

+1

En el ejemplo XSLT 2.0, ¿cuál es el propósito de si no está utilizando la función de tecla()? – Paul

0

no prefiero la adición de elementos como eso y esto es lo que haré. Esto funciona perfectamente Le da la salida que necesita. Pruébalo.

XML

<?xml version="1.0"?> 
<Users> 
<User id="2" name="ABC" Division="HR"/> 
<User id="3" name="xyz" Division="Admin"/> 
<User id="4" name="LMN" Division="Payroll"/> 
<User id="5" name="PQR" Division="HR"/> 
</Users> 

XSLT 1,0

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" indent="yes" /> 
    <xsl:key name="division" match="User" use="@Division" /> 
    <xsl:template match="Users"> 
     <xsl:element name="AllUsers"> 
     <xsl:apply-templates select="User[generate-id(.)=generate-id(key('division',@Division)[1])]" /> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="User"> 
     <xsl:element name="Division"> 
     <xsl:attribute name="value"> 
      <xsl:value-of select="@Division" /> 
     </xsl:attribute> 
     <xsl:for-each select="key('division', @Division)"> 
      <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:template> 
</xsl:stylesheet> 

XSLT 2,0

<?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> 

Utilizando cualquiera se lo regalo salida,

<AllUsers> 
    <Division value="HR"> 
     <User> 
     <id>2</id> 
     <name>ABC</name> 
     </User> 
     <User> 
     <id>5</id> 
     <name>PQR</name> 
     </User> 
    </Division> 
    <Division value="Admin"> 
     <User> 
     <id>3</id> 
     <name>xyz</name> 
     </User> 
    </Division> 
    <Division value="Payroll"> 
     <User> 
     <id>4</id> 
     <name>LMN</name> 
     </User> 
    </Division> 
</AllUsers>