<?xml version="1.0" standalone="no"?>
<!DOCTYPE s1 SYSTEM "../../style/dtd/document.dtd">
<!-- 
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, Sun
 * Microsystems., http://www.sun.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 -->
  <s1 title="&lt;xsl:include&gt; / &lt;xsl:import&gt;">

  <s2 title="Contents">
  <ul>
    <li><link anchor="functionality">Functionality</link></li>
    <li><link anchor="implementation">Implementation</link></li>    
  </ul>
  </s2>

  <anchor name="functionality"/>
  <s2 title="Functionality">

    <p><code>&lt;xsl:include&gt;</code> allows you to include one stylesheet
    into another. The includ<em>ed</em> stylesheet's templates will have the same
    default priorities and import precedence as the includ<em>ing</em> stylesheet.
    <code>&lt;xsl:import&gt;</code> offers the same, but the import precedence
    of elements in an import<em>ed</em> stylesheet is always less than that of
    the import<em>ing</em> stylesheet.</p>
   
  </s2>

  <anchor name="implementation"/>
  <s2 title="Implementation">
 
    <anchor name="include"/>
    <s3 title="&lt;xsl:include&gt;">

    <p>This is the simplest case, so we will look at that first. The algorithm
    for including another stylesheet is roughly:</p>

    <ul>
      <li>get the including stylesheet from the XSLT parser</li>
      <li>get the value of the "href" attribute from the
        <code>&lt;xsl:include&gt;</code> element and check for circular
        includes/imports</li>
      <li>check if there is a defined <code>SourceLoader</code> set either
        through the native or the TrAX API</li>
      <li>get an <code>InputSource</code> for the document to include, either
        from the <code>SourceLoader</code> or from the document's URI</li>
      <li>parse the input document using the compiler's XSLT parser</li>
      <li>set the import precedence of the included stylesheet to the same as
        the import precedence of the including stylesheet</li>
      <li>get the top-level stylesheet from the XSLT parser</li>
      <li>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)</li>
    </ul>
 
    </s3>    

    <anchor name="import"/>
    <s3 title="&lt;xsl:import&gt;">

    <p>This is very similar to <code>&lt;xsl:include&gt;</code>, but import
    precedence has to be handled differently. Looking at the code you'll find
    this fragment:</p><source>
    // Handle precedence for the including stylesheet
    final int currPrecedence = parser.getCurrentImportPrecedence();
    final int nextPrecedence = parser.getNextImportPrecedence();
    _imported.setImportPrecedence(currPrecedence);
    context.setImportPrecedence(nextPrecedence);</source>

    <p>The important thing here is that the imported stylesheet has import
    precedence <em>less</em> 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
    <code>Stylesheet</code> class has a method
    <code>setImportPrecedence()</code> 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:</p><source>
    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() &lt; 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);
	}
    }</source>

    <p>This method has been carefully cluttered together, and it works, and it
    should not be touched.</p>

    </s3>

    <anchor name="apply-imports"/>
    <s3 title="&lt;xsl:apply-imports&gt;">

    </s3>

  </s2>

</s1>
