Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use xsl:import with a variable in the path name?

Tags:

xslt

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?

like image 831
Andrew G. Johnson Avatar asked Apr 14 '11 20:04

Andrew G. Johnson


3 Answers

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.

like image 192
lavinio Avatar answered Oct 14 '22 09:10

lavinio


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.

like image 41
Dimitre Novatchev Avatar answered Oct 14 '22 10:10

Dimitre Novatchev


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>
like image 44
Daniel Haley Avatar answered Oct 14 '22 09:10

Daniel Haley