<?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="XSLTC Native API Documentation">

  <s2 title="XSLTC Compiler API">

    <p>XSLTC's native API is represented by the
    <code>org.apache.xalan.xsltc.compiler.XSLTC</code> class. Any application
    using XSLTC's native API should only have to access methods in this class
    in order to compile a stylesheet (or a set or stylesheets) into one or
    more Java classes. The <code>XSLTC</code> has an empty constructor. The
    class needs to be initialized before each compilation by a call to:</p>
<source>
    public void init();
</source>

    <s3 title="Compile methods">
    <p>There is a set of methods for compiling one or more stylesheets into a
    set of Java classes. The stylesheet can be specified either as a
    <code>URL</code>, <code>InputStream</code>, <code>InputSource</code> or
    a <code>Vector</code> containing a set of <code>URL</code>s pointing to
    stylesheets:</p><source>
    public boolean compile(URL url);
    public boolean compile(URL url, String transletName);
    public boolean compile(InputStream stream, String transletName);
    public boolean compile(InputSource input, String transletName);
    public boolean compile(Vector stylesheets);</source>

    <p>The default behaviour is to output the compiled Java class(es) to one or
    more Java classes in the current working directory. The name of the main
    translet class will be obtained from (in order of priority):</p>

    <ul>
      <li>that specified in the <code>compile()</code> method</li>
      <li>if none is specified (if the parameter is 'null') the name will be
      generated from the filename specified by the input URL/file/stream</li>
      <li>the default translet name (set by <code>setClassName()</code>)</li>
      <li>the built-in default class name <code>&quot;GregorSamsa&quot;</code></li>
    </ul>

    <p>Additional Java classes will be generated for complex stylesheets. These
    classes represent elements such as predicates, sort-records, etc. in the
    stylesheet. Additional classes share the same root name as the main translet
    class, with a suffix containing a '$'-sign and a sequence number. The result
    of a single compilation of a complex stylesheet could be:</p><source>
    GregorSamsa.java
    GregorSamsa$0.java
    GregorSamsa$1.java
    GregorSamsa$2.java
    GregorSamsa$3.java</source>

    <p>It is not always desireable having these classes dumped to files in the
    current working directory. There is one <code>compile()</code> method that
    will return the Java class definitions as bytecodes. The bytecodes are
    returned in a two-dimmensional <code>byte</code> array. Each byte-array
    contains the bytecodes for one Java class:</p><source>
    public byte[][] compile(String name, InputSource input);</source>

    <p>Alternatively, one can first compile the stylesheet into one or more
    Java class files, and then also retrieve the bytecodes from the compiler:</p><source>
    public byte[][] getBytecodes();</source>

    </s3>

    <s3 title="Output settings">

    <p>The default (root) name for the generated Java classes can be set and
    retrieved by calls to these methods:</p><source>
    public void setClassName(String className);
    public String getClassName();</source>

    <p>One can also specify a package to place the classes in:</p><source>
    public void setPackageName(String package);</source>

    <p>The generated classes can also be wrapped inside a single Java archive
    (JAR-file):</p><source>
    public void setJarFileName(String jarFileName);
    public String getJarFileName();</source>

    <p>The result file(s) need not be output in the current working directory.
    Specify the directory to output to by calling:</p><source>
    public boolean setDestDirectory(String directory);</source>

    </s3>

    <anchor name="document-locator"/>
    <s3 title="Input document locator interface">

    <p>XSLTC's compiler has an interface that a client application can implement
    to provide XSL input from alternative sources. Implementing and using this
    interface is necessary when the top-level stylesheet contains one or more
    <code>&lt;xsl:include&gt;</code> and <code>&lt;xsl:import&gt;</code>
    elements that reference stylesheets that cannot be read using standard
    <code>File</code> or <code>URL</code> classes. The interface that a client
    must implement is <code>org.apache.xalan.xsltc.compiler.SourceLoader</code>,
    and its only method is:</p><source>
    public InputSource loadSource(String href, String context, XSLTC xsltc);</source>

    <p>The compiler class, <code>XSLTC</code>, has a method for specifying the
    implementation of this interface:</p><source>
    public void setSourceLoader(SourceLoader loader);</source>

    <p>This interface shares the same purpose as the <code>URIResolver</code>
    interface in the JAXP/TrAX API.</p>

    </s3>

    <s3 title="Debug settings">

    <p>XSLTC can be forced to output debug messages and stack dumps:</p><source>
    public void setDebug(boolean debug);
    public boolean debug();</source>

    </s3>

    <s3 title="Error handling">

    <p>All <code>compile()</code> methods return 'true' if the compilation
    succeeded. The compiler could in such case still generate warning messages.
    These message could be retrieved a <code>Vector</code> of strings or
    output directlry to stderr:</p><source>
    public Vector getWarnings();
    public void printWarnings();</source>

    <p>All <code>compile()</code> methods will return 'false' if any serious
    errors prevented the compiler from generating any Java classes. Error
    messages are handled similar to warning messages:</p><source>
    public Vector getErrors();
    public void printErrors();</source>

    <p>Note that warning messages are not returned/output by these two methods.
    A client application should pass both warning  and error messages
    to its user.</p>

    </s3>

  </s2>

  <s2 title="XSLTC Transform API">

    <p>The steps described in this chapter are covered in these sample
    source code files:</p>

    <ul>
      <li><code>org.apache.xalan.xsltc.cmdline.Transform</code></li>
      <li><code>xml-xalan/java/samples/CompiledApplet/TransformApplet.java</code></li>
      <li><code>xml-xalan/java/samples/CompiledBrazil/TransformHandler.java</code></li>
      <li><code>xml-xalan/java/samples/CompiledEJB/TransformBean.java</code></li>
      <li><code>xml-xalan/java/samples/CompiledEJB/TransformHome.java</code></li>
      <li><code>xml-xalan/java/samples/CompiledEJB/TransformRemote.java</code></li>
      <li><code>xml-xalan/java/samples/CompiledEJB/TransformServlet.java</code></li>
      <li><code>xml-xalan/java/samples/CompiledServlet/CompileServlet.java</code></li>
      <li><code>xml-xalan/java/samples/CompiledServlet/TransformServlet.java</code></li>
    </ul>

    <s3 title="Transformation input handling">

    <p>The main input document must be parsed using a SAX handler. The main SAX
    events (<code>ContentHandler</code>) and lexical declarations
    (<code>LexicalHandler</code>) are handled by the internal DOM builder.
    The classes that make up the internal DOM are:</p><source>
    org.apache.xalan.xsltc.DOM;             - DOM interface
    org.apache.xalan.xsltc.dom.DOMImpl;     - DOM implementation
    org.apache.xalan.xsltc.dom.DOMAdapter;  - DOM-to-translet mapper
    org.apache.xalan.xsltc.dom.MultiDOM;    - DOM multiplexer
    org.apache.xalan.xsltc.dom.DOMBuilder;  - DOM builder interface</source>

    <p>The <code>DOMBuilder</code> interface is a wrapper for the standard SAX
    <code>ContentHandler</code> and <code>LexicalHandler</code> interfaces.
    The <code>DOMBuilder</code> contains both these interfaces, and it is
    implemented by an inner class of the <code>DOMImpl</code> class. To build
    the internal DOM, one has to go through these steps:</p><source>
    // Create a SAX parser and get the XMLReader object it uses
    final SAXParserFactory factory = SAXParserFactory.newInstance();
    try {
	factory.setFeature(Constants.NAMESPACE_FEATURE,true);
    }
    catch (Exception e) {
	factory.setNamespaceAware(true);
    }
    final SAXParser parser = factory.newSAXParser();
    final XMLReader reader = parser.getXMLReader();

     // Set the DOM's DOM builder as the XMLReader's SAX2 ContentHandler
    final DOMImpl dom = new DOMImpl();
    DOMBuilder builder = dom.getBuilder();
    reader.setContentHandler(builder);

     // Set the DOM's DOM builder as the XMLReader's SAX2 LexicalHandler
    try {
	String prop = "http://xml.org/sax/properties/lexical-handler";
	reader.setProperty(prop, builder);
    }
    catch (SAXException e) {
	 // Can be quitely ignored...
    }

     // Pass the document URI or file-name to the DOM
    dom.setDocumentURI(uri);
     // Parse the input document to populate the DOM
    reader.parse(uri);</source>

    <p>The input XML document may contain of reference a DTD. A DTD must be
    processed by XSLTC in order to support the <code>id()</code> and
    <code>unparsed-entity-uri()</code> functions.
    The <code>org.apache.xalan.xsltc.dom.DTDMonitor</code> class can handle
    DTD declarations and aggregate them for use by a translet. Create your
    <code>DTDMonitor</code> instance by passing it a reference to your SAX
    parser:</p><source>
     // Create a DTD monitor and pass it to the XMLReader object
    final DTDMonitor dtd = new DTDMonitor(reader);</source>

    <p>This call ensures that an index is built for all <code>ID</code>
    attributes described in the DTD:</p><source>
     // If there are any elements with ID attributes, build an index
    dtd.buildIdIndex(dom, 0, _translet);</source>

    <p>And this call ensures that the translet is passed all unparsed entities
    described in the DTD:</p><source>
    translet.setDTDMonitor(dtd);</source>

    <p>We'll tell you how to create the translet instance in the next section.</p>

    </s3>

    <s3 title="The translet instance">

    <p>All compiled translets inherit from the <code>AbstractTranslet</code>
    class, so it is safe to cast your tranlet instance to that class:</p><source>
    Class transletClass = Class.forName(transletName);
    AbstractTranslet translet = (AbstractTranslet)transletClass.newInstance();</source>

    <p>Note that the translet  instance  is not reusable, so you would
    benefit from keeping the reference to the translet class.</p>

    <p>Once you have your translet instance you can start playing around with
    it. First you want to pass parameters to it:</p><source>
    // Pass global parameters
    translet.addParameter("my-param", "my-value");</source>

    <p>You also want to remember to pass your DTD handler to the translet.
    (See previous section.)</p>

    </s3>

    <s3 title="Preparing the output handler">

    <p>The compiled translet does not contain all the functionality needed to
    format the output document. This is handled by our output post-processor
    <code>org.apache.xalan.xsltc.runtime.TextOutput</code>. This class needs
    to be instanciated with three parameters; a SAX <code>ContentHandler</code>,
    a <code>LexicalHandler</code> and a string containing the desired output
    encoding. The user should normally provide the two handlers, and the
    output encoding can be obtained from a field in the translet:</p><source>
    // Get the output encoding (from any &lt;xsl:output&gt; element
    String encoding = translet._encoding;

    // Create a translet output handler and plug in the SAX handlers
    TextOutput textOutput = new TextOutput(myContentHandler, myLexicalHandlere, encoding);</source>
    </s3>

    <s3 title="Transformation">

    <p>With the internal DOM built, the DTD monitor in place, and the output
    handler set up, we're ready to run the actual transformation:</p><source>
    // Transform and pass output to the translet output handler
    translet.transform(dom, textOutput);</source>
 
    </s3>

    <s3 title="The DOM cache interface">

    <p>Parsing the input document and building the internal DOM is a fairly
    expensive operation, and it is often desireable to build a cache holding
    frequently accessed internal DOMs. An application using XSLTC's native
    API can accomplish this by implementing the
    <code>org.apache.xalan.xsltc.DOMCache</code> interface. The application will
    still have to call the translet's <code>transform()</code> method with a
    DOM from the cache. But, the translet may have to load additional documents
    if the original stylesheet contained calls to the <code>document()</code>
    function. The translet can be instructed to read DOMs from a cache by
    calling this method:</p><source>
    public void setDOMCache(DOMCache cache);
    public DOMCache getDOMCache();</source>

    </s3>

  </s2>

</s1>
