Уникальный идентификатор и несколько классов с XPath - PullRequest
3 голосов
/ 12 января 2010

Я использую XSLT для отображения меню ul, содержащего li и a.

Я хочу следующее:

  1. Найдите первый элемент li a и добавьте класс .firstitem.
  2. Найдите последний элемент li a и добавьте класс .lastitem.
  3. Найдите активный элемент li a и добавьте класс .active.
  4. Добавить уникальный идентификатор для каждого li a элемента. (Т. Е. Текстовое меню, удобное для URL, как идентификатор).

Мне удалось выполнить шаг 1-3. За исключением того, что когда я пытаюсь добавить классы, он фактически заменяет другие классы, а не добавляет к ним.

Вот код:

<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>

В действительности элемент a может содержать все эти три класса. Но, как он проходит через код, он заменяет все в атрибуте class. Как я могу добавить классы вместо того, чтобы заменить их?

И шаг № 4 в моем списке - получить уникальный идентификатор, предпочтительно на основе @MenuText. Я знаю, что есть функция replace(), но я не могу заставить ее работать, и мой редактор говорит, что replace() это не функция.

Текст пункта меню содержит пробелы, тире и другие символы, которые недопустимы для использования в атрибуте id. Как я могу заменить эти символы?

Ответы [ 3 ]

6 голосов
/ 12 января 2010
<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() - это функция XSLT2.0. При использовании XSLT1.0 вам потребуется пользовательский шаблон для выполнения большинства операций со строками.

4 голосов
/ 12 января 2010

Я добавляю это к ответу Мартина Лаармана, который охватывает ваши требования 1-3 и имеет мой голос:

Чтобы удалить все, кроме определенного диапазона символов, из строки с XSLT 1.0 (ваше четвертое требование), выполните следующие действия.

<!-- declare at top level -->
<xsl:variable 
  name="validRange" 
  select="'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' 
/>

<!-- later, within a template… -->
<xsl:attribute name="id">
  <xsl:value-of select="
    concat(
      'id_',
      translate(
        @MenuText, 
        translate(@MenuText, $validRange, ''),
        ''
      )
    )
  " />
</xsl:attribute>

Внутренний translate() удаляет любой действительный символ из @MenuText, оставляя только недействительные символы. Они подаются на внешний translate(), который теперь может удалить все недействительные символы из @MenuText, какими бы они ни были в этом случае. Остаются только действительные символы.

Вы можете сделать из него функцию:

<xsl:template name="HtmlIdFromString">
  <xsl:param name="input" select="''" />
  <xsl:value-of select="
    concat('id_', translate( $input, translate($input, $validRange, ''), ''))
  " />
</xsl:template>

и назовите это так:

<xsl:attribute name="id">
  <xsl:call-template name="HtmlIdFromString">
    <xsl:with-param name="input" select="@MenuText" />
  </xsl:call-template>
</xsl:attribute>
0 голосов
/ 12 января 2010

Используйте

<xsl:template match="@*">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
    </xsl:copy>
</xsl:template>

для копирования всех существующих атрибутов.

Функция replace () поддерживается только в xslt 2.0, но я нашел этот обходной путь для xslt 1.0.

...