2009-08-17 3 views
3

Ist es in XSLT möglich, in alphabetischer Reihenfolge mit 5 Elementen als "bevorzugt" zu sortieren.XSLT Custom Sort

heißt

gegeben
<teams> 
<team id="142" name="Scotland" /> 
<team id="110" name="Liverpool" /> 
<team id="13" name="Manchester United" /> 
<team id="123" name="England" /> 
<team id="84" name="Chelsea" /> 
<team id="295" name="Wales" /> 
<team id="49" name="Arsenal" /> 
<team id="126" name="Northern Ireland" /> 
<team id="121" name="Republic of Ireland" /> 
<team id="42" name="Manchester City" /> 
<team id="298" name="Tottenham Hotspur" /> 
<team id="299" name="Bolton" /> 
</teams> 

Ich benötige die Nationalmannschaften in alphabetischer Reihenfolge nach dem Rest ersten in einer bestimmten Reihenfolge, gefolgt sortiert werden:

<teams> 
<team id="123" name="England" /> 
<team id="126" name="Northern Ireland" /> 
<team id="121" name="Republic of Ireland" /> 
<team id="142" name="Scotland" /> 
<team id="295" name="Wales" /> 
<team id="49" name="Arsenal" /> 
<team id="299" name="Bolton" /> 
<team id="84" name="Chelsea" /> 
<team id="110" name="Liverpool" /> 
<team id="42" name="Manchester City" /> 
<team id="13" name="Manchester United" /> 
<team id="298" name="Tottenham Hotspur" /> 
</teams> 

Ich habe versucht, aber scheitern.

Gibt es einen guten Weg, oder müssen Sie die Nationalmannschaften einzeln sortieren, gefolgt von einer Art, die alle Nationalmannschaften ausschließt?

Antwort

5

Sie können dies tun:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:my="http://tempuri.org" 
    exclude-result-prefixes="my" 
> 

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

    <my:data> 
    <my:nationalteams> 
     <my:team id="121" /><!-- Republic of Ireland --> 
     <my:team id="123" /><!-- England --> 
     <my:team id="126" /><!-- Northern Ireland --> 
     <my:team id="142" /><!-- Scotland --> 
     <my:team id="295" /><!-- Wales --> 
    </my:nationalteams> 
    </my:data> 

    <xsl:template match="teams"> 
    <xsl:copy> 
     <xsl:variable name="national" select=" 
     document('')/*/my:data/my:nationalteams/my:team 
     " /> 
     <!-- national teams preferred --> 
     <xsl:apply-templates select="team[@id = $national/@id]"> 
     <xsl:sort select="@name" /> 
     </xsl:apply-templates> 
     <!-- other teams after them --> 
     <xsl:apply-templates select="team[not(@id = $national/@id)]"> 
     <xsl:sort select="@name" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="team"> 
    <xsl:copy-of select="." /> 
    </xsl:template> 

</xsl:stylesheet> 

Die ganzen <my:data> auf eine sekundäre XML/config-Datei verschoben werden könnte, wo man auch die „my“ Namespace weglassen kann.

Danach würde eine Zeile eine kleine Änderung:

<xsl:variable name="national" select=" 
    document('config.xml')/data/nationalteams/team 
" /> 

Der Ausgang des oben ist etwas überraschend :-)

<teams> 
    <team id="123" name="England" /> 
    <team id="126" name="Northern Ireland" /> 
    <team id="121" name="Republic of Ireland" /> 
    <team id="142" name="Scotland" /> 
    <team id="295" name="Wales" /> 
    <team id="49" name="Arsenal" /> 
    <team id="299" name="Bolton" /> 
    <team id="84" name="Chelsea" /> 
    <team id="110" name="Liverpool" /> 
    <team id="42" name="Manchester City" /> 
    <team id="13" name="Manchester United" /> 
    <team id="298" name="Tottenham Hotspur" /> 
</teams> 
1

Haben Sie xsl gesehen: Sortierelement, können Sie zwei oder mehr Sortierkriterien erstellen, indem Sie xsl Kombination: apply-templates und xsl: sort

Indeeed, hier ist ein Beispiel, wo einige Länder an erster Stelle steht, in einem vordefinierten bestellen, dann alle anderen. Beachten Sie, dass dies Elemente sind, keine Attribute wie oben.

<xsl:sort select="not(CountryValue = 'Scotland')"/> 
<xsl:sort select="not(CountryValue = 'India')"/> 
<xsl:sort select="CountryValue"/> 

Beispieler:

Land

Scotland 
Scotland 
Scotland 
India 
Afghanistan 
Afghanistan 
Afghanistan 
Afghanistan 
Afghanistan 
Afghanistan 
Albania 
Albania 
Albania 
Algeria 
1

In Ihrem XSLT, sind Sie in der Lage Verwendung von Erweiterungsfunktionen zu machen?

Wenn dies der Fall ist, besteht eine Methode darin, die vorhandene Liste der Knoten inline zu ändern, um einen neuen Knotensatz mit einem zusätzlichen Attribut 'sortname' auf jedem Knoten zu erstellen. Sie können dann über diesen neuen Knotensatz durchlaufen, das Sortieren des neuen ‚sortname‘ Attribut:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="urn:schemas-microsoft-com:xslt"> 
    <xsl:output method="xml" /> 
    <xsl:template match="/teams"> 
     <xsl:variable name="extendedteams"> 
     <xsl:for-each select="team"> 
      <xsl:copy> 
       <xsl:copy-of select="@*" /> 
       <xsl:attribute name="sortname"> 
        <xsl:choose> 
         <xsl:when test="@name='England' or @name='Northern Ireland' or @name='Republic of Ireland' or @name='Scotland' or @name='Wales'">1</xsl:when> 
         <xsl:otherwise>2</xsl:otherwise> 
        </xsl:choose> 
        <xsl:value-of select="@name" /> 
       </xsl:attribute> 
      </xsl:copy> 
     </xsl:for-each> 
     </xsl:variable> 
     <xsl:copy> 
     <xsl:for-each select="exsl:node-set($extendedteams)/team"> 
      <xsl:sort select="@sortname" /> 

      <xsl:copy> 
       <xsl:copy-of select="@*[name() != 'sortname']" /> 
      </xsl:copy> 
     </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

In dem obigen Beispiel voran ich eine ‚1‘ auf jede Nationalmannschaft, und eine ‚2‘ auf jedem inländischen Team und sortieren Sie dann nach diesem neuen Attribut.

Informationen darüber, welche XSLT-Prozessoren welche Erweiterungen unterstützen, finden Sie unter Node Sets.

11

Tim C bereits eine nette Antwort gegeben hat, aber vielleicht wird ein einfacherer Weg in Ihrem Fall ausreichen. Sie könnten einfach zwei xsl:sort Bedingungen angeben: Die erste wird sortieren nach bevorzugten/nicht-bevorzugten Elemente, die zweite alphabetisch nach Namen:

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

    <xsl:template match="/teams"> 
    <teams> 
     <xsl:for-each select="team"> 
     <xsl:sort select="not(@name = 'England' or @name='Northern Ireland' 
          or @name='Republic of Ireland' 
          or @name='Scotland' or @name='Wales')" 
        data-type="number"/> 
     <xsl:sort select="@name"/> 
     <team> 
      <xsl:value-of select="@name"/> 
     </team> 
     </xsl:for-each> 
    </teams> 
    </xsl:template> 
</xsl:stylesheet> 

Bitte beachten Sie, dass die erste Bedingung not() mit invertieren haben.Der Grund dafür ist, dass das boolesche Ergebnis Ihres Ausdrucks in eine Zahl konvertiert wird (0 ist falsch, 1 ist wahr) und daher werden die Elemente, die auf "falsch" ausgewertet werden, zuerst aufgeführt.

+0

Ihre Antwort ist viel schöner als meine. Ihr benötigt keine Erweiterungsfunktion! –

+0

Eine Erweiterungsfunktion gibt Ihnen jedoch größere Flexibilität IMHO. –