Essentially I want do this in XSL:
<xsl:include href="_domains/{$domain}/templates/header.xsl" />
But I can't seem to use a variable ($domain) in the include. Any suggestions on a work around?
Essentially I want do this in XSL:
<xsl:include href="_domains/{$domain}/templates/header.xsl" />
But I can't seem to use a variable ($domain) in the include. Any suggestions on a work around?
xsl:import
and xsl:include
are resolved at compile time, and do not support runtime expansion.
Except, if you are using XSLT 2.0, you can use conditional inclusion with use-when
, if you have an expression that can be evaluated in a static context.
With the addition of static parameters, it is now possible to conditionally include in XSLT 3.0. Static parameters can be used in the use-when
attribute of the xsl:include
.
Now we can declare parameters with default values of false()
and then override the ones we need at run time...
<xsl:param name="someparam" as="xs:boolean" select="false()"
static="yes" required="no"/>
<xsl:include href="include_me.xsl" use-when="$someparam"/>
Here is a full working example tested with Saxon-HE v9.7 (also tested with Saxon-PE 9.5).
XML Input (test.xml)
<doc>
<foo/>
</doc>
Main 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>
First possible included 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>
Second possible included 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>
Command line (setting inc2
to true)
java -cp "saxon9he.jar" net.sf.saxon.Transform -s:"test.xml" -xsl:"test_main.xsl" inc2="true"
Output
<doc>
<foo>INCLUDE FILE 2!!!</foo>
</doc>
Here's another example, using the above files (except main.xsl), that is more like the original question where part of the path is a variable. Note the _href
which is a shadow attribute.
Main 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>
As explained by @lavinio, in XSLT 2.0 the use-when
attribute may be used to allow a certain degree of "compile-time" inclusion of an xslt instruction, however this is only limited to testing conditions that can can be determined from values in the static context and from these dynamic context values: current date and time, and implicit time zone.
Another approach is to load the XSLT stylesheet (as an XML document) at runtime and before initiating the transformation to dynamically set the href
attribute of any desired <xsl:include>
and/or <xsl:import>
instructions.
This technique is used by the XPath Visualizer to dynamically change the XSLT stylesheet that then evaluates the user-specified XPath expression and formats the XML document with all selected and visible nodes -- highlighted.
Another solution is to load an XML file and transform it by a set of rules (this file could even be a simple XSLT variant).
<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>
© 2022 - 2024 — McMap. All rights reserved.