Announcement

Collapse
No announcement yet.

Rekursive Sortierung möglich?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Rekursive Sortierung möglich?

    Hallo beisammen,
    ich beschäftige mich seit Kurzem mit XSLT und bin auf ein Problem gestoßen, für das ich noch keine Lösung gefunden habe.
    Es soll eine XML Quelldatei sortiert werden und zwar sowohl die Elternknoten sollen sortiert sein, als auch die Kinderknoten innerhalb eines jedes Elternknoten.
    Bsp: Städte nach PLZ-Gebieten und innerhalb dieser Gebiete sollen alle Städtenamen alphabethisch geordnet sein.

    Geht das überhaupt (ich denke eigentlich sollte es gehen) und wie geht das richtig?
    PS.: Die Werte für PLZ und Name sind jeweils Attribute (das geht leider auch net anders)
    XML-Quelldaten Beispiel
    Code:
    <data>
    <record plzgebiet="5">
         <record plz="54345" name="Musterdorf"/>
         <record plz="54321" name="AnderesMusterdorf"/>
    </record>
    <record plzgebiet="1">
         <record plz="12321" name="Musterstadt"/> 
         <record plz="12345" name="AndereMusterstadt"/>
    </record>
    .....
    </data>
    Ziel ist jetzt folgendes:
    Code:
    <data>
    <record plzgebiet="1">
         <record plz="12321" name="AndereMusterstadt"/>
         <record plz="12345" name="Musterstadt"/>
    </record>
    <record ="5">
         <record plz="54321" name="AnderesMusterdorf"/>
         <record plz="54345" name="Musterdorf"/>
    </record>
    </data>
    mit folgender Transformierung bin ich nicht weiter gekommen, es wird nur die erste Hierarchiestufe sortiert...
    Code:
    <xsl:template match="/">
    <xsl:for-each select="/data/record" >
    <xsl:sort select="@plzgebiet" order="descending" data-type="number" />
    	<xsl:for-each select="/data/record/record">
    		<xsl:sort select="@name" order="ascending" data-type="text" />
    	</xsl:for-each>
    <xsl:copy-of select="."/>
    </xsl:for-each>
    </xsl:template>
    Kann mir da jmd weiterhelfen??
    Danke schon mal im Voraus!

  • #2
    Ansatz (das gewünschte Ergebnis entsteht mit 2x aufsteigender Sortierung, bei den Eingabedaten sind offenbar bei plzgebiet="1" die plz-Werte vertauscht):
    Code:
    <xsl:template match="data">
      <data>
        <xsl:for-each select="record">
          <xsl:sort select="@plzgebiet" order="ascending" data-type="number"/>
          <record plzgebiet="{@plzgebiet}">
            <xsl:for-each select="record">
              <xsl:sort select="@name" order="ascending" data-type="text"/>
              <xsl:copy-of select="."/>
            </xsl:for-each>
          </record>
        </xsl:for-each>
      </data>
    </xsl:template>
    Noch eine strukturiertere Variante ohne xsl:for-each:
    Code:
    <xsl:template match="data">
      <data>
        <xsl:apply-templates select="record[@plzgebiet]">
          <xsl:sort select="@plzgebiet" order="ascending" data-type="number"/>
        </xsl:apply-templates>
      </data>
    </xsl:template>
    
    <xsl:template match="record[@plzgebiet]">
      <record plzgebiet="{@plzgebiet}">
        <xsl:apply-templates select="record[@plz]">
          <xsl:sort select="@name" order="ascending" data-type="text"/>
        </xsl:apply-templates>  
      </record>
    </xsl:template>
    
    <xsl:template match="record[@plz]">
      <xsl:copy-of select="."/>
    </xsl:template>

    Comment


    • #3
      Danke schon mal für die Hilfe, habs grad getestet und funktioniert gut!
      Ist es auch möglich die "records" einfach zu übernehmen, da die ja schon vorhanden sind?
      Dann müsste man sie nicht neu "von Hand" erzeugen...

      Comment


      • #4
        Ja, so entfällt die manuelle <record>...</record>-Erstellung:
        Code:
        <xsl:template match="record[@plzgebiet]">
         <xsl:copy-of select=".">
           <xsl:apply-templates select="record[@plz]">
             <xsl:sort select="@name" order="ascending" data-type="text"/>
           </xsl:apply-templates> 
         </xsl:copy-of>
        </xsl:template>

        Comment


        • #5
          Danke für die schnelle Hilfe, werd ich gleich mal ausprobieren. Grüße

          Ein Problem ist jetzt schon aufgetaucht. Mit der "dynamischen Erweiterung" lässt sich das XSL nicht ausführen.
          Der Fehler meint: XTSE0260: Element must be empty
          Die Zeilenangabe verweist auf den <xsl:copy-of select="." >
          Der verwendete Transformer ist saxonHE9.2.0.3j
          Zuletzt editiert von Gast_1; 03.11.2009, 14:25.

          Comment


          • #6
            Kannst du mir das bitte mal erklären, wie das mit den einzelnen Templates genau funktioniert?
            Was wird als erstes gemacht? Erst sortiert und dann eine Etage tiefer, oder umgekehrt? Wie werden die "Daten" an die Templates weitergereicht?
            Ich kann mir das immer noch net so richtig vorstellen...

            Comment


            • #7
              Ok, mit Saxon ist der Fehler nachvollziehbar. Hatte mit AltovaXML getestet und es lief durch. Verwende alternativ diese Form:
              Code:
              <xsl:template match="record[@plzgebiet]">
                <xsl:copy>
                  <xsl:copy-of select="@*"/>
                  <xsl:apply-templates select="record[@plz]">
                    <xsl:sort select="@name" order="ascending" data-type="text"/>
                  </xsl:apply-templates> 
                </xsl:copy>
              </xsl:template>
              xsl:apply-templates ruft die im Kontext relevanten Templates auf. Für Details vielleicht mal einen XSLT-Kurs wie den von SELFHTML oder ein Einsteigerbuch konsultieren.

              Comment


              • #8
                Klasse, das funktioniert jetzt ohne Probleme.
                Ein XSLT Buch ist schon bestellt und auf SELFHTML bin ich auch schon die ganze Zeit unterwegs. Bisher hab ich nur sehr viel mit Java, Groovy und C# programmiert. Das Umdenken auf XSL ist nicht gerade leicht!
                Aber so langsam seh ich Licht am Ende des Tunnels...

                Comment

                Working...
                X