Search code examples
xsltclassxpathreplaceunique

Unique ID and multiple classes with XPath


I'm using XSLT for displaying a ul menu containing li and a.

I want the following:

  1. Find the first li a element and add the .firstitem class.
  2. Find the last li a element and add the .lastitem class.
  3. Find the active li a element and add the .active class.
  4. Add an unique ID to each li a element. (I.e. URL friendly menu text as ID).

I've managed to make step 1-3 work. Except that when I try to add the classes, it actually replaces the other classes rather than adding to them.

Here's the code:

<li>
    <a>
        <!-- Add .firstitem class -->
        <xsl:if test="position() = 1">
            <xsl:attribute name="class">firstitem</xsl:attribute>
        </xsl:if>

        <!-- Add .lastitem class -->
        <xsl:if test="postition() = count(//Page)">
            <xsl:attribute name="class">lastitem</xsl:attribute>
        </xsl:if>

        <!-- Add .active class -->
        <xsl:if test="@Active='True'">
            <xsl:attribute name="class">active</xsl:attribute>
        </xsl:if>

        <!-- Add link URL -->
        <xsl:attribute name="href"><xsl:value-of select="@FriendlyHref" disable-output-escaping="yes"/></xsl:attribute>

        <!-- Add link text -->
        <xsl:value-of select="@MenuText" disable-output-escaping="yes"/>
    </a>
</li>

In realtity, the a element could contain all those three classes. But as is goes through the code, it replaces everything in the class attribute. How can I add the classes instead of replacing them?

And step number 4 on my list, is to get a unique ID, preferably based on @MenuText. I know there is a replace() function, but I can't get it to work and my editor says that replace() isn't a function.

The menu item text contains spaces, dashes and other symbols that are not valid for using in the id attribute. How can I replace those symbols?


Solution

  • <a>
           <xsl:attribute name="class">
                <!-- Add .firstitem class -->
                <xsl:if test="position() = 1">
                    <xsl:text> firstitem</xsl:text>
                </xsl:if>
                <!-- Add .lastitem class -->
                <xsl:if test="postition() = count(//Page)">
                    <xsl:text> lastitem</xsl:text>
                </xsl:if>
    
                <!-- Add .active class -->
                <xsl:if test="@Active='True'">
                    <xsl:text> active</xsl:text>
               </xsl:if>
           </xsl:attribute>
    
            <!-- Add link URL -->
            <xsl:attribute name="href"><xsl:value-of select="@FriendlyHref" disable-output-escaping="yes"/></xsl:attribute>
    
            <!-- Add link text -->
            <xsl:value-of select="@MenuText" disable-output-escaping="yes"/>
        </a>
    

    replace() is an XSLT2.0 function. When using XSLT1.0 you need a custom template to do most string manipulations.