问题是您的链接创建模板做错了事。
正确的做法是使用标识模板<li>
并为元素的文本节点后代创建专用模板。
试试这个:
<xsl:variable
name="keywords"
select="document('../../documents/main/keywords.xml')/keywords/keyword"
/>
<!-- the identity template does copies of everything not matched otherwise -->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<!-- text nodes in <li> elements get special treatment -->
<xsl:template match="li//text()">
<xsl:call-template name="markup">
<xsl:with-param name="phrases" select="$keywords"/>
<xsl:with-param name="first-only" select="false()"/>
</xsl:call-template>
</xsl:template>
<!-- marks up the current node -->
<xsl:template name="markup">
<xsl:with-param name="phrases" />
<xsl:with-param name="first-only" select="true()" />
<!-- you can use . here - no need to pass in a $text param -->
</xsl:template>
身份模板是成功解决此类问题的关键。它透明地处理复制<li>
和。<b>
- 它对输入进行完全遍历,复制它,除非更具体的模板与当前节点匹配。
- 这意味着您只需为要更改的节点编写模板。在这种情况下,匹配文本节点效果最好,因为它们不能有嵌套的子节点。
- 避免命名模板,如
<xsl:template name="List">
. 这是“推式”XSLT,即它是必要的,并且经常导致相当笨拙的结果。
- 将节点从流中
<xsl:template match="li//text()">
拉出并做一些比复制它们更复杂的事情。这是“拉式”XSLT,即模板匹配。它通常更容易处理并生成更清晰的 XSLT 代码。
- 当然,您不受限于
<li>
元素内的文本节点。只需更改匹配表达式以影响其他节点。
假设您想在不破坏任何其他模板的情况下将所有<b>
节点转换为。<strong>
使用拉式风格,这很简单:
<xsl:template match="b">
<strong>
<xsl:apply-templates select="node() | @*" />
<strong>
</xsl:template>
另请注意,当您这样做时,当前节点不会更改<xsl:call-template>
。因此不需要将当前节点传递给被调用的模板。