Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically include other XSL files in XSLT

I have a small problem, is there a way to dynamically include another xsl? For example:

<xsl:variable name="PathToWeb" select="'wewe'"/>
<xsl:include href="http://{$PathToWeb}/html/xsl/head.xsl" />
<xsl:include href="http://{$PathToWeb}/html/xsl/navigation.xsl" />
<xsl:include href="http://{$PathToWeb}/html/xsl/promo.xsl" />
<xsl:include href="http://{$PathToWeb}/html/xsl/3columns.xsl" />

<xsl:include href="http://{$PathToWeb}/html/xsl/footer.xsl" />
like image 994
Master345 Avatar asked Oct 29 '11 15:10

Master345


People also ask

How do I import one XSLT to another?

Remarks. An XSLT file can import another XSLT file using an <xsl:import> element. Importing an XSLT file is the same as including it except that definitions and template rules in the importing file take precedence over those in the imported XSLT file.

Is XSL and XSLT the same?

XSLT is designed to be used as part of XSL. In addition to XSLT, XSL includes an XML vocabulary for specifying formatting. XSL specifies the styling of an XML document by using XSLT to describe how the document is transformed into another XML document that uses the formatting vocabulary.

What does node () do in XSLT?

XSLT current() Function Usually the current node and the context node are the same. However, there is one difference. Look at the following XPath expression: "catalog/cd". This expression selects the <catalog> child nodes of the current node, and then it selects the <cd> child nodes of the <catalog> nodes.

What is XSL Param In XSLT?

XSLT <xsl:param> The <xsl:param> element is used to declare a local or global parameter. Note: The parameter is global if it's declared as a top-level element, and local if it's declared within a template.


3 Answers

I have solved this problem differently, might be useful for someone who works with Java and XSLT (this solution is specific to people using javax.xml.transform package).

XSLT transformer factory allows setting a custom URI resolver. Say if your XSLT looks like

<?xml version="1.0" encoding="utf-8"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" version="4.0" encoding="UTF-8"/>
    <xsl:include href="import://stackoverflow.com/xsl"/>
    ...

The URI resolver's resolve method will get import://stackoverflow.com/xsl as a href parameter. import:// could serve as a "special" identifier scheme for custom includes, so you can detect it and create/return javax.xml.transform.Source which is pointing to the necessary file. For example:

TransformerFactory tf = TransformerFactory.newInstance();
URIResolver delegate = tf.getURIResolver();
tf.setURIResolver( new CustomURIResolver( delegate ) );

Then, inside CustomURIResolver:

  public Source resolve( String href, String base )
    throws TransformerException {
    Source result = null;
    URI uri = null;

    try {
      uri = new URI( href );
    }
    catch( Exception e ) {
      throw new TransformerException( e );
    }

    // The XSLT file has a URI path that allows for a file to be included
    // dynamically.
    if( "import".equalsIgnoreCase( uri.getScheme() ) &&
        "stackoverflow.com".equalsIgnoreCase( uri.getAuthority() ) ) {
      result = openTemplate();
    }
    else {
      result = getDelegate().resolve( href, base );
    }

    return result;
  }

Add an openTemplate() method that includes the logic to dynamically determine the XSL file to open.

like image 77
mindas Avatar answered Sep 30 '22 10:09

mindas


I have a small problem, is there a way to dynamically include another xsl? For example:

<xsl:variable name="PathToWeb" select="'wewe'"/> 
<xsl:include href="http://{$PathToWeb}/html/xsl/head.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/navigation.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/promo.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/3columns.xsl" /> 

<xsl:include href="http://{$PathToWeb}/html/xsl/footer.xsl" />

It is illegal to have a variable reference in the href attribute of <xsl:include>. According to the W3C XSLT 1.0 and XSLT 2.0 specifications, the value of this attribute must be an URI reference.

However, if the value of the $PathToWeb variable is known before the start of the transformation, it can be used in a number of ways to produce dynamically a stylesheet representation in which the <xsl:include> statements above contain the desires URIs (after substituting the reference to $PathToWeb with the required value:

  1. Generate a new stylesheet from the current one, using XSLT.

  2. Load the stylesheet as an XmlDocument object. Then locate the respective <xsl:include> elements and set their href attributes to the desired values. Finally, invoke the transformation using the so modified XmlDocument that represents the stylesheet.

Method 2. has been used for 11 years in the XPath Visualizer to dynamically set the exact value of a select attribute used to select all nodes that a user-entered XPath expression selects and to generate an HTML document representing the XML document with all selected and visible nodes highlighted.

like image 26
Dimitre Novatchev Avatar answered Sep 30 '22 12:09

Dimitre Novatchev


You cannot do this. The reasons are simple :

XSL will first expand the xsl:include during compilation, before it does anything else. At that point your "variable" is not know and cannot be known and you can't change the compiled transform once it compiles. In addition the href is a Uniform Resource Locator not an XPath expression, therefore you can't just expand a variable in it.

like image 28
FailedDev Avatar answered Sep 30 '22 10:09

FailedDev