hh: Frage zum Sortieren mit XSL

Hi, welchen Lösungsweg gibt es hierfür, habe mich schon wund gegoogelt.

<roo>
<name att="einebezeichnung"/>
<name att="eineanderebezeichnung"/>
<name att="nocheinebezeichnung"/>
</root>

es soll das Attribut att ausgegeben werden und dabei ist eine Sortierung vorzunehmen. Die Regelung für die Sortierung entnehme ich aber einer anderen xml quelle

ich wollte es so machen

<xsl:for-each select="name">
<xsl:variable name="att_wert" select="@att"/>
<xsl:variable name="stufe">
<xsl:call-tempplate name="stufe_ermitteln">
<xsl:with param name="att_uebergabe" select="$att_wert"/>
</xsl:call-template>
</xsl:variable>

<!-- Ausgabe der Stufe und Bezeichnung -->
<xsl:value-of select="$stufe"/>
xsl:text_</xsl:text>
<xsl:value-of select="$att_wert"/>
<br/>
</xsl:for-each>

Zur Zeit bekomme ich dann ein Ergebnis wie folgt:

2_einebezeichnung
1_eineanderebezeichnung
3_nocheinebezeichnung

Wie schaffe ich es nun, die Ausgabe noch sortieren zu lassen? also etwa nach der stufe so:

1_eineanderebezeichnung
2_einebezeichnung
3_nocheinebezeichnung

Bin etwas ratlos.

  1. Hallo,

    Hi, welchen Lösungsweg gibt es hierfür, habe mich schon wund gegoogelt.
    es soll das Attribut att ausgegeben werden und dabei ist eine Sortierung vorzunehmen. Die Regelung für die Sortierung entnehme ich aber einer anderen xml quelle

    ich wollte es so machen

    <xsl:for-each select="name">
    <xsl:variable name="att_wert" select="@att"/>
    <xsl:variable name="stufe">
    <xsl:call-tempplate name="stufe_ermitteln">
    <xsl:with param name="att_uebergabe" select="$att_wert"/>
    </xsl:call-template>
    </xsl:variable>

    <!-- Ausgabe der Stufe und Bezeichnung -->
    <xsl:value-of select="$stufe"/>

    auf diese Weise hat aber $stufe nie einen Wert, da fehlt noch was und genau das fehlt hier auch (zu wissen, nach welchen Regel du sotrieren wills (andere xml-quelle))

    Grüße
    Thomas

    1. Hallo Thomas, die andere xml-Quelle sieht ungefähr so aus, etwas "vereinfacht" (ich hoffe das ich nichts übersehen habe) Mir ist kein anderer Lösungsweg eingefallen um das Ergebnis dann so zubekommen:

      <root>
      <name att="einebezeichnung"/>
      <name att="eineanderebezeichnung"/>
      <name att="nocheinebezeichnung"/>
      <name att="undnocheinebezeichnung"/>
      </root>

      <root>
      <einheit att1="eineanderebezeichnung" att2="einebezeichnung" rang="1"/>
      <einheit att1="einebezeichnung" att2="nocheinebezeichnung" rang="1"/>
      <einheit att1="einebezeichnung" att2="undnocheinebezeichnung" rang="2"/>
      </root>

      xsl-file

      <xsl:for-each select="name">
      <xsl:variable name="att_wert" select="@att"/>
      <xsl:variable name="rang" select="document('quelle.xml')/einheit[@att2=$att_wert]/@rang"/>
      <xsl:variable name="stufe">
      <xsl:call-tempplate name="stufe_ermitteln">
      <xsl:with param name="att_uebergabe" select="$att_wert"/>
      </xsl:call-template>
      </xsl:variable>

      <!-- Ausgabe der Stufe und Rang und Bezeichnung -->
      <xsl:value-of select="$stufe"/>
      xsl:text_</xsl:text>
      <xsl:value-of select="$rang"/>
      xsl:text_</xsl:text>
      <xsl:value-of select="$att_wert"/>
      <br/>
      </xsl:for-each>

      <xsl:template name="stufe_ermitteln">
              <xsl:param name="att_uebergabe"/>
              <xsl:param name="counter" select="0"/>
              xsl:choose
                  <xsl:when
                      test="not(document('quelle.xml')/einheit[@att1=$att_uebergabe])">
                      <xsl:value-of select="$counter"/>
                      </xsl:when>
                  xsl:otherwise
                      <xsl:call-template name="stufe">
                          <xsl:with-param name="att_uebergabe"
                              select="document('quelle')/einheit[@att2=$att_uebergabe]/@att1"/>
                          <xsl:with-param name="counter" select="$counter + 1"/>
                      </xsl:call-template>
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:template>

      Zur Zeit bekomme ich dann ein Ergebnis wie folgt:

      2_1_einebezeichnung
      1_1_eineanderebezeichnung
      3_1_nocheinebezeichnung
      3_2_undnocheinebezeichnung

      Wie schaffe ich es nun, die Ausgabe noch sortieren zu lassen? also etwa nach der stufe so:

      1_1_eineanderebezeichnung
      2_1_einebezeichnung
      3_1_nocheinebezeichnung
      3_2_undnocheinebezeichnung

      Man könnte auch alles in ein XML-Quelle schreiben, das Problem dürfte aber das gleiche sein:

      <root>
      <name att="einebezeichnung"/>
      <name att="eineanderebezeichnung"/>
      <name att="nocheinebezeichnung"/>
      <name att="undnocheinebezeichnung"/>
      <einheit att1="eineanderebezeichnung" att2="einebezeichnung" rang="1"/>
      <einheit att1="einebezeichnung" att2="nocheinebezeichnung" rang="1"/>
      <einheit att1="einebezeichnung" att2="undnocheinebezeichnung" rang="2"/>
      </root>

      1. Hallo,

        Hallo Thomas, die andere xml-Quelle sieht ungefähr so aus, etwas "vereinfacht" (ich hoffe das ich nichts übersehen habe) Mir ist kein anderer Lösungsweg eingefallen um das Ergebnis dann so zubekommen:

        Wie schaffe ich es nun, die Ausgabe noch sortieren zu lassen? also etwa nach der stufe so:

        Nach "rang" zu sortieren ist relativ einfach:
        <xsl:for-each select="name">
           <xsl:sort select="document('quell.xml')/root/einheit[@att2=current()/@att]/@rang" data-type="number" />

        Nach Stufe zu sortieren geht so nicht, denn die Stufe wird nur erst bei instantiieren des Templates (hier for-each) ermittelt, also erst nachdem - falls vorhanden- eine Sortierung stattgefunden hat (und sort muss als erstes Kind von for-each stehen).
        Den Sinn dieses Counters verstehe ich aber trotzdem nicht wirklich.

        Grüße
        Thomas

        1. Hallo Thomas,

          danke für den Rang. Der Counter soll nichts anderes tun, als die ebene zu bestimmen.

          Vielleicht wird es so etwas deutlicher

          <root>
          <name att="untertitel"/>
          <name att="titel"/>
          <name att="unteruntertitel2"/>
          <name att="unteruntertitel1"/>
          </root>

          <root>
          <einheit att1="untertitel" att2="unteruntertitel1" rang="1"/>
          <einheit att1="titel" att2="untertitel" rang="1"/>
          <einheit att1="untertitel" att2="unteruntertitel2" rang="2"/>
          </root>

          Also der Counter mach nichts anderes, als rekursive die ebene (stufe) zu bestimmen. Mir fällt kein anderer Weg ein.

          0_titel
          1_1_untertitel
          2_1_unteruntertitel1
          2_2_unteruntertitel2

          1. Hallo,

            danke für den Rang. Der Counter soll nichts anderes tun, als die ebene zu bestimmen.

            Vielleicht wird es so etwas deutlicher

            <root>
            <name att="untertitel"/>

            <root>
            <einheit att1="untertitel" att2="unteruntertitel1" rang="1"/>

            Ja, das ergibt mehr Sinn.

            Also der Counter mach nichts anderes, als rekursive die ebene (stufe) zu bestimmen. Mir fällt kein anderer Weg ein.

            0_titel
            1_1_untertitel
            2_1_unteruntertitel1
            2_2_unteruntertitel2

            Da wäre ein count() ganz sinnvoll:
            -----------------------------------------
            <?xml version="1.0" encoding="iso-8859-1"?>
            <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:template match="/root">
             <html>
              <head>
               <title>Untitled</title>
              </head>
              <body>
               <xsl:for-each select="name">
                <xsl:sort select="count(document('temp1.xml')/root/einheit[@att1=current()/@att])" data-type="number" />
                <xsl:sort select="document('temp1.xml')/root/einheit[@att2=current()/@att]/@rang" data-type="number" />
                <xsl:variable name="rang" select="document('temp1.xml')/root/einheit[@att2=current()/@att]/@rang"/>
                <xsl:variable name="stufe">
                 <xsl:call-template name="stufe_ermitteln">
                  <xsl:with-param name="att_uebergabe" select="@att"/>
                 </xsl:call-template>
                </xsl:variable>

            <!-- Ausgabe der Stufe und Rang und Bezeichnung -->
                <xsl:value-of select="$stufe"/>
                xsl:text_</xsl:text>
                <xsl:value-of select="$rang"/>
                xsl:text_</xsl:text>
                <xsl:value-of select="@att"/>
                <br/>
               </xsl:for-each>
              </body>
             </html>
            </xsl:template>
            <xsl:template name="stufe_ermitteln">
             <xsl:param name="att_uebergabe"/>
             <xsl:param name="counter" select="1"/>
             xsl:choose
              <xsl:when test="not(document('temp1.xml')/root/einheit[@att1=$att_uebergabe])">
               <xsl:value-of select="$counter"/>
              </xsl:when>
              xsl:otherwise
               <xsl:call-template name="stufe_ermitteln">
                <xsl:with-param name="att_uebergabe" select="document('temp1.xml')/root/einheit[@att2=$att_uebergabe]/@att1"/>
                <xsl:with-param name="counter" select="$counter + 1"/>
               </xsl:call-template>
              </xsl:otherwise>
             </xsl:choose>
            </xsl:template>
            </xsl:stylesheet>
            -------------------------------

            meine Ausgabe ist:
            1_1_unteruntertitel1
            1_2_unteruntertitel2
            2__titel
            3_1_untertitel

            Falls das count() nicht ausreichend ist, wäre eine Gruppierung mit key() sinnvoll.

            Grüße
            Thomas

            1. Hallo Thomas, danke für die Mühe, habe es nur kurz überflogen und werde mich damit auseinandersetzten. Allerdings sollte nicht es nicht so:
              1_1_unteruntertitel1
              1_2_unteruntertitel2
              2__titel
              3_1_untertitel

              sonder eher

              1_titel
              2_1_untertitel
              3_1_unteruntertitel1
              3_2_unteruntertitel2

              ergeben. Aber ich werde mich gleich mal ransetzen, und schauen, ob ich es so hinbigene kann. Danke dir schon einmal.

              Gruß

              Holger
              »