如何根据变量调用命名模板?

Pau*_*tos 14 xslt fxsl

我不知道是否可能,但我想知道该怎么做......

假设我们有以下XSL:

<xsl:template name="foo">
  Bla bla bla
</xsl:template>
...
<xsl:template name="bar">
  Bla bla bla
</xsl:template>
...
<xsl:template match="/">
  <xsl:if test="$templateName='foo'">
    <xsl:call-template name="foo"/>
  </xsl:if>
  <xsl:if test="$templateName='bar'">
    <xsl:call-template name="bar"/>
  </xsl:if>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

是否可以将XSL更改为类似......

<xsl:template match="/">
  <xsl:call-template name="$templateName"/>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

Pav*_*aev 12

这与您描述的完全不可能,但如果您希望能够根据您在其他地方设置的某个值在运行时选择模板,那么就有一个技巧可以做到.我们的想法是让您的命名模板也以不同的模式匹配具有相应名称的节点(这样它不会弄乱您的正常转换),然后匹配.例如:

<xsl:stylesheet ... xmlns:t="urn:templates">

  <!-- Any compliant XSLT processor must allow and ignore any elements 
       not from XSLT namespace that are immediate children of root element -->
  <t:templates>
    <t:foo/>
    <t:bar/>
  </t:templates>

  <!-- document('') is the executing XSLT stylesheet -->     
  <xsl:variable name="templates" select="document('')//t:templates" />

  <xsl:template name="foo" match="t:foo" mode="call-template">
    Bla bla bla
  </xsl:template>

  <xsl:template name="bar" match="t:foo" mode="call-template">
    Bla bla bla
  </xsl:template>

  <xsl:template match="/">
    <xsl:variable name="template-name" select="..." />
    <xsl:apply-templates select="$templates/t:*[local-name() = $template-name]"
                         mode="call-template"/>
  </xsl:template>
Run Code Online (Sandbox Code Playgroud)

请注意,您可以使用<xsl:with-param>in <xsl:apply-templates>,因此您可以使用plain来执行所有操作<xsl:call-template>.

此外,上面的代码比您可能需要的更长,因为它试图避免使用任何XSLT扩展.如果您的处理器支持exslt:node-set(),那么您可以直接使用生成节点<xsl:element>,并使用node-set()将生成的树片段转换为普通节点以进行匹配,而无需进行document('')黑客攻击.

有关更多信息,请参阅FXSL - 它是基于此概念的XSLT函数式编程库.


Tom*_*lak 6

不,这是不可能的,不可能直接实现.调用约定是:

<xsl:call-template name="QName" />
Run Code Online (Sandbox Code Playgroud)

QName的定义为:

QName ::= PrefixedName | UnprefixedName

PrefixedName   ::= Prefix ':' LocalPart
UnprefixedName ::= LocalPart

Prefix         ::= NCName
LocalPart      ::= NCName
Run Code Online (Sandbox Code Playgroud)

基本上这归结为"只有字符,没有表达".正如其他答案所强调的那样,实际上有一些方法可以做同等的事情,但直截了当的方法/天真的方法是行不通的.