如何调用基于变量命名模板?(How to call named templates based on

2019-06-28 01:48发布

我不知道这是否是可能的,但我不知道该怎么办呢?

比方说,我们有以下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>

是否有可能改变XSL阅读类似...

<xsl:template match="/">
  <xsl:call-template name="$templateName"/>
</xsl:template>

Answer 1:

不,这是不可能的不能直接成为可能。 调用约定是:

<xsl:call-template name="QName" />

凡QName的定义为 :

QName ::= PrefixedName | UnprefixedName

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

Prefix         ::= NCName
LocalPart      ::= NCName

这基本上可以归结为“只有文字,没有任何表情。” 至于其他的答案突出, 事实上的方式做事情相当的,但直接的方法/幼稚的做法是行不通的。



Answer 2:

这是不可能完全按照你的描述,但如果你希望能够选择在根据您设置其他地方的一些值运行时的模板,还有一招做到这一点。 这个想法是让你命名模板也处于不同的模式匹配相应名称的节点(这样不会弄乱你的正常转化),再搭配上。 例如:

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

请注意,您可以使用<xsl:with-param><xsl:apply-templates> ,这样你就可以做这个的一切,你可以用一个简单的做<xsl:call-template>

另外,上面的代码是有点冗长的可能比你需要的,因为它试图避免使用任何XSLT扩展。 如果您的处理器支持exslt:node-set()则可以只生成的节点是使用直接<xsl:element> ,并使用node-set()到所得到的树片段转换为纯节点来匹配,而不需要对于document('')黑客。

欲了解更多信息,请参阅FXSL -这对XSLT的功能编程库,是基于这样的理念。



Answer 3:

对于任何人的将来参考:

这是基于帕维尔Minaev的回答工作的例子。 没有原以为我的一部分。 ;-)我切换它MSXML使用:节点设置为他描述(或多或少),使得它在.NET。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0">
    <xsl:variable name="templates">
        <templates>
            <foo />
            <bar />
        </templates>
    </xsl:variable>
    <xsl:template name="foo" match="foo" mode="call-template">
        <FooElement />
    </xsl:template>
    <xsl:template name="bar" match="bar" mode="call-template">
        <BarElement />
    </xsl:template>
    <xsl:template match="/">
        <Root>
            <xsl:variable name="template-name">bar</xsl:variable> <!-- Change this to foo to get the other template. -->
            <xsl:apply-templates select="msxsl:node-set($templates)/*/*[local-name() = $template-name]" mode="call-template" />
        </Root>
    </xsl:template>
</xsl:stylesheet>


Answer 4:

更新 :下面的链接进行了更新,使其指向web.archive.org -不幸的是,IDEAlliance的取得了所有Exteme标记语言会议记录不可用......在适当的时候,我会发现这两篇文章一个更永久的地方。


这是在实施FXSL

还有的FXSL的主要原则很好的解释。

请参阅以下两篇文章:

在(对XSLT 1.0),(PDF) 使用FXSL库在XSLT函数编程 ”:

http://web.archive.org/web/20070710091236/http://www.idealliance.org/papers/extreme/proceedings/xslfo-pdf/2003/Novatchev01/EML2003Novatchev01.pdf

(HTML)在:

http://conferences.idealliance.org/extreme/html/2003/Novatchev01/EML2003Novatchev01.html



(PDF)“ 用XSLT 2.0和FXSL高阶函数编程 ”上:

http://web.archive.org/web/20070222111927/http://www.idealliance.org/papers/extreme/proceedings/xslfo-pdf/2006/Novatchev01/EML2006Novatchev01.pdf

(HTML)在: http://conferences.idealliance.org/extreme/html/2006/Novatchev01/EML2006Novatchev01.html



使用FXSL我已经能够解决轻松优雅的诸多问题,即“为XSLT不可能”看起来。 人们可以找到很多的例子在这里



Answer 5:

我觉得我有更多或更少同样的问题你。 我有一个“外”的模板,并希望根据一些变量集在运行时调用不同的“内部”的模板。 我用谷歌搜索的方式有一个动态的发现你的问题<xsl:call-template> 我解决它利用<xsl:apply-templates>代替,如下所述。

输入XML(在运行时生成的)包含的线沿线的东西:

<template name="template_name_1"/>

在“外”模板中的XSL有:

<xsl:apply-templates select="template"/>

(该select="template"在本申请的模板是指<template>在输入XML标签)

最后是“内部”模板,我想包括作为价值的结果name在我的XML属性,是这样的:

<xsl:template match="template[@name='template_name_1']">
    <!-- XSL / XHTML goes here -->
</xsl:template>

(同样, match="template[@name='xyz']"指的是先前select="template"和反过来到<template>标签及其name在输入XML属性)

这样,我可以简单地从我的XML输入控制的动态“称为”模板。

这可能是不一样的问题,因为你正在试图解决,但我认为这是相当比这个页面上的其他地方提到FSXL解决方案紧密,并且要简单得多。



Answer 6:

这个如何?:

  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

      <xsl:template match="xsl:template[@name='foo']" name="foo">
    Bla bla bla foo
      </xsl:template>

      <xsl:template match="xsl:template[@name='bar']" name="bar">
    Bla bla bla bar
      </xsl:template>

      <xsl:template match="/">
        <xsl:variable name="templateName" select="'bar'"/>
        <xsl:apply-templates select="document('')/*/xsl:template[@name=$templateName]"/>
        <xsl:apply-templates select="document('')/*/xsl:template[@name='foo']"/>
      </xsl:template>

    </xsl:stylesheet>

您可以简化,如前面描述的贡献使用一个变量类似模板的“来电”:

<xsl:variable name="templates" select="document('')/*/xsl:template"/> 

<xsl:apply-templates select="$templates[@name=$templateName]"/>
<xsl:apply-templates select="$templates[@name='foo']"/>

注意,可选<xsl:with-param>可以照常使用。



文章来源: How to call named templates based on a variable?
标签: xslt fxsl