如何在xsl生成的节点上使用xsl:apply-templates?

时间:2013-02-06 23:11:53

标签: xslt apply-templates

我有一个像这样的xml:

<span reference="1">Reference Text 1</span>
<term reference="2">Reference Text 2</term>

我需要它成为这个:

<span class="referenceText">Reference Text 1</span> <a href="1">[1]</a>
<i>Reference Text 2</i> <a href="2">[2]</a>

因此,基本上,如果具有reference属性的元素是一个范围,我们只需保留原样,添加class="referenceText"。但是,如果它是任何其他元素,那么我们还应该应用为此元素创建的模板。这就是<term>成为<i>的原因 - 我有一个模板:

<xsl:template match="term">
  <i><xsl:apply-templates select="@* |node()"/></i>
</xsl:template>

对于具有reference属性的所有元素的转换,我有这个模板:

<xsl:template match="*[@reference]">

  <xsl:param name="href" select="./@reference"/>

  <xsl:choose>
    <xsl:when test="name() = 'span'">
      <span class="referenceText">
        <xsl:value-of select="."/>
      </span>
    </xsl:when>
    <xsl:otherwise>
      <xsl:element name="{name()}">
        <xsl:value-of select="."/>
      </xsl:element>
    </xsl:otherwise>
  </xsl:choose>

  <xsl:text> </xsl:text><a href="#{$href}">[<xsl:value-of select="./@href"/>]</a>

</xsl:template>

不幸的是,这导致以下输出:

<span class="referenceText">Reference Text 1</span> <a href="1">[1]</a>
<term>Reference Text 2</term> <a href="2">[2]</a>

因此,<term>未转换为<i>。看起来我需要某种递归来重新应用模板到生成的内容,但我无法想出任何东西。

1 个答案:

答案 0 :(得分:2)

如果您正在使用XSLT 1.0,则可以捕获变量中的输出,然后使用exslt:node-set函数将模板应用于变量。尽量避免无限递归:)

<xsl:variable name="foo">
...
</xsl:variable>
<xsl:apply-templates select="exslt:node-set($foo)"/>

编辑:纳入与此答案相关的其他评论)

为了使用EXSLT扩展,第一步是声明其命名空间。 EXSLT项目网站建议您在<xsl:stylesheet>节点上执行此操作:

  

使用EXSLT中描述的扩展的第一步是为EXSLT模块定义相关的命名空间。您应该在样式表中的xsl:stylesheet元素上声明命名空间。

<xsl:stylesheet xmlns:exslt="http://exslt.org/common">
  //...
</xsl:stylesheet>

此外,extension-element-prefixes属性可用于防止扩展名称空间被添加到结果文档中:

<xsl:stylesheet xmlns:exslt="http://exslt.org/common" extension-element-prefixes="exslt">
  //...
</xsl:stylesheet>