2011-07-16 10 views
5

He XML siguiente:XSLT de ordenación condicional

<Users> 
    <User Id="1"> 
    <Name>abc</Name> 
    <LastName>d</LastName> 
    </User> 
    <User Id="2"> 
    <Name></Name> 
    <LastName>ab</LastName> 
    </User> 
    <User Id="3"> 
    <Name>a</Name> 
    <LastName>efg</LastName> 
    </User> 
</Users> 

Ahora ordenar los usuarios que usan siguiente plantilla:

<xsl:template match="Users"> 
    <Users> 
    <xsl:for-each select="User"> 
     <xsl:sort select="Name"/> 
     <xsl:sort select="LastName"/> 

     <User> 
     <xsl:attribute name="Id"> 
      <xsl:value-of select="attribute::Id"/> 
     </xsl:attribute> 
     <Name> 
      <xsl:value-of select="Name"/> 
     </Name> 
     <LastName> 
      <xsl:value-of select="LastName"/> 
     </LastName> 
     </User> 
    </xsl:for-each> 
    </Users> 
</xsl:template> 

pero necesito clasificar, satisface wich siguiente condición: Ordenar por nombre. Si Nombre está vacío o nulo, necesito ordenar por Apellido. Por lo tanto, en XML producido necesito el siguiente orden: Usuario3, Usuario2, Usuario1.

Cualquier ayuda es apreciada.

PS: Yo uso ASP.NET 3.5

+0

+1 para una buena pregunta. –

Respuesta

3

me gustaría utilizar primero la transformación de identidad, y luego aplicar la clasificación a la unión de los elementos (con exclusión de aquellos cuya Name está vacío)

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

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Users"> 
     <xsl:copy> 
      <xsl:apply-templates select="User"> 
       <xsl:sort select="Name[.!='']|LastName"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

cuando se aplica en la entrada se muestra en la cuestión, se obtiene:

<Users> 
    <User Id="3"> 
     <Name>a</Name> 
     <LastName>efg</LastName> 
    </User> 
    <User Id="2"> 
     <Name/> 
     <LastName>ab</LastName> 
    </User> 
    <User Id="1"> 
     <Name>abc</Name> 
     <LastName>d</LastName> 
    </User> 
</Users> 
+0

+1, me dejaste atrás :-) –

+0

+1, ¡muchas gracias! –

+0

De nada. –

1

se puede seleccionar el Name y LastName elementos con filtros de predicados que usan normalize-space() para filtrar los vacíos, use el operador de unión | para combinarlos y agruparlos con la perenthesis (lo que crearía una secuencia en XSLT/XPath 2.0). Luego, seleccione el primero en la agrupación para usar para el género.

Además, en lugar de volver a construir el elemento <Users>, puede usar <xsl:copy-of>.

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes" /> 

<xsl:template match="Users"> 
    <Users> 
    <xsl:for-each select="User"> 
     <xsl:sort select="(Name[normalize-space()]|LastName[normalize-space()])[1]"/> 
     <xsl:copy-of select="."/> 
    </xsl:for-each> 
    </Users> 
</xsl:template> 

</xsl:stylesheet>