<xsl:include> / <xsl:import>
Contents
Functionality
<xsl:include>
allows you to include one stylesheet
into another. The included stylesheet's templates will have the same
default priorities and import precedence as the including stylesheet.
<xsl:import>
offers the same, but the import precedence
of elements in an imported stylesheet is always less than that of
the importing stylesheet.
Implementation
<xsl:include>
This is the simplest case, so we will look at that first. The algorithm for including another stylesheet is roughly:
- get the including stylesheet from the XSLT parser
- get the value of the "href" attribute from the
<xsl:include>
element and check for circular includes/imports - check if there is a defined
SourceLoader
set either through the native or the TrAX API - get an
InputSource
for the document to include, either from theSourceLoader
or from the document's URI - parse the input document using the compiler's XSLT parser
- set the import precedence of the included stylesheet to the same as the import precedence of the including stylesheet
- get the top-level stylesheet from the XSLT parser
- move all variables, parameters, and top-level elements (include templates) from the included stylesheet to the top-level stylesheet (all elements will keep their import precedence even after being moved to the top-level stylesheet)
<xsl:import>
This is very similar to <xsl:include>
, but import
precedence has to be handled differently. Looking at the code you'll find
this fragment:
// Handle precedence for the including stylesheet final int currPrecedence = parser.getCurrentImportPrecedence(); final int nextPrecedence = parser.getNextImportPrecedence(); _imported.setImportPrecedence(currPrecedence); context.setImportPrecedence(nextPrecedence);
The important thing here is that the imported stylesheet has import
precedence less than the importing stylesheet. So the imported
stylesheet gets the current import precedence, while the current stylesheet
gets the next available (unused) import precedence. The
Stylesheet
class has a method
setImportPrecedence()
that ensures that the import precedence
is set not only for the stylesheet itself, but that it is also propagated
down to any included/imported stylesheets:
public void setImportPrecedence(final int precedence) { // Set import precedence for this stylesheet _importPrecedence = precedence; // Set import precedence for all included stylesheets final Enumeration elements = elements(); while (elements.hasMoreElements()) { SyntaxTreeNode child = (SyntaxTreeNode)elements.nextElement(); if (child instanceof Include) { Stylesheet included = ((Include)child).getIncludedStylesheet(); if (included != null) included.setImportPrecedence(precedence); } } // Set import precedence for the stylesheet that imported this one if (_importedFrom != null) { if (_importedFrom.getImportPrecedence() < precedence) { final Parser parser = getParser(); final int nextPrecedence = parser.getNextImportPrecedence(); _importedFrom.setImportPrecedence(nextPrecedence); } } // Set import precedence for the stylesheet that included this one else if (_includedFrom != null) { if (_includedFrom.getImportPrecedence() != precedence) _includedFrom.setImportPrecedence(precedence); } }
This method has been carefully cluttered together, and it works, and it should not be touched.