我四处搜寻找到解决问题的方法,但我还有更多问题......
考虑以下XML:
<dynamicStuff>
<dyn id="name1">...</dyn>
<dyn id="name2">...</dyn>
<dyn id="name3">...</dyn>
<dyn id="name4">...</dyn>
</dynamicStuff>
并假设我有一个XSLT文件,如下所示:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="name1">
...
</xsl:template>
<xsl:template name="name2">
...
</xsl:template>
<xsl:template name="name3">
...
</xsl:template>
<xsl:template name="name4">
...
</xsl:template>
</xsl:stylesheet>
我想要做的是从SECOND XSLT文件动态确定要调用哪个模板,如下所示:
<xsl:variable name="templateName">
<xsl:value-of select="dyn/@id"/>
</xsl:variable>
<xsl:call-template name="$templateName"/>
可悲的是它不起作用,相信我,当我说我尝试过很多不同的东西时,虽然听起来很简单但它也不起作用......
我错过了什么吗?
修改
我已成功完成以下任务:
<xsl:template name="staticName">
<xsl:param name="id" />
<xsl:if test="$id = 'name1'">....</xsl:if>
<xsl:if test="$id = 'name2'">....</xsl:if>
...
</xsl:template>
以这种方式打电话:
<xsl:call-template name="staticName">
<xsl:with-param name="id" select="@id"/>
</xsl:call-template>
Needles说这有多么不方便......首先我的代码将被绑定到那个staticName(想象我需要在十几个文件中调用这个)...第二我会有一堆(联合国)相同的模板内部相关的内容,当它可能更加分离......一个噩梦升级系统uu
它做我想要的但不是我需要的方式......
提前感谢您对此事的任何启示!
答案 0 :(得分:6)
来自http://www.w3.org/TR/xslt#named-templates
name
属性的值是a QName, 如图所示进行扩展 [2.4 Qualified Names]。
这意味着既不是表达也不是AVT。
显式xsl:call-template
指令可以通过逻辑指令或模式匹配来完成,如:
<xsl:template match="dyn[@id='name1']" mode="dynamic">
<xsl:call-template name="name1"/>
</xsl:template>
另一种方法是命名模板引用...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="vTemplate" select="document('')/*/xsl:template"/>
<xsl:template match="dyn">
<xsl:apply-templates select="$vTemplate[@name = current()/@id]"/>
</xsl:template>
<xsl:template match="xsl:template[@name='name1']"
name="name1"> one </xsl:template>
<xsl:template match="xsl:template[@name='name2']"
name="name2"> two </xsl:template>
<xsl:template match="xsl:template[@name='name3']"
name="name3"> three </xsl:template>
<xsl:template match="xsl:template[@name='name4']"
name="name4"> four </xsl:template>
</xsl:stylesheet>
输出:
one two three four
<小时/> 注意:因为此技术使用
document('')
来处理XSLT而不是原始XML文件,所以正在处理的原始文档在命名模板中不可用。但是,如果需要,您可以将current()
作为参数显式传递给模板:
<xsl:template match="dyn">
<xsl:apply-templates select="$vTemplate[@name = current()/@id]">
<xsl:with-param name="current" select="current()"/>
</xsl:apply-templates>
</xsl:template>
如果需要,$current
可用于访问原始文档:
<xsl:template match="xsl:template[@name='name1']" name="name1">
<xsl:param name="current"/>
<xsl:value-of select="$current/@id"/>
<xsl:text> becomes one</xsl:text>
</xsl:template>
如果需要,可以使用$current
将for-each
重新建立为当前节点:
<xsl:template match="xsl:template[@name='name2']" name="name2">
<xsl:param name="current"/>
<xsl:for-each select="$current">
<xsl:value-of select="@id"/>
<xsl:text> becomes two</xsl:text>
</xsl:for-each>
</xsl:template>
答案 1 :(得分:1)
如果您只有有限数量的可能模板,是否可以使用xsl if构造来选择在主模板中执行的操作?
<xsl:if test="$templateName = 'name1'">
<xsl:call-template name="name1"/>
</xsl:if>
答案 2 :(得分:1)
通常当有人试图这样做时,这意味着他们并不知道xsl:apply-templates的全部功能。在XSLT中进行动态调度的方法是使用xsl:apply-templates。例如,对于引用的问题,请编写模板规则,例如
<xsl:template match="dyn[@id='name1']">...</xsl:template>
<xsl:template match="dyn[@id='name2']">...</xsl:template>
<xsl:template match="dyn[@id='name3']">...</xsl:template>
然后使用<xsl:apply-templates select="dyn"/>
进行发货。
答案 3 :(得分:0)
您尝试的内容不是直接可行的,但为什么不首先简单地匹配id
属性的值?如果您绝对需要间接调用模板,请从匹配id
的模板中调用它(请参阅下面的name4
):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<t><xsl:apply-templates select="dynamicStuff/dyn"/></t>
</xsl:template>
<!-- match on attribute value -->
<xsl:template match="dyn[@id='name1']">name1</xsl:template>
<xsl:template match="dyn[@id='name2']">name2</xsl:template>
<xsl:template match="dyn[@id='name3']">name3</xsl:template>
<xsl:template match="dyn[@id='name4']">
<xsl:call-template name="name4"/>
</xsl:template>
<!-- named templates -->
<xsl:template name="name1">name1</xsl:template>
<xsl:template name="name2">name2</xsl:template>
<xsl:template name="name3">name3</xsl:template>
<xsl:template name="name4">name4</xsl:template>
</xsl:stylesheet>
输入:
<dynamicStuff>
<dyn id="name1">...</dyn>
<dyn id="name2">...</dyn>
<dyn id="name3">...</dyn>
<dyn id="name4">...</dyn>
</dynamicStuff>
输出:
<t>name1name2name3name4</t>
答案 4 :(得分:0)
如果您使用旧的Saxon-B或更新的Saxon-PE或Saxon-EE作为XSLT处理器,您可以使用saxon扩展来实现动态模板调用:
<xsl:variable name="templateName">
<xsl:value-of select="dyn/@id"/>
</xsl:variable>
<saxon:call-template name="{$templateName}"/>
不要忘记在xsl-stylesheet元素中声明saxon-Namespace:
<xsl:stylesheet xmlns:saxon="http://saxon.sf.net/" [...] >