Mr. Horse: CSS-Klasse aus mehreren Werten zusammensetzen

Hallo,

ich baue mir per XSLT ein Menü zusammen. Der aktive Menüpunkt soll dabei die Klasse "current" bekommen. Zusätzlich muss das erste LI-Elemente in der Navigation die Klasse "first" bekommen.
Ich versuche es im Moment so:

<xsl:template match="menuItem" mode="subnav">
 <li>
  <xsl:attribute name="class" value="" />
  <xsl:if test="@href = $current_file_path">
   <xsl:attribute name="class"><xsl:value-of select="concat(@class,' current')" /></xsl:attribute>
  </xsl:if>
  <xsl:if test="position()=1">
   <xsl:attribute name="class"><xsl:value-of select="concat(@class,' first')" /></xsl:attribute>
  </xsl:if>
<!-- ... etc. -->

Dabei wird der Wert des class-Attributs aber leider innerhalb des zweiten if-Blocks überschrieben. Das Ergebnis ist dann im resultierenden HTML "first" statt "current first".
Trifft das zweite if-Statement nicht zu, so erhalte ich class="current".

Das heißt, die Einzelteile des XSLT-Fragments oben scheinen korrekt zu sein - aber es hapert an der Gesamtlogik.
Vielleicht könnt Ihr mir weiterhelfen?

Danke!

So long,
Andreas

--
No, Sir, I don't like it.
  1. Hallo!

    <xsl:template match="menuItem" mode="subnav">
    <li>
      <xsl:attribute name="class" value="" />
      <xsl:if test="@href = $current_file_path">
       <xsl:attribute name="class"><xsl:value-of select="concat(@class,' current')" /></xsl:attribute>
      </xsl:if>
      <xsl:if test="position()=1">
       <xsl:attribute name="class"><xsl:value-of select="concat(@class,' first')" /></xsl:attribute>
      </xsl:if>
    <!-- ... etc. -->

    Du solltest eher so etwas machen:

    <xsl:template match="menuItem" mode="subnav">  
      <li>  
         <xsl:attribute name="class">  
           <xsl:if test="@href = $current_file_path">  
             <xsl:value-of select="' current'" />  
           </xsl:if>  
           <xsl:if test="position() = 1">  
             <xsl:value-of select="' first'" />  
           </xsl:if>  
         </xsl:attribute>  
         <!-- etc. -->  
    </xsl:template>
    

    Du hast bei Deinem Versuch zwei Dinge nicht beachtet:

    1. XSL ist eine funktionale Programmiersprache, d.h. Du kannst nicht einfach etwas Setzen und hinterher ändern. Selbst wenn Du zweimal hintereinander xsl:variable mit dem gleichen Namen hast, deklarierst Du im Endeffekt ZWEI Variablen, wobei die erste nur bis zum Auftauchen der zweiten sichtbar ist.

    2. XPath-Selektoren beziehen sich immer auf den Quell-Dokumentbaum, d.h. @class matcht garantiert *nicht* das class-Attribut des *generierten* Knotens - sondern höchstens ein potentiell existierendes class-Attribut des aktuellen Knotens im Quelldokument.

    Viele Grüße,
    Christian

    1. Hallo Christian,

      danke für Deine superschnelle Antwort!

      Du solltest eher so etwas machen:
      [...]

      Das klappt tatsächlich. Und erscheint mir jetzt, wo ich's weiß, auch sauberer und XML-gemäßer.

      1. XSL ist eine funktionale Programmiersprache, d.h. Du kannst nicht einfach etwas Setzen und hinterher ändern.

      Ja, habe ich mir hinter die Ohren geschrieben (ich hatte auch anderswo im Netz schon den Hinweis gefunden, dass man z.B. den Wert einer Variablen in XSL nicht ändern kann.

      1. XPath-Selektoren beziehen sich immer auf den Quell-Dokumentbaum, d.h. @class matcht garantiert *nicht* das class-Attribut des *generierten* Knotens - sondern höchstens ein potentiell existierendes class-Attribut des aktuellen Knotens im Quelldokument.

      Ah, ok, habe da zu sehr von den Script-Sprachen her gedacht.
      Danke für Deine Hilfe.

      So long,
      Andreas

      --
      No, Sir, I don't like it.