XSLT:如何两次使用文本节点?一次带空格,另一次不带空格?

3
我使用这个模板来生成一个内部链接列表,该列表包含在xHTML文档中通过"id='{title}'"引用的各个部分。
<xsl:template match="folder/folder" mode="folderlist">
    <li>[<a href="#{title}"><xsl:value-of select="title" /></a>]</li>
</xsl:template>

它能够工作,但是当然不能通过验证,因为“title”的内容可能包含空格,而规则指出“id”不能有空格。

假设{title}的内容为:“带有空格的标题”。

我想要实现的是从{title}的内容中移除空格,仅将其插入到href =中,使结果看起来像这样:

<a href="Titlewithspaces">

然后以某种方式再次使用{title}的原始内容,使得完整的结果行变成:

<li>[<a href="#Titlewithspaces">Title with spaces</a>]</li>

这是有可能的吗?如果是这样,能否告诉我如何实现?谢谢。
3个回答

2

一般的解决方案(适用于XPath 1.0和XPath 2.0,分别对应XSLT 1.0和XSLT 2.0),当我们想要将任何非字母数字字符替换为下划线时:

<a href="#{translate(., translate(.,$vAlphaNum,''), '_')}">

变量vAlphaNum被定义为包含所有字母(A-Z和a-z)和所有数字(0-9)的字符串。

这是所谓的“双重翻译法”,最初由@Michael Kay提出。


好的,目前这个可以工作: <xsl:variable name="vAlphaNum">&#x20;&#x9;&#xD;&#xA;0123456789+,</xsl:variable> <li>[<a href="#{translate(title, $vAlphaNum, '')}"><xsl:value-of select="title" /></a>]</li>我该如何创建变量'vAlphaNum',使用反映此模式的正则表达式 匹配模式:[A-Za-z][A-Za-z0-9:_.-](意味着只允许这些字符,所有其他字符都将被删除)? - snahl
@snahl:你只需要阅读并理解我的答案,然后将其应用于字符串的“尾部”,同时单独测试字符串起始字符的要求。如果你正在使用XSLT 2.0,请了解XPath 2.0中的正则表达式。 - Dimitre Novatchev
终于我明白了你的答案,是你以前的一个帖子:链接。现在它可以工作了,非常感谢。现在是最后一点。最后的干净字符串可能包含数字,但开头字符必须是ASCII字母字符 [A-Za-z][A-Za-z0-9:_.-]。由于我没有使用XSLT 2.0,是否有办法在XSLT 1.0中应用这个规则?(或者我应该把它作为一个新问题来提出?) - snahl
@snahl:使用:contains($vLegal1stChars, substring($vYourString,1,1))。我的答案有用吗? - Dimitre Novatchev
是的,你的回答非常有帮助。你可以在这里检查最终结果:[链接](http://tiny.cc/kpyrd)。 (请不要介意当前显示数据的状态,它将在下一步中得到纠正)。由于原始模板在几次迭代中构建了'<li>',直到在模板的最后才用'</li>'标签关闭,所以我遇到了一些应用'contains'的问题。显然,'choose'函数需要关闭标签。因此,我不得不加倍一些代码。我仍然需要学习很多。你的提示非常有帮助,帮助我实现了我的目标,非常感谢。 - snahl

1

您可以使用translate()函数:

    translate(title, '&#x20;&#x9;&#xD;&#xA;', '')

将其应用于您的示例模板:

<xsl:template match="folder/folder" mode="folderlist">
    <li>[<a href="#{translate(title, '&#x20;&#x9;&#xD;&#xA;', '')}">
    <xsl:value-of select="title" /></a>]</li>
</xsl:template>

谢谢,你的回复帮助我找到了函数:replace(string,pattern,replace)。哪一个更合适?不过,仍然想找到完整 XSLT 代码的正确语法。 - snahl
empo和@MadsHansen:我理解你们两个的建议,但我不知道如何将数据放入“href”标记中 - 我卡住了。 - snahl
1
将其放入属性值模板中,其中您当前正在引用“title”。我已更新我们的答案以显示如何应用它。 - Mads Hansen
@snahi,“replace()”是XPath 2.0 / XSLT 2.0函数。 - Emiliano Poggi

1
你可以使用normalize-space()函数来去除首尾空格,并将任何重复的空格字符折叠成一个,然后使用translate()函数将剩余的空格替换为空。
translate(normalize-space(title),' ',''))

将其应用于您的示例模板:

<xsl:template match="folder/folder" mode="folderlist">
    <li>[<a href="#{translate(normalize-space(title),' ','')}">
    <xsl:value-of select="title" /></a>]</li>
</xsl:template>

太好了,删除右括号后它就可以工作了:{translate(normalize-space(title),' ','')}。下一步是像@DimitreNovatchev建议的那样删除特殊字符。谢谢。 - snahl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接