MudGuard: Zugriff auf vorheriges Element bei Sortierung

Hi,

ich versuche gerade, eine kleine Navigation zu basteln - es gibt einen Haufen Namen in einer Liste, es soll obendrüber eine Liste der vorhandenen Anfangsbuchstaben kommen, die dann als Links dienen sollen, damit man schnell z.B. zu den mit W beginnenden Namen kommt (also eine Buchstabenleiste).

Das versuche ich so zu lösen:

Für das erste Element (position 1) wird der Link auf jeden Fall ausgegeben.
Für die weiteren Elemente wird der Link nur dann ausgegeben, wenn der Anfangsbuchstabe sich vom Anfangsbuchstaben des vorherigen Elements unterscheidet.

Das Problem dabei ist der Zugriff auf das in der Sortierreihenfolge vorherige Element.
Wenn ich die Position des aktuellen Elements um 1 verringert für den Zugriff benutze, bekomme ich das entsprechende Element aus der XML-Dokumentreihenfolge, nicht aus der Sortierreihenfolge.

Was muß ich machen, um auf das vorherige Element bezüglich der Sortierreihenfolge zugreifen kann?

Oder gibt es einen besseren (weil funktionierenden) Weg, das zu lösen?

Eine Sortierung der XML-Daten kommt nicht in Frage, da das gleiche Spielchen noch mit anderen Attributen gemacht werden soll - das Dokument müßte also gleichzeitig in verschiedenen Sortierungen vorliegen...

Hier der Ausschnitt aus dem XSL:

<!-- das aufrufende Template, das für die Sortierung sorgt -->
<xsl:template match="allelems">
    <!-- diverser anderer Kram, der mit dem Problem nichts zu tun hat... -->

<xsl:apply-templates select="elem" mode="shortnavi">
        <xsl:sort select="@name"/>
    </xsl:apply-templates >

<!-- diverser anderer Kram, der mit dem Problem nichts zu tun hat... -->
</xsl:template>

<!-- das Template, das die Kurz-Navigation erzeugen soll -->
<xsl:template match="elem" mode="shortnavi">
    <!-- $current enthält erstes Zeichen des name-Attributs als Großbuchstabe) -->
    <xsl:variable name="current" select="translate(substring(@name,1,1),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>

<!-- $thispos enthält Position des Elements (minus 1) entsprechend der Sortierung -->
    <xsl:variable name="thispos" select="position()-1"/>

<!-- falls nicht das erste Element: -->
    <xsl:if test="$thispos>0">

<!-- $current sollte das erste Zeichen des Vorgängers enthalten -->
        <!-- leider wird aber die Position auf die Reihenfolge der Elemente im XML bezogen, nicht auf die sortierte Reihenfolge -->
        <xsl:variable name="previous" select="translate(substring(../elem[$thispos]/@name,1,1),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />

<!-- was muß ich ändern, damit ich an das vorherige Element in der Sortierreihenfolge komme? -->

<!-- bei nicht-Übereinstimmung: Link erzeugen -->
        <xsl:if test="$previous != $current">
            <a href="#label{$current}"><xsl:value-of select="$current"/></a>
        </xsl:if>
    </xsl:if>
</xsl:template>

cu,
Andreas

--
MudGuard? Siehe http://www.Mud-Guard.de/
  1. Was muß ich machen, um auf das vorherige Element bezüglich der Sortierreihenfolge zugreifen kann?

    Pack das xsl:sort-Ergebnis in eine Variable - dann klappt's auch mit der -1

    1. Hi,

      Was muß ich machen, um auf das vorherige Element bezüglich der Sortierreihenfolge zugreifen kann?

      Pack das xsl:sort-Ergebnis in eine Variable - dann klappt's auch mit der -1

      Danke schonmal.
      Hm. Ok.
      2 Fragen dazu:

      1.) Wie krieg ich das sort-Ergebnis in eine Variable?
      Sprich:
      was muß ich in mein
      <xsl:variable name="sortedelems"></xsl:variable>
      reinschreiben?

      2.) Wie greife ich dann auf das Zeug wieder zu?
      Geht das dann per select="$sortedelems/elem"?
      (würd ich ja ausprobieren, wenn ich wüßte, wie ich die Teile in die Variable reinbekomme...)

      cu,
      Andreas

      --
      MudGuard? Siehe http://www.Mud-Guard.de/
  2. Hallo Andreas,

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="firstletter" match="elem" use="translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />

    ...

    <xsl:template match="allelems">
        <!-- diverser anderer Kram, der mit dem Problem nichts zu tun hat... -->
        <xsl:call-template name="abclist" />
        <!-- diverser anderer Kram, der mit dem Problem nichts zu tun hat... -->
     <xsl:apply-templates select="elem">
      <xsl:sort select="@name" />
     </xsl:apply-templates>
    </xsl:template>

    <xsl:template name="abclist">
        <xsl:for-each select="elem[generate-id() = generate-id(key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))[1])]">
      <xsl:sort select="@name"/>
            <a href="#label{@name}"><xsl:value-of select="substring(@name, 1, 1)"/></a>&#160;
     </xsl:for-each>
    </xsl:template>

    <xsl:template match="elem">
     <p><a name="label{@name}"></a><xsl:value-of select="." /></p>
    </xsl:template>
    </xsl:stylesheet>

    ----------

    Grüße
    Thomas

    1. Hi,

      Hallo Andreas,

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:key name="firstletter" match="elem" use="translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />
      [...]

      Mal gucken - das muß ich mir erst in Ruhe reinziehen, was das tut.
      Mit key hab ich noch nicht gearbeitet.

      Danke schonmal

      cu,
      Andreas

      --
      MudGuard? Siehe http://www.Mud-Guard.de/
      1. Hallo,

        <xsl:key name="firstletter" match="elem" use="translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />
        [...]

        Mal gucken - das muß ich mir erst in Ruhe reinziehen, was das tut.
        Mit key hab ich noch nicht gearbeitet.

        Der key erstellt quasi ein Array in dem alle <elem>-elemente drinn sind, der WErt des Schlüssels ist der erste Buchstabe (großgeschrieben) den @name-Attributes

        ------
        <xsl:for-each select="elem[generate-id() = generate-id(key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))[1])]">

        "elem[generate-id()"

        Generiert eine ID für das <elem>-Element
        "generate-id(key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))[1])]"

        Generiert eine ID für das erste <elem>-Element aus der (mit xsl:key) erstellten Grupppe, wo der Schlüssel für das Aktuelle Element passt.
        (also z.B. für das erste vorkommende <elem> dessen @name mit einem "A" beginnt.)

        Wenn die zwei ID identisch sind, wird ein Link erstellt, mit dem Anfangsbuchstaben von @name des gegenwärtigen Elements.

        -----------
        Das Problem dabei ist der Zugriff auf das in der Sortierreihenfolge vorherige Element.
        Wenn ich die Position des aktuellen Elements um 1 verringert für den Zugriff benutze, bekomme ich das entsprechende Element aus der XML-Dokumentreihenfolge, nicht aus der Sortierreihenfolge.
        -----------

        Sort gilt immer nur für die Sortierung in der Ausgabe, nie aber für die Sortierung im Transformationsprozess selbst.

        Grüße
        Thomas

        1. Hi,

          Der key erstellt quasi ein Array in dem alle <elem>-elemente drinn sind, der WErt des Schlüssels ist der erste Buchstabe (großgeschrieben) den @name-Attributes

          Ok, soweit hab ich das kapiert.

          <xsl:for-each select="elem[generate-id() = generate-id(key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))[1])]">

          Auch das habe ich verstanden.

          Die Navigationsliste krieg ich jetzt wunderschön generiert.

          Problem sind jetzt noch die Anker.
          Das sollen (müssen) nämlich id-Attribute werden (einerseits, weil der NS 4.x keine Rolle spielt und die id als Ansprungpunkt ausreicht, andererseits, weil die ids dann auch noch für CSS-Zwecke benutzt werden).

          Das resultiert wieder in 2 Problemen:
          id-Attribute müssen eindeutig sein, die name-Attributwerte aus dem XML sind es nicht.

          Darum wollte ich ja auch von Anfang an eigentlich nur diejenigen Ankerpunkte erzeugen, die tatsächlich benötigt werden.
          Sprich: nur im jeweils ersten Element pro Gruppe (Gruppierung nach erstem Buchstaben).

          Mein Versuch war folgendes:

          <xsl:template match="elem" mode="byname">
              <p>
                  <xsl:variable name="current" select="translate(substring(@name,1,1),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>

          <xsl:if test="generate-id() = generate-id(key('firstletter', $current)[1])">
                      <xsl:attribute name="id">label<xsl:value-of select="$current"/></xsl:attribute>
                  </xsl:if>
                  <!-- restliche Ausgabe des Elements -->
              </p>
          </xsl:template>

          Aber das setzt die ID wieder beim ersten Element pro Gruppe - aber wieder nach der XML-Reihenfolge...

          So wie ich das sehe, hab ich jetzt 3 Möglichkeiten:

          Ich verzichte auf Validität und die Möglichkeit, die anzuspringenden Elemente einfach per CSS zu formatieren, indem ich allen so erzeugten Absätzen die ID erzeugen lasse.

          Oder ich lasse doch nur pro Gruppe eine ID erzeugen, dann ist das erzeugte HTML valide, aber die Anker sitzen teilweise an der falschen Stelle, und ich kann die IDs auch nicht als CSS-Selektoren benutzen, da sie ja nicht in den gewünschten Elementen (das erste pro Gruppe) stehen.

          Oder ich muß statt einem
          <xsl:apply-templates select="elem"/>
          zig verschiedene machen, wobei jedes apply-template nur die Elemente mit einem bestimmten Anfangszeichen im name-Attribut selektiert (dann kann ich wieder mit position() = 1 dasjenige rausfiltern, das die ID bekommt, also
          <xsl:apply-templates select="elem[substring(@name,1,1) = 'A' or substring(@name,1,1) = 'a']"/>
          <xsl:apply-templates select="elem[substring(@name,1,1) = 'B' or substring(@name,1,1) = 'b']"/>
          <!-- ... -->
          <xsl:apply-templates select="elem[substring(@name,1,1) = 'Z' or substring(@name,1,1) = 'z']"/>
          und noch ein paar mehr für die Ziffern und noch ein paar erlaubte Zeichen.

          Oder ist das von sschumann vorgeschlagene irgendwie realisierbar?
          Mir ist es jedenfalls nicht gelungen, den sortierten Baum in eine Variable zu bekommen (und dann mit der Variable weiterzuarbeiten).

          cu,
          Andreas

          --
          MudGuard? Siehe http://www.Mud-Guard.de/
          1. Hallo,

            Problem sind jetzt noch die Anker.

            Ich denke nach ... :-)

            Oder ist das von sschumann vorgeschlagene irgendwie realisierbar?

            Nein, weil xsl:sort ein leeres Element ist und es darf nur als top-level innerhalt vom for-each oder apply-temptaltes stehen.

            Grüße
            Thomas

            1. Hi,

              Problem sind jetzt noch die Anker.
              Ich denke nach ... :-)

              Ich auch - ich werde mich dazu jetzt in eine horizontale Körperhaltung begeben, Licht und andere störende Einflüsse abschalten und mir nur noch von über einen Zaun hüpfenden Schäfchen helfen lassen. ;-)

              Oder ist das von sschumann vorgeschlagene irgendwie realisierbar?
              Nein, weil xsl:sort ein leeres Element ist und es darf nur als top-level innerhalt vom for-each oder apply-temptaltes stehen.

              Ok, ein Weg weniger, der weiterverfolgt werden muß...

              cu,
              Andreas

              --
              MudGuard? Siehe http://www.Mud-Guard.de/
              1. Hallo,

                Problem sind jetzt noch die Anker.
                Ich denke nach ... :-)

                ich habe jetzt eine Lösung (wenn es dir so reicht?)

                Grüße
                Thomas
                --------- xml ---------------------
                <data>
                 <allelem>
                  <elem name="bbcd">bbcd</elem>
                  <elem name="abcd">abcd</elem>
                  <elem name="aaa">aaa</elem>
                  <elem name="deef">deef</elem>
                  <elem name="dada">dada</elem>
                  <elem name="bacb">bacb</elem>
                  <elem name="efgh">efgh</elem>
                  <elem name="waw">waw</elem>
                  <elem name="h">h</elem>
                  <elem name="waz">waz</elem>
                  <elem name="adef">adef</elem>
                  <elem name="cece">cece</elem>
                  <elem name="cdbb">cdbb</elem>
                  <elem name="ghij">ghij</elem>
                  <elem name="gghh">gghh</elem>
                  <elem name="eeff">eeff</elem>
                  <elem name="aaab">aaab</elem>
                 </allelem>
                </data>
                ---------------- xsl ------------------------------
                <?xml version="1.0" encoding="iso-8859-1"?>
                <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
                <xsl:key name="firstletter" match="elem" use="translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />

                <xsl:template match="/data">
                <html>
                <head>
                 <title>Untitled</title>
                </head>

                <body>
                 <xsl:apply-templates />
                </body>
                </html>
                </xsl:template>

                <xsl:template match="allelem">
                    <xsl:call-template name="abclist" />
                 <xsl:apply-templates select="elem" mode="byname">
                  <xsl:sort select="@name"/>
                 </xsl:apply-templates>
                </xsl:template>

                <xsl:template name="abclist">
                 <xsl:for-each select="elem[generate-id() = generate-id(key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))[1])]">
                  <xsl:sort select="@name"/>
                     <a href="#label{substring(@name, 1, 1)}"><xsl:value-of select="substring(@name,1,1)"/></a>&#160;
                 </xsl:for-each>
                </xsl:template>

                <xsl:template match="elem" mode="byname">
                 <xsl:if test="generate-id(.) = generate-id(key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))[1])">
                  <xsl:call-template name="groupelembyname">
                   <xsl:with-param name="gruppe" select="key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))" />
                  </xsl:call-template>
                 </xsl:if>
                </xsl:template>

                <xsl:template name="groupelembyname">
                 <xsl:param name="gruppe" />
                   <h1><a id="label{substring($gruppe[1], 1, 1)}">label <xsl:value-of select="substring($gruppe[1], 1, 1)" /></a></h1>
                  <xsl:for-each select="$gruppe">
                   <xsl:sort select="@name" />
                   <p>
                    <xsl:value-of select="." />
                   </p>
                  </xsl:for-each>
                </xsl:template>
                </xsl:stylesheet>

                1. Hi,

                  ich habe jetzt eine Lösung (wenn es dir so reicht?)

                  Muchachos Garcia oder so...

                  Mal sehen, ob ich die neuen Teile verstanden habe...

                  <xsl:template match="elem" mode="byname">
                     <xsl:if test="generate-id(.) = generate-id(key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))[1])">
                         <xsl:call-template name="groupelembyname">
                             <xsl:with-param name="gruppe" select="key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))" />
                        </xsl:call-template>
                     </xsl:if>
                  </xsl:template>

                  Mit dem generate-id-Zeug wird sichergestellt, daß pro Anfangszeichen im Name-Attribut genau ein Aufruf von groupelembyname geschieht.
                  Diesem Aufruf werden die Elemente der Gruppe als Parameter mitgegeben.

                  <xsl:template name="groupelembyname">
                     <xsl:param name="gruppe" />
                     <h1><a id="label{substring($gruppe[1], 1, 1)}">label <xsl:value-of select="substring($gruppe[1], 1, 1)" /></a></h1>
                     <xsl:for-each select="$gruppe">
                         <xsl:sort select="@name" />
                         <p>
                             <xsl:value-of select="." />
                         </p>
                    </xsl:for-each>
                  </xsl:template>

                  Hier wird erstmal das Label erzeugt, anschließend die Elemente der Gruppe ausgegeben.

                  Klingt eigentlich einfach - aber da wär ich nie drauf gekommen.

                  Nochmals herzlichen Dank - wenn Du mal hier vorbeikommst, geb ich Dir nen Green Spot aus - jetzt trink ich erst mal einen auf Dein Wohl!

                  cu,
                  Andreas

                  --
                  MudGuard? Siehe http://www.Mud-Guard.de/
                  1. Hallo,

                    Eigentlich kannst du auf den named-Template verzichten und gleich so machen:
                    <xsl:template match="elem" mode="byname">
                     <xsl:variable name="gruppe" select="key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))" />
                        <xsl:if test="generate-id(.) = generate-id(key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))[1])">
                      <h1><a id="label{substring($gruppe[1], 1, 1)}">label <xsl:value-of select="substring($gruppe[1], 1, 1)" /></a></h1>
                            <xsl:for-each select="$gruppe">
                             <xsl:sort select="@name" />
                                <p>
                                 <xsl:value-of select="." />
                                </p>
                            </xsl:for-each>
                        </xsl:if>
                    </xsl:template>

                    Allerdings auf die 2-fache xsl:sort kannst du nicht verzeichten, dass muss also bleiben.

                    Mit dem generate-id-Zeug wird sichergestellt, daß pro Anfangszeichen im Name-Attribut genau ein Aufruf von groupelembyname geschieht.

                    <xsl:if test="generate-id(.)  ....

                    Überprüft die Übereinstimmung des aktuellen Elements mit dem ersten Knoten aus xsl:key, wo d. anf.Buchstabe aus @name überinstimmt. Testet also das aktuelle element auf seine Gruppenzugehörigkeit.

                    <h1><a id="label{substring($gruppe[1], 1, 1)}">label <xsl:value-of select="substring($gruppe[1], 1, 1)" /></a></h1>

                    Das ist quasi das gemogelte: anstatt hier tatsächlich das erste element nach der Sortierreihenfolge (wäre name="aaa" aus dem XML) zu verlinken, wird einfach die anf.Buchstabe der Gruppe ausgegeben.

                    » »»    <xsl:for-each select="$gruppe">

                    $gruppe ist hier zugegebener Maßen leicht irreführend, die Variable selektiert die Elemente die mit dem key() übereinstimmen. Was zwar eine Gruppe ergibt, jedoch enthält die Variable nur einzelne Elementen. Darum for-each.

                    <xsl:sort select="@name" />

                    Diese sortiert die Elementen innerhalb der Gruppe.
                    Das andere xsl:sort im apply-template sortiert (quasi) die Gruppen.

                    Klingt eigentlich einfach - aber da wär ich nie drauf gekommen.

                    Ja, ich wollte es auch erst anders machen (erstes Element in der sortierten Gruppe verlinken.) Dann bin ich daraufgekommen, dass das an sich nicht nötig ist.

                    Nochmals herzlichen Dank - wenn Du mal hier vorbeikommst, geb ich Dir nen Green Spot aus - jetzt trink ich erst mal einen auf Dein Wohl!

                    Danke, ich nehme dich bei Gelegenheit beim Wort ;-)

                    Grüße
                    Thomas

                    1. Hi,

                      Danke, jetzt sind alle Klarheiten beseitigt.

                      Nochmals herzlichen Dank - wenn Du mal hier vorbeikommst, geb ich Dir nen Green Spot aus - jetzt trink ich erst mal einen auf Dein Wohl!
                      Danke, ich nehme dich bei Gelegenheit beim Wort ;-)

                      Gerne - ist ja nicht das erste Mal, das Du mir hier hilfst!

                      cu,
                      Andreas

                      --
                      MudGuard? Siehe http://www.Mud-Guard.de/
                2. Hi,

                  <xsl:template name="groupelembyname">
                  <xsl:param name="gruppe" />
                     <h1><a id="label{substring($gruppe[1], 1, 1)}">label <xsl:value-of select="substring($gruppe[1], 1, 1)" /></a></h1>
                     <xsl:for-each select="$gruppe">
                       <xsl:sort select="@name" />
                       <p>
                         <xsl:value-of select="." />
                       </p>
                     </xsl:for-each>
                  </xsl:template>

                  Hab das jetzt noch leicht modifiziert - ich will eigentlich keine zusätzlichen Elemente (so wie hier im Beispiel die h1 + a), sondern direkt in den sowieso erzeugten Elementen (hier: p) die id.
                  Aber das ist jetzt kein Problem - innerhalb des for-each kann ich mit test="position()=1" arbeiten:

                  <xsl:template name="groupelembyname">
                     <xsl:param name="gruppe" />
                     <xsl:for-each select="$gruppe">
                        <xsl:sort select="@name" />
                        <p>
                           <xsl:if test="position() = 1">
                              <xsl:attribute name="id">label<xsl:value-of select="translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/></xsl:attribute>
                           </xsl:if>
                           <xsl:value-of select="." />
                        </p>
                     </xsl:for-each>
                  </xsl:template>

                  Nochmals vielen Dank für Deine Mühen!

                  Nicht nur mein akutes Problem ist gelöst, ich meine, jetzt grundsätzlich key verstanden zu haben.

                  cu,
                  Andreas

                  --
                  MudGuard? Siehe http://www.Mud-Guard.de/
          2. Hi,

            Problem sind jetzt noch die Anker.
            Das sollen (müssen) nämlich id-Attribute werden (einerseits, weil der NS 4.x keine Rolle spielt und die id als Ansprungpunkt ausreicht, andererseits, weil die ids dann auch noch für CSS-Zwecke benutzt werden).

            Ich glaub, ich lös das jetzt ganz anders:

            Da die ganze Transformation nicht online bzw. on demand geschieht, sondern offline zu von mir vorgegebenen Zeitpunkten:

            ich lasse vom XSLT einfach alle Labels generieren und schick das Ergebnis noch durch ein Perlscript (oder PHP-Commandline-Script), das dann die überflüssigen id-Attribute wieder rauswirft. Da brauch ich mir ja nur die letzte id="label?" zu merken - ist die aktuelle identisch, wird sie weggeworfen, ist sie anders, wird sie stehengelassen und gemerkt...

            Eine XSLT-Only-Variante wär aber trotzdem schöner...

            cu,
            Andreas

            --
            MudGuard? Siehe http://www.Mud-Guard.de/
        2. Hi,

          <xsl:key name="firstletter" match="elem" use="translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />
          <xsl:for-each select="elem[generate-id() = generate-id(key('firstletter', translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))[1])]">

          Nach noch etwas Nachdenken:

          Wenn ich das richtig sehe, funktioniert das bei der Buchstabenliste, weil bei mehreren Elementen, deren name-Attribut dasselbe ersten Zeichen haben, vollkommen egal ist, von welchem dieser mehreren Elemente ich das erste Zeichen verwende, da das erste Zeichen ja bei allen gleich ist.
          Es wird immer das vom XML-Dokument-Reihenfolge-ersten Element benutzt, aber das unterscheidet sich ja nicht von den anderen.

          Und das hilft natürlich bei den id-Attributen nicht, denn hier unterscheiden sich die Elemente, da ja nicht nur das erste Zeichen des name-Attributs verwendet wird - hier bräuchte ich das erste in Sortierreihenfolge mit einem bestimmten ersten Zeichen, und das kann ich wohl nicht rausfinden...

          cu,
          Andreas

          --
          MudGuard? Siehe http://www.Mud-Guard.de/
  3. Hi,

    Ok, inzwischen schaut das Template im Prinzip so aus:

    <xsl:template name="groupelembyname">
       <xsl:param name="gruppe" />
       <xsl:for-each select="$gruppe">
          <xsl:sort select="@name" />
          <p>
             <xsl:if test="position() = 1">
                <xsl:attribute name="id">label<xsl:value-of select="translate(substring(@name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/></xsl:attribute>
             </xsl:if>

    <!-- hier Numerierung erzeugen -->.)
             <xsl:value-of select="." />
          </p>
       </xsl:for-each>
    </xsl:template>

    Jetzt würde ich gerne noch eine Numerierung haben.
    Wenn ich an der oben markierten Stelle <xsl:value-of select="position()" /> schreibe, bekomme ich zwar wunderschöne Nummern, aber diese starten für jede Gruppe wieder bei 1 - klar, pro Template-Aufruf wird ja auch nur eine Gruppe ausgegeben, und die Tatsache, daß immer wieder mit 1 begonnen wird, nutze ich ja auch aus, um nur beim ersten Element jeder Gruppe die id zu erzeugen.

    Ok - Numerierung ==> <xsl:number />
    Wenn ich das aber einsetze, bekomme ich wieder die Numerierung anhand der XML-Dokument-Reihenfolge.

    So ein Mist!
    Ich will das Zeug eigentlich nicht in eine ol packen. Und die CSS-Counter funktionieren leider im Mozilla nicht...

    cu,
    Andreas

    --
    MudGuard? Siehe http://www.Mud-Guard.de/
    Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
    1. Hi,

      Ich will das Zeug eigentlich nicht in eine ol packen. Und die CSS-Counter funktionieren leider im Mozilla nicht...

      Hab ich jetzt doch gemacht...

      cu,
      Andreas

      --
      MudGuard? Siehe http://www.Mud-Guard.de/
      Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
      1. Hallo,

        Ich will das Zeug eigentlich nicht in eine ol packen. Und die CSS-Counter funktionieren leider im Mozilla nicht...

        Hab ich jetzt doch gemacht...

        Hm ... mir fällt im Moment auch nichts besseres ein.

        Grüße
        Thomas