使用 XPath 的唯一 ID 和多个类

发布于 2024-08-17 17:50:32 字数 1704 浏览 2 评论 0原文

我使用 XSLT 来显示包含 liaul 菜单。

我想要以下内容:

  1. 找到第一个 li a 元素并添加 .firstitem 类。
  2. 找到最后一个 li a 元素并添加 .lastitem 类。
  3. 找到活动的 li a 元素并添加 .active 类。
  4. 为每个 li a 元素添加一个唯一的 ID。 (即 URL 友好的菜单文本作为 ID)。

我已经成功地完成了步骤 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 步是获取唯一 ID,最好基于 @MenuText。我知道有一个 replace() 函数,但我无法让它工作,而且我的编辑器说 replace() 不是一个函数。

菜单项文本包含空格、破折号和其他在 id 属性中使用无效的符号。我怎样才能替换这些符号?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

箹锭⒈辈孓 2024-08-24 17:50:32
<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 时,您需要 自定义模板用于执行大多数字符串操作。

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

南街九尾狐 2024-08-24 17:50:32

我将此添加到 Martijn Laarman 的答案中,该答案涵盖了您的要求 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>

I'm adding this to Martijn Laarman's answer, which covers your requirements 1-3 and has my vote:

To remove everything except a certain range of characters from a string with XSLT 1.0 (your 4th requirement), do the following.

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

The inner translate() removes any valid character from @MenuText, leaving only the invalid ones. These are fed to the outer translate(), which now can remove all invalid chars from the @MenuText, whatever they might be in this instance. Only the valid chars remain.

You can make a function out of it:

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

and call it like this:

<xsl:attribute name="id">
  <xsl:call-template name="HtmlIdFromString">
    <xsl:with-param name="input" select="@MenuText" />
  </xsl:call-template>
</xsl:attribute>
獨角戲 2024-08-24 17:50:32

使用

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

复制所有现有属性。

Replace() 函数仅在 xslt 2.0 中受支持,但我发现 此解决方法适用于 xslt 1.0。

Use

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

to copy all existing attributes.

The replace() function is only supported in xslt 2.0 but i found this workaround for xslt 1.0.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文