André Laugks: xsl:sort

Hallo!

Mhhhh, sehe ich den Wald vor lauter XSL-Bäumen nicht mehr?

Folgendes XML-Dokument soll sortiert werden.

<liste>
 <eintrag>
  <name>Sandra C.</name>
 </eintrag>
 <eintrag>
  <name>Alex</name>
 </eintrag>
 <eintrag>
  <name>Michael Z.</name>
 </eintrag>
 <eintrag>
  <name>Ernst</name>
 </eintrag>
 <eintrag>
  <name>Dominic</name>
 </eintrag>
 <eintrag>
  <name>Evelyne</name>
 </eintrag>
 <eintrag>
  <name>Joukje</name>
 </eintrag>
 <eintrag>
  <name>Therese</name>
 </eintrag>
 <eintrag>
  <name>Lars</name>
 </eintrag>
</liste>

Dazu habe ich dieses XSL-Template geschrieben.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" indent="yes"/>
 <xsl:template match="/liste">
  <html>
   <body>
    <table border="1">
     <xsl:apply-templates select="eintrag"/>
    </table>
   </body>
  </html>
 </xsl:template>

<xsl:template match="eintrag">
   <xsl:for-each select="name">
   xsl:sort/
    <tr>
     <td><xsl:value-of select="."/></td>
    </tr>
   </xsl:for-each>
 </xsl:template>

</xsl:stylesheet>

xsl:sort/ sollte den aktuelle Kontextknoten 'name', für die Sortierung auswählen. Mir wird die Reihenfolge im XML-Dokument ausgegeben. Ich habe es im select-Attribut schon mit dem absoluten Pfad versucht, was auch nicht wollte.

Mit dem folgenen XSL-Template bekomme ich es richtig sortiert, also aussteigent.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" indent="yes"/>
 <xsl:template match="/liste">
  <html>
   <body>
    <table border="1">
     <xsl:apply-templates select="eintrag/name">
     xsl:sort/
     </xsl:apply-templates>
    </table>
   </body>
  </html>
 </xsl:template>

<xsl:template match="name">
    <tr>
     <td><xsl:value-of select="."/></td>
    </tr>
 </xsl:template>
</xsl:stylesheet>

MfG, André Laugks
L-Andre @ gmx.de

  1. Mhhhh, sehe ich den Wald vor lauter XSL-Bäumen nicht mehr?

    Folgendes XML-Dokument soll sortiert werden.

    <liste>
    <eintrag>
      <name>Sandra C.</name>
    </eintrag>
    <eintrag>
      <name>Alex</name>
    </eintrag>
    [...]

    Dazu habe ich dieses XSL-Template geschrieben.

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/liste">
      <html>
       <body>
        <table border="1">
         <xsl:apply-templates select="eintrag"/>
        </table>
       </body>
      </html>
    </xsl:template>

    <xsl:template match="eintrag">
       <xsl:for-each select="name">
       xsl:sort/
        <tr>
         <td><xsl:value-of select="."/></td>
        </tr>
       </xsl:for-each>
    </xsl:template>

    </xsl:stylesheet>

    xsl:sort/ sollte den aktuelle Kontextknoten 'name', für die Sortierung auswählen. Mir wird die Reihenfolge im XML-Dokument ausgegeben. Ich habe es im select-Attribut schon mit dem absoluten Pfad versucht, was auch nicht wollte.

    Guck dir nochmal an, was du eigentlich sortierst, alle name-Kinder eines eintrag-Elements. Jedes eintrag-Element hat aber nur ein name-Kind, von daher lässt sich da nicht viel sortieren.

  2. Hallo andre,

    Mhhhh, sehe ich den Wald vor lauter XSL-Bäumen nicht mehr?

    xsl:sort/ sollte den aktuelle Kontextknoten 'name', für die Sortierung auswählen. Mir wird die Reihenfolge im XML-Dokument ausgegeben. Ich habe es im select-Attribut schon mit dem absoluten Pfad versucht, was auch nicht wollte.

    was du suchst ist:
        <table border="1">
         <xsl:apply-templates select="eintrag">
          <xsl:sort select="name"/>
        </xsl:apply-templates>
        </table>

    Grüße
    Thomas

    1. Hallo!

      was du suchst ist:
          <table border="1">
           <xsl:apply-templates select="eintrag">
            <xsl:sort select="name"/>
          </xsl:apply-templates>
          </table>

      So oder fast hatte ich es schon gehabt.

      Diese Form bedeutet: Alle Kinderelemente des Elementes 'eintrag' selectieren. Die gesamte Liste der Kinderlemente soll dann sortiert werden? In meinem Falle gebe ich 'name'(Kind) an.
      Da ich aber nur ein element habe, benötige ich das Attribut select ja nicht.

      Wenn ich aber xsl:sort innerhalb xsl:tempalte definiere, wird die Sortierung pro Elternelement angewendet? Ich durchlaufe ja mit xsl:for-each jedes Kindelement eines Elternelementes?

      MfG, André Laugks
      L-Andre @ gmx.de

      1. Hallo Anrer,

        So oder fast hatte ich es schon gehabt.

        Diese Form bedeutet: Alle Kinderelemente des Elementes 'eintrag' selectieren. Die gesamte Liste der Kinderlemente soll dann sortiert werden? In meinem Falle gebe ich 'name'(Kind) an.
        Da ich aber nur ein element habe, benötige ich das Attribut select ja nicht.

        Überleg mal: wenn du nur ein Element hättest, was willst du dann an diesem einen Element sortieren? Du hast aber viele <name> Elemente.
        Du benötigst hier das Attribut select, weil du dein Sortierkriterium darin festlegst. Du legst eben fest dass die Ausgabe sortiert und zwar aufgrund des <name> Elements erfolgen muss.

        Wenn ich aber xsl:sort innerhalb xsl:tempalte definiere, wird die Sortierung pro Elternelement angewendet?

        Dann wird die Sortierung immer wieder pro <name> Element durchgeführt und da du in dem Fall tatsächlich nur ein einziges <name> Element zum Sortieren hast, bekommst du die von dir erwähnte "unsortierte" Liste.

        Ich durchlaufe ja mit xsl:for-each jedes Kindelement eines Elternelementes?

        Das kommt darauf an was du im xsl:for-each selektiert hast.
        Aber das ändert nicht daran, dass du beim for-each für <eintrag> pro <eintrag> die Sortierung vornimmst, was nur dann etwas bringen würde, wenn du im <eintrag> mehrere <name> Element hättest.
        Beim <xsl:teplate match=""> wird zwar ähnlich wie beim for-each für jedes <eintrag> Element die entsprechende Transformation durchgeführt aber die Ausgabe des Ergebnissbaumes erfolgt erst durch xsl:apply-templates und dort kannst du für diese Ausgabe eben die Reihenfolge der selben mit <xsl:sort select=""> festlegen.

        Grüße
        Thomas

        1. Hallo!

          Überleg mal: wenn du nur ein Element hättest, was willst du dann an diesem einen Element sortieren? Du hast aber viele <name> Elemente.

          Du benötigst hier das Attribut select, weil du dein Sortierkriterium darin festlegst. Du legst eben fest dass die Ausgabe sortiert und zwar aufgrund des <name> Elements erfolgen muss.

          Uppsss, ich hatte als ich es geschrieben habe, an mein Entwurf gedacht. Deshalb schrieb ich, ich kann das select weg lassen.

          Auszug:
          <xsl:apply-templates select="eintrag/name">
            xsl:sort/
          </xsl:apply-templates>

          Dann wird die Sortierung immer wieder pro <name> Element durchgeführt und da du in dem Fall tatsächlich nur ein einziges <name> Element zum Sortieren hast, bekommst du die von dir erwähnte "unsortierte" Liste.

          Ok, das ist jetzt klar.

          Beim <xsl:teplate match=""> wird zwar ähnlich wie beim for-each für jedes <eintrag> Element die entsprechende Transformation durchgeführt aber die Ausgabe des Ergebnissbaumes erfolgt erst durch xsl:apply-templates und dort kannst du für diese Ausgabe eben die Reihenfolge der selben mit <xsl:sort select=""> festlegen.

          'Ergebnisbaum' hat mich jetzt glaube drauf gebracht.

          <table border="1">
             <xsl:apply-templates select="eintrag">
               <xsl:sort select="name"/>
             </xsl:apply-templates>
          </table>

          <xsl:template match="eintrag">
            <xsl:for-each select="name">
              <xsl:sort select="."></xsl:sort>
                <tr>
                   <td><xsl:value-of select="."/></td>
                </tr>
            </xsl:for-each>
          </xsl:template>

          Bei <xsl:apply-templates select="eintrag"><xsl:sort select="name"/></xsl:apply-templates> kommen meine Namen folgendermaßen an. (Vielleicht nicht ganz so, aber mal bildlich gezeigt.)

          <tr><td><name>Sandra C.</name></td></tr>
          <tr><td><name>Alex</name></td></tr>
          <tr><td><name>Michael Z.</name></td></tr>
          <tr><td><name>Ernst</name></td></tr>
          <tr><td><name>Dominic</name></td></tr>
          <tr><td><name>Evelyne</name></td></tr>
          <tr><td><name>Joukje</name></td></tr>
          <tr><td><name>Therese</name></td></tr>
          <tr><td><name>Lars</name></td></tr>

          Jetzt erst wird nach 'name' sortiert.

          MfG, André Laugks
          L-Andre @ gmx.de