2011-07-16 13 views
5

Mam następujące XML:XSLT warunkowy sortowania

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

Teraz sortować użytkowników przy użyciu następującej formy:

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

ale muszę sortowania, wich spełnia następujący warunek: Sortuj według nazw. Jeśli Nazwa jest pusta lub zerowa, muszę sortować według Nazwisko. Tak więc w produkowanym formacie XML potrzebuję następującej kolejności: User3, User2, User1.

Każda pomoc jest doceniana.

PS: Używam ASP.NET 3.5

+0

+1 za dobre pytanie. –

Odpowiedz

3

użyłbym pierwszą przemianę tożsamości, a następnie zastosować do sortowania unii elementów (z wyłączeniem tych, których Name jest pusty)

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

po nałożeniu na wejściu przedstawionej w pytaniu, otrzymujemy:

<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, zostawiłeś mnie :-) –

+0

+1, Wielkie dzięki! –

+0

Nie ma za co. –

1

można wybrać Name i LastName elementów z filtrami predykatów, które używają normalize-space() do odfiltrowania pustych, użyj operatora unitu |, aby połączyć je i pogrupować je z perenthesis (co stworzy sekwencję w XSLT/XPath 2.0). Następnie wybierz pierwszy w grupie, którego chcesz użyć do sortowania.

Ponadto, zamiast ponownie budować element <Users>, można po prostu użyć <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>