提问人:Andrew G. Johnson 提问时间:4/15/2011 更新时间:11/20/2023 访问量:4469
如何在路径名中将 xsl:import 与变量一起使用?
How can I use xsl:import with a variable in the path name?
问:
从本质上讲,我想在XSL中执行此操作:
<xsl:include href="_domains/{$domain}/templates/header.xsl" />
但我似乎不能在包含中使用变量 ($domain)。关于解决方法的任何建议?
答:
xsl:import
并在编译时解析,并且不支持运行时扩展。xsl:include
但是,如果您使用的是 XSLT 2.0,那么如果有一个可以在静态上下文中计算的表达式,则可以将条件包含与 一起使用。use-when
评论
正如 @lavinio 所解释的,在 XSLT 2.0 中,use-when
属性可用于允许在一定程度上“编译时”包含 XSLT 指令,但这仅限于测试条件,这些条件可以从静态上下文中的值和这些动态上下文值(当前日期和时间以及隐式时区)中确定。
另一种方法是在运行时加载 XSLT 样式表(作为 XML 文档),然后再启动转换,以动态设置任何所需和/或指令的属性。href
<xsl:include>
<xsl:import>
XPath 可视化工具使用此技术来动态更改 XSLT 样式表,然后计算用户指定的 XPath 表达式,并使用突出显示所有选定和可见节点来设置 XML 文档的格式。
通过添加静态参数,现在可以有条件地包含在 XSLT 3.0 中。静态参数可以在 的属性中使用。use-when
xsl:include
现在,我们可以声明默认值为 的参数,然后覆盖我们在运行时需要的参数......false()
<xsl:param name="someparam" as="xs:boolean" select="false()"
static="yes" required="no"/>
<xsl:include href="include_me.xsl" use-when="$someparam"/>
这是使用 Saxon-HE v9.7 测试的完整工作示例(也使用 Saxon-PE 9.5 测试)。
XML 输入 (test.xml)
<doc>
<foo/>
</doc>
主 XSLT 3.0 (test_main.xsl)
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="inc1" as="xs:boolean" select="false()"
static="yes" required="no"/>
<xsl:param name="inc2" as="xs:boolean" select="false()"
static="yes" required="no"/>
<xsl:include href="test_inc1.xsl" use-when="$inc1"/>
<xsl:include href="test_inc2.xsl" use-when="$inc2"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
第一个可能包含的 XSLT 3.0 (test_inc1.xsl)
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="foo">
<xsl:copy>INCLUDE FILE 1!!!</xsl:copy>
</xsl:template>
</xsl:stylesheet>
第二个可能的包括 XSLT 3.0 (test_inc2.xsl)
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="foo">
<xsl:copy>INCLUDE FILE 2!!!</xsl:copy>
</xsl:template>
</xsl:stylesheet>
命令行(设置为 true)inc2
java -cp "saxon9he.jar" net.sf.saxon.Transform -s:"test.xml" -xsl:"test_main.xsl" inc2="true"
输出
<doc>
<foo>INCLUDE FILE 2!!!</foo>
</doc>
这是另一个示例,使用上述文件(main.xsl 除外),这更像是原始问题,其中部分路径是变量。请注意 which 是 shadow 属性。_href
主 XSLT 3.0
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="inc_number" as="xs:string" select="'1'" static="yes" required="no"/>
<xsl:include _href="test_inc{$inc_number}.xsl"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
另一种解决方案是加载一个 XML 文件,并通过一组规则对其进行转换(此文件甚至可以是一个简单的 XSLT 变体)。
<xsl:param name="domain">_default</xsl:param>
<xsl:variable name="header-template"
select="document( concat('_domains/', $domain, '/templates/header.xml' ) )" />
<xsl:template name="header">
<xsl:apply-templates mode="transform" select="$header-template"/>
</xsl:template>
评论