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