<?xml version="1.0" standalone="no"?>
<!DOCTYPE s1 SYSTEM "../../style/dtd/document.dtd">
<!-- 
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2001-2003 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>
