You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by dl...@apache.org on 2001/05/04 22:20:47 UTC

cvs commit: xml-xalan/java/xdocs/sources/xsltc DOMInterface.gif DOMLocking.gif all_namespaces.gif cast_expression.gif compiler_AST.gif compiler_DOM.gif compiler_architecture.gif dom_namespace1.gif dom_namespace2.gif dom_namespace3.gif index.xml key_relations.gif match_namespace1.gif match_namespace2.gif namespace_stack.gif output_namespaces1.gif output_namespaces2.gif pattern_objects.gif runtime_architecture.gif runtime_type_mapping.gif sort_objects.gif type_mapping.gif type_mappings.gif typecast.gif xsl_comment_design.xml xsl_key_design.xml xsl_lang_design.xml xsl_sort_design.xml xsl_unparsed_design.xml xsl_whitespace_design.xml xsltc_compiler.xml xsltc_dom.xml xsltc_namespace.xml xsltc_runtime.xml xsltover.xml

dleslie     01/05/04 13:20:47

  Added:       java/xdocs/sources/xsltc DOMInterface.gif DOMLocking.gif
                        all_namespaces.gif cast_expression.gif
                        compiler_AST.gif compiler_DOM.gif
                        compiler_architecture.gif dom_namespace1.gif
                        dom_namespace2.gif dom_namespace3.gif index.xml
                        key_relations.gif match_namespace1.gif
                        match_namespace2.gif namespace_stack.gif
                        output_namespaces1.gif output_namespaces2.gif
                        pattern_objects.gif runtime_architecture.gif
                        runtime_type_mapping.gif sort_objects.gif
                        type_mapping.gif type_mappings.gif typecast.gif
                        xsl_comment_design.xml xsl_key_design.xml
                        xsl_lang_design.xml xsl_sort_design.xml
                        xsl_unparsed_design.xml xsl_whitespace_design.xml
                        xsltc_compiler.xml xsltc_dom.xml
                        xsltc_namespace.xml xsltc_runtime.xml xsltover.xml
  Log:
  Transformed Morten Jorgensen's XSLTC design documents
  to XML.
  Adding to repository with accompanying .gif files.
  
  Revision  Changes    Path
  1.1                  xml-xalan/java/xdocs/sources/xsltc/DOMInterface.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/DOMLocking.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/all_namespaces.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/cast_expression.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/compiler_AST.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/compiler_DOM.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/compiler_architecture.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/dom_namespace1.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/dom_namespace2.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/dom_namespace3.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/index.xml
  
  Index: index.xml
  ===================================================================
  <?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="Introduction to XSLTC">
      <p><ref>Design documents by <jump href="mailto:morten@xml.apache.org">Morten J&oslash;rgensen</jump> 
      - updated 06.03.2001</ref></p>
  <ul>
    <li><link anchor="compiler">Compiler design</link></li>
    <li><link anchor="runtime">Runtime library/DOM design</link></li>  
  </ul>
  <anchor name="compiler"/>
   <s2 title="Compiler design">
    <p><link idref="xsltc_compiler"><img src="compiler_architecture.gif" alt="compiler_architecture.gif"/></link></p>
    <p><ref>Figure 1: Compiler architecture overview</ref></p>
    <p>Click on the picture to jump to the overall design document for the compiler.</p>
      <p>Each XSL element/function and XPath expression/pattern is represented by
    its own class in the Abstract Syntax Tree (AST). Some of these classes have
    their own design documents (I am working on the rest of them):</p>
      <s3 title="XSL elements">
          <ul>
            <li>
              <link idref="xsl_whitespace_design">&lt;xsl:preserve-space&gt;/&lt;xsl:strip-space&gt;</link>
            </li>
            <li>
              <link idref="xsl_sort_design">&lt;xsl:sort&gt;</link>
            </li>
            <li>
              <link idref="xsl_key_design">&lt;xsl:key&gt;</link>
            </li>
            <li>
              <link idref="xsl_comment_design">&lt;xsl:comment&gt;/&lt;xsl:message&gt;</link>
            </li>
          </ul>
          </s3>
          <s3 title="XSL functions">
          <ul>
            <li>
              <link idref="xsl_key_design">key()</link>
            </li>
            <li>
              <link idref="xsl_lang_design">lang()</link>
            </li>
            <li>
              <link idref="xsl_unparsed_design">unparsed-entity-uri()</link>
            </li>
          </ul>
    </s3>
    </s2><anchor name="runtime"/>
    <s2 title="Runtime library/DOM design">
    <p><link idref="xsltc_runtime"><img src="runtime_architecture.gif" alt="runtime_architecture.gif"/></link></p>
    <p><ref>Figure 2: Runtime library architecture overview</ref></p>
    <p>Click on the picture to jump to the overall design document for the XSLTC
    runtime library. This document describes the structure of the compiled
    translet as well as the translet runtime library.</p> 
    <p>The <link idref="xsltc_dom">Internal DOM</link> describes the components and structure of the internal DOM,
     support for DOM2 navigation, the DOM adapter, DOM multiplexer, and DOM builder.</p>
      <p><link idref="xsltc_namespace">Namespaces</link> explains how XSLTC (including the compiler) handles
       namespaces.</p>   
    </s2>
  </s1>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/key_relations.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/match_namespace1.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/match_namespace2.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/namespace_stack.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/output_namespaces1.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/output_namespaces2.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/pattern_objects.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/runtime_architecture.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/runtime_type_mapping.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/sort_objects.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/type_mapping.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/type_mappings.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/typecast.gif
  
  	<<Binary file>>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/xsl_comment_design.xml
  
  Index: xsl_comment_design.xml
  ===================================================================
  <?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:comment&gt; / &lt;xsl:message&gt;">
    <ul>
    <li><link anchor="functionality">Functionality</link></li>
    <li><link anchor="implementation">Implementation</link></li>  
    </ul>
  <anchor name="functionality"/>
  <s2 title="Functionality">
  
    <p>The <code>&lt;xsl:comment&gt;</code> element is used to insert XML comments
    into the result document. The comment is inserted as follows in the XSL
    stylesheet:</p>
  
    <source>    &lt;element&gt;
        &lt;xsl:comment&gt;This is a comment!&lt;/xsl:comment&gt;
      &lt;/element&gt;</source>
  
    <p>and it will be output in the result document as follows:</p>
  
    <source>    &lt;element&gt;
        &lt;!-- This is a comment! --&gt;
      &lt;/element&gt;</source>
  
    <p>The <code>&lt;xsl:message&gt;</code> element is used to send messages to
    who/whatever is performing the transformation. The message can be displayed
    in a terminal, a dialog box, etc. The  <code>&lt;xsl:message&gt;</code> element
    is used in the same way as the <code>&lt;xsl:comment&gt;</code> element,
    however the message is <em>not</em> output in the result document.</p>
  
    <p>The <code>&lt;xsl:message&gt;</code> element has an attribute
    <code>"terminate"</code> which can be used to terminate the transformation at any
    given stage. This is useful when using message to give information about
    illegal values in the input document.</p>
  </s2><anchor name="implementation"/>
  <s2 title="Implementation">
  
    <p>The output handler class has a method for outputting comments in the
    output document and messages to the operator. The code compiled for a
    comment gathers all text that goes into the comment in a StringValueHandler
    object, retrieves the full text string from this handler, and then finally
    sends it to the output handler. Similarly the code compiled for a message
    will simply send the message to the output handler in use.</p>
  
    <p>Messages will be output to the terminal (stdout) when a transformation
    is run in a terminal. The message will be output before the beginning of the
    output document. Messages will be shown in a dialog box if a transformation
    is run in an applet.</p>
  
    <p><code>&lt;xsl:message&gt;</code> elements that use the <code>"terminate"</code>
    attribute to abort transformations cause an exception to be thrown. A
    RuntimeException is used for this, and the exception text is:</p>
    <p><code>Termination forced by an xsl:message instruction</code></p>
    </s2>
  </s1>  
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/xsl_key_design.xml
  
  Index: xsl_key_design.xml
  ===================================================================
  <?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:key&gt; / key() / KeyPattern">
    <ul>
      <li><link anchor="functionality">Functionality</link></li>
      <li><link anchor="implementation">Implementation</link></li>    
    </ul>
    <anchor name="functionality"/>
    <s2 title="Functionality">
  
    <p>The <code>&lt;xsl:key&gt;</code> element is a top-level element that can be
    used to define a named index of nodes from the source XML tree(s). The
    element has three attributes:</p>
  
    <ul>
      <li>
        <code>name</code> - the name of the index
      </li>
      <li>
        <code>match</code> - a pattern that defines the nodeset we want
        indexed
      </li>
      <li>
        <code>use</code> - an expression that defines the value to be used
        as the index key value.
      </li>
    </ul>
  
    <p>A named index can be accessed using either the <code>key()</code> function or
    a KeyPattern. Both these methods address the index using its defined name
    (the "name" attribute above) and a parameter defining one or more lookup
    values for the index. The function or pattern returns a node set containing
    all nodes in the index whose key value match the parameter's value(s):</p>
  
    <source>
      &lt;xsl:key name="book-author" match="book" use="author"/&gt;
      :
      :
      &lt;xsl:for-each select="key('book-author', 'Mikhail Bulgakov')"&gt;
        &lt;xsl:value-of select="author"/&gt;
        &lt;xsl:text&gt;: &lt;/xsl:text&gt;
        &lt;xsl:value-of select="author"/&gt;
        &lt;xsl:text&gt;&amp;#xa;&lt;/xsl:text&gt;
      &lt;/xsl:for-each&gt;
    </source>
  
    <p>The KeyPattern can be used within an index definition to create unions
    and intersections of node sets:</p>
  
  <source>
      &lt;xsl:key name="cultcies" match="farmer | fisherman" use="name"/&gt;
  </source>
  
    <p>This could of course be done using regular <code>&lt;xsl:for-each&gt;</code>
    and <code>&lt;xsl:select&gt;</code> elements. However, if your stylesheet
    accesses the same selection of nodes over and over again, the transformation
    will be much more efficient using pre-indexed keys as shown above.</p>
   </s2><anchor name="implementation"/>
   <s2 title="Implementation">
  
    <p>AbstractTranslet has a global hashtable that holds an index for each named
    key in the stylesheet (hashing on the "name" attribute of xsl:key).
    AbstractTranslet has a couple of public methods for inserting and retrieving
    data from this hashtable:</p>
  
  <source>
      public void buildKeyIndex(String name, int nodeID, String value);
      public KeyIndex KeyIndex getKeyIndex(String name);
  </source>
  
    <p>The Key class compiles code that traverses the input DOM and extracts
    nodes that match some given parameters (the <code>"match"</code> attribute of the
    <code>&lt;xsl:key&gt;</code> element). A new element is inserted into the named
    key's index. The nodes' DOM index and the value translated from the 
    <code>"use"</code> attribute of the <code>&lt;xsl:key&gt;</code> element are stored
    in the new entry in the index.</p>
  
    <p>The index itself is implemented in the <code>KeyIndex</code> class.
    The index has an hashtable with all the values from the matching nodes (the
    part of the node used to generate this value is the one specified in the
    <code>"use"</code> attribute). For every matching value there is a Vector
    holding a list of all node indexes for which this value gives a match:</p>
  
    <p><img src="key_relations.gif" alt="key_relations.gif"/></p>
    <p><ref>Figure 1: Indexing tables</ref></p>
  
    <p>The <code>KeyIndex</code> class implements the <code>NodeIterator</code>
    interface, so that it can be returned directly by the implementation of the
    <code>key()</code> function. This is how the index generated by
    <code>&lt;xsl:key&gt;</code> and the node-set returned by the <code>key()</code> and
    KeyPattern are tied together. You can see how this is done in the
    <code>translate()</code> method of the <code>KeyCall</code> class.</p>
  
    <p>The <code>key()</code> function can be called in two ways:</p>
  
  <source>
      key('key-name','value')
      key('key-name','node-set')
  </source>
  
    <p>The first parameter is always the name of the key. We use this value to
    lookup our index from the _keyIndexes hashtable in AbstractTranslet:</p>
  
  <source>
      il.append(classGen.aloadThis());
      _name.translate(classGen, methodGen);
      il.append(new INVOKEVIRTUAL(getKeyIndex));
  </source>
  
    <p>This compiles into a call to
    <code>AbstractTranslet.getKeyIndex(String name)</code>, and it leaves a
    <code>KeyIndex</code> object on the stack. What we then need to do it to
    initialise the <code>KeyIndex</code> to give us nodes with the requested value.
    This is done by leaving the <code>KeyIndex</code> object on the stack and pushing
    the <code>"value"</code> parameter to <code>key()</code>, before calling
    <code>lookup()</code> on the index:</p>
  
  <source>
      il.append(DUP);  // duplicate the KeyIndex obejct before return
      _value.translate(classGen, methodGen);
      il.append(new INVOKEVIRTUAL(lookup));
  </source>
  
    <p>This compiles into a call to <code>KeyIndex.lookup(String value)</code>. This
    will initialise the <code>KeyIndex</code> object to return nodes that match the
    given value, so the <code>KeyIndex</code> object can be left on the stack when
    we return. This because the <code>KeyIndex</code> object implements the
    <code>NodeIterator</code> interface.</p>
  
    <p>This matter is a bit more complex when the second parameter of
    <code>key()</code> is a node-set. In this case we need to traverse the nodes in
    the set and do a lookup for each node in the set. What I do is this:</p>
  
    <ul>
      <li>
        construct a <code>KeyIndex</code> object that will hold the return node-set
      </li>
      <li>
        find the named <code>KeyIndex</code> object from the hashtable in
        AbstractTranslet
      </li>
      <li>
        get an iterator for the node-set and do the folowing loop:</li>
        <ul>
          <li>get string value for current node</li>
          <li>do lookup in KeyIndex object for the named index</li>
          <li>merge the resulting node-set into the return node-set</li>
        </ul>
      <li>
        leave the return node-set on stack when done
      </li>
    </ul>
  
    <p>The only work that remains is to update the <code>merge()</code> method of
    the <code>KeyIndex</code> class so that it eliminates duplicate nodes in the
    resulting node-set.</p>
    </s2>
  </s1>
  
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/xsl_lang_design.xml
  
  Index: xsl_lang_design.xml
  ===================================================================
  <?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="lang() function">
    <ul>
      <li><link anchor="functionality">Functionality</link></li>
      <li><link anchor="implementation">Implementation</link></li>    
    </ul>
    <anchor name="functionality"/>
    <s2 title="Functionality">
  
    <p>The <code>xml:lang</code> can be used to determine the language for a node or
    a node-set. The attribute can be used to store language-specific data in an
    XML document:</p>
  
    <source>
      &lt;phrases&gt;
        &lt;greeting xml:lang="en"&gt;Hello!&lt;/greeting&gt;
        &lt;greeting xml:lang="no"&gt;Hei!&lt;/greeting&gt;
        &lt;greeting xml:lang="fr"&gt;Salut!&lt;/greeting&gt;
        &lt;greeting xml:lang="es"&gt;Hola!&lt;/greeting&gt;
        &lt;greeting xml:lang="de"&gt;Sweinhund!&lt;/greeting&gt;
      &lt;/phrases&gt;
    </source>
  
    <p>The XSL stylesheet can use the <code>lang()</code> function to select the
    element with the desired language:</p>
  
    <source>
      &lt;xsl:template match="greeting"&gt;
        &lt;xsl:if test="lang("de")&gt;
          &lt;xsl:value-of select="."/&gt;
          &lt;xsl:text&gt; Grossglucklicher wunche!&lt;/xsl:text&gt;
        &lt;/xsl:if&gt;
      &lt;/xsl:template&gt;
    </source>
  </s2> <anchor name="implementation"/>
  <s2 title="Implementation">
  
    <p>The DOM interface has been given a method that returns the language for
    a given node. The language is returned as a string (on whatever format is
    used in the XML document - should be iso), and may be null if no language is
    defined.</p>
  
    <source>
      public String DOM.getLanguage(int node);
    </source>
  
    <p>The BasisLibrary class has a static method that will compare the language
    of the context node with some other language and return the result as a
    boolean.</p>
  
    <source>
      public static boolean BasisLibrary.testLanguage(String language, DOM dom, int node);
    </source>
  
    <p>The compiled code for the <code>lang()</code> method calls this method in the
    BasisLibrary and leaves the result on the stack for the calling element.</p>
    </s2>
  </s1>
  
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/xsl_sort_design.xml
  
  Index: xsl_sort_design.xml
  ===================================================================
  <?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:sort&gt;">
    <ul>
      <li><link anchor="functionality">Functionality</link></li>
      <li><link anchor="sort-class">The Sort class</link></li>
      <li><link anchor="sortingiterator-class">The SortingIterator class</link></li>
      <li><link anchor="nodesortrecord-class">The NodeSortRecord class</link></li>    
      <li><link anchor="nodesortrecordfactory-class">The NodeSortRecordFactory class</link></li>
    </ul>
    
    <anchor name="functionality"/>
    <s2 title="Functionality">
  
    <p>The <code>&lt;xsl:sort&gt;</code> element is used to define a sort key which
    specifies the order in which nodes selected by either
    <code>&lt;xsl:apply-templates&gt;</code> or <code>&lt;xsl:for-each&gt;</code> are
    processed. The nodes can be sorted either in numerical or alphabetic order,
    and the alphabetic order may vary depeinding on the language in use. The
    nodes can be sorted either in ascending or descending order.</p>
  
    </s2><anchor name="sort-class"/>
    <s2 title="The Sort class">
  
    <p>Static methods of the Sort class is responsible for generating the
    necessary code for invoking SortingIterators under
    <code>&lt;xsl:apply-templates&gt;</code> and <code>&lt;xsl:for-each&gt;</code>
    elements. Both these elements can have several <code>&lt;xsl:sort&gt;</code>
    child nodes defining primary, secondary, teriary, etc. keys. The code for
    <code>&lt;xsl:apply-templates&gt;</code> and <code>&lt;xsl:for-each&gt;</code>
    create  vectors containg a Sort object for each sort key. The object methods
    of the Sort object encapsulate a container for key-specific data (such as the
    sort key itself, sort order, sort type, and such) while the static methods
    take a vector of Sort objects and generate the actual code.</p>
  
    <p>The <code>translate()</code> method of the Sort object is never called. The
    vectors containing the Sort objects for a <code>&lt;xsl:apply-templates&gt;</code>
    or <code>&lt;xsl:for-each&gt;</code> element are instead passed to the static
    <code>translateSortIterator()</code> method. This method compiles code that
    instanciates a SortingIterator object that will pass on a node-set in a
    specific order to the code handling the <code>&lt;xsl:apply-templates&gt;</code>
    or <code>&lt;xsl:for-each&gt;</code> element.</p>
  
    </s2><anchor name="sortingiterator-class"/>
    <s2 title="The SortingIterator class">
  
    <p>The SortingIterator class is responsible for sorting nodes encapsulated in
    sort obects. These sort objects must be of a class inheriting from
    NodeSortRecord, a the SortingIterator object needs a factory object providing
    it with the correct type of objects:</p>
  
    <p><img src="sort_objects.gif" alt="sort_objects.gif"/></p>
    <p><ref>Figure 1: SortingIterator</ref></p>
  
    <p>The SortingIterator class is fairly dumb and leaves much of the work to the
    NodeSortRecord class. The iterator gets the NodeSortRecords from the factory
    object and sorts them using quicksort and calling <code>compareTo()</code> on
    pairs of NodeSortRecord objects.</p>
  
    </s2><anchor name="nodesortrecord-class"/>
    <s2 title="The NodeSortRecord class">
  
    <p>The static methods in the Sort class generates a class inheriting from
    NodeSortRecord, with the following overloaded methods:</p>
  
    <ul>
      <li><em>Class Constructor</em></li>
        <ul><li>The class constructor is overloaded to create sort-key global
        tables, such as an array containing the sort order for all the sort keys
        and another array containg all the sort types. Different sort order/types
        can be specified for the different levels of sort keys, but we assume that
        the same language is used for all levels.</li></ul>
        
      <li><code>extractValueFromDOM(int level)</code></li>
        <ul><li>This method is called by the SortingIterator object to extract the
        value for a specific sort key for a node. The SortingIterator will only
        use this method once and will cache the returned value for later use. The
        method will only be called if absultely necessary.</li></ul>
  
      <li><code>compareType(int level)</code></li>
        <ul><li>This method returns the sort type for one sort key level. Returns
        either <code>COMPARE_STRING</code> or <code>COMPARE_NUMERIC</code>.</li></ul>
      
      <li><code>sortOrder(int level)</code></li>
        <ul><li>This method returns the sort order for one sort key level. Returns
        either <code>COMPARE_ASCENDING</code> or <code>COMPARE_DESCENDING</code></li></ul>
      
      <li><code>getCollator(int level)</code></li>
        <ul><li>This method returns a Collator object for language-specific
        string comparisons. The same Collator is used for all levels of the key.
        </li></ul> 
    </ul>
  
    <p>The <code>compareTo()</code> method of the NodeSortRecord base class deserves
    a bit of attention. It takes its own node (from the this pointer) and another
    node and compares, if necessary, the values for all sort keys:</p>
  
    <source>
      /**
       * Compare this sort element to another. The first level is checked first,
       * and we proceed to the next level only if the first level keys are
       * identical (and so the key values may not even be extracted from the DOM)
       */
      public int compareTo(NodeSortRecord other) {
  	int cmp;
      
  	for (int level=0; level&lt;_levels; level++) {
  	    
  	    // Compare the two nodes either as numeric or text values
  	    if (compareType(level) == COMPARE_NUMERIC) {
  		final Double our = numericValue(level);
  		final Double their = other.numericValue(level);
  		if (our == null) return(-1);
  		if (their == null) return(1);
  		cmp = our.compareTo(their);
  	    }
  	    else {
  		String our = stringValue(level);
  		String their = other.stringValue(level);
  		if (our == null) return(-1);
  		if (their == null) return(1);
  		cmp = getCollator().compare(our,their);
  	    }
  	    
  	    // Return inverse compare value if inverse sort order
  	    if (cmp != 0) {
  		if (sortOrder(level) == COMPARE_DESCENDING)
  		    return(0 - cmp);
  		else
  		    return(cmp);
  	    }
  	    
  	}
  	return(0);
      }
    </source>
  
    <p>The two methods <code>stringValue(int level)</code> and 
    <code>numericValue(int level)</code> return values for one level of the sort key
    of a node. These methods cache these values after they are first read so that
    the <code>DOM.getNodeValue()</code> is only called once. Also, the algorithm
    used for these two methods assure that <code>DOM.getNodeValue()</code> is only
    called when needed. The value for a node's secondary sort key is never
    retrieved if the node can be uniquely identified by its primary key.</p>
  
    </s2><anchor name="nodesortrecordfactory-class"/>
    <s2 title="The NodeSortRecordFactory class">
  
    <p>After the static methods of the Sort class has generated the new class for
    sort objects it generates code that instanciates a new NodeSortRecordFactory
    object. This object is passed as a parameter to SortingIterators constructor
    and is used by the iterator to generate the necessary sort objects.</p>
  
    </s2>
  </s1>
  
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/xsl_unparsed_design.xml
  
  Index: xsl_unparsed_design.xml
  ===================================================================
  <?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="unparsed-entity-uri()">
    <ul>
      <li><link anchor="functionality">Functionality</link></li>
      <li><link anchor="implementation">Implementation</link></li>
    </ul>
    
    <anchor name="functionality"/>
    <s2 title="Functionality">
  
  
    <p>The <code>unparsed-entity-uri()</code> function gives access to declarations
    of unparsed entities in the DTD of the source document. If the DTD contains
    the declaration:</p>
  
    <source>
      &lt;!ENTITY mom-picture SYSTEM "http://www.home.com/mom.jpg" NDATA JPEG&gt;
    </source>
  
    <p>the expression <code>unparsed-entity-uri('mom-picture')</code> returns an
    URI for the file <code>mom.jpg</code>.</p>
  
    </s2><anchor name="implementation"/>
    <s2 title="Implementation">
  
    <p>Unparsed entities must be gathered from the XML input document at the time
    when the DOM is built. To achieve this our parser must parse the document DTD
    (if any) and store all data of type NDATA (not XML data) in a
    hashtable in the AbstractTranslet object. All the compiled code for this
    function needs to do is call a method in the translet for retrieving the
    value for the requested element:</p>
  
    <source>
      public String AbstractTranslet.getUnparsedEntity(String entityName);
    </source>
  
    <p>The translet will use the supplied <code>entityName</code> to look up the
    value in the hashtable and then leave the string value on the stack for the
    element that called <code>lang()</code>.</p>
    </s2>
  </s1>
  
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/xsl_whitespace_design.xml
  
  Index: xsl_whitespace_design.xml
  ===================================================================
  <?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:strip/preserve-space&gt;">
    <ul>
      <li><link anchor="functionality">Functionality</link></li>
      <li><link anchor="identify">Identifying strippable whitespace nodes</link></li>
      <li><link anchor="which">Determining which nodes to strip</link></li>
      <li><link anchor="strip">Stripping nodes</link></li>
      <li><link anchor="filter">Filtering whitespace nodes</link></li>
    </ul>
    
    <anchor name="functionality"/>
    <s2 title="Functionality">
  
    <p>The <code>&lt;xsl:strip-space&gt;</code> and <code>&lt;xsl:preserve-space&gt;</code>
    elements are used to control the way whitespace nodes in the source XML
    document are handled. These elements have no impact on whitespace in the XSLT
    stylesheet. Both elements can occur only as top-level elements, possible more
    than once, and the elements are always empty</p>
   
    <p>Both elements take one attribute &quot;elements&quot; which contains a
    whitespace separated list of named nodes which should be or preserved
    stripped from the source document. These names can be on one of these three
    formats (NameTest format):</p>
  
    <ul>
      <li>
        All whitespace nodes:
        <code>elements=&quot;*&quot;</code>
      </li>
      <li>
        All whitespace nodes with a namespace:
        <code>elements=&quot;&lt;namespace&gt;:*&quot;</code>
      </li>
      <li>
        Specific whitespace nodes: <code>elements=&quot;&lt;qname&gt;&quot;</code>
      </li>
    </ul>
  
    </s2><anchor name="identify"/>
    <s2 title="Identifying strippable whitespace nodes">
  
    <p>The DOM detects all text nodes and assigns them the type <code>TEXT</code>.
    All text nodes are scanned to detect whitespace-only nodes. A text-node is
    considered a whitespace node only if it consist entirely of characters from
    the set { 0x09, 0x0a, 0x0d, 0x20 }. The DOM implementation class has a static
    method used to detect such nodes:</p>
  
  <source>
      private static final boolean isWhitespaceChar(char c) {
          return c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09;
      }
  </source>
  
    <p>The characters are checked in proable order.</p>
  
    <p> The DOM has a bit-array that is used to  tag text-nodes as strippable
    whitespace nodes:</p>
  
    <source>private int[] _whitespace;</source>
  
    <p>There are two methods in the DOM implementation class for accessing this
    bit-array: <code>markWhitespace(node)</code> and <code>isWhitespace(node)</code>.
    The array is resized together with all other arrays in the DOM by the
    <code>DOM.resizeArrays()</code> method. The bits in the array are set in the
    <code>DOM.maybeCreateTextNode()</code> method. This method must know whether
    the current node is a located under an element with an
    <code>xml:space=&quot;&lt;value&gt;&quot;</code> attribute in the DOM, in which
    case it is not a strippable whitespace node.</p>
  
    <p>An auxillary class, WhitespaceHandler, is used for this purpose. The class
    works in a way as a stack, where you "push" a new strip/preserve setting
    together with the node in which this setting was determined. This means that
    for every time the DOM builder encounters an <code>xml:space</code> attribute
    it will invoke a method on an instance of teh WhitespaceHandler class to
    signal that a new preserve/strip setting has been encountered. This is done
    in the <code>makeAttributeNode()</code> method. The whitespace handler stores the
    new setting and pushes the current element node on its stack. When the
    DOM builder closes up an element (in <code>endElement()</code>), it invokes
    another method of the whitespace handler to check if the strip/preserve
    setting is still valid. If the setting is now invalid (we're closing the
    element whose node id is on the top of the stack) the handler inverts the
    setting and pops the element node id off the stack. The previous
    strip/preserve setting is then valid, and the id of node where this setting
    was defined is on the top of the stack.</p>
  
    </s2><anchor name="which"/>
    <s2 title="Determining which nodes to strip">
  
    <p>A text node is never stripped unless it contains only whitespace
    characters (Unicode characters 0x09, 0x0A, 0x0D and 0x20). Stripping a text
    node means that the node disappears from the DOM; so that it is never
    included in the output and that it is ignored by all functions such as
    <code>count()</code>. A text node is preserved if any of the following apply:</p>
  
    <ul>
      <li>
        the element name of the parent of the text node is in the set of
        elements listed in <code>&lt;xsl:preserve-space&gt;</code>
      </li>
      <li>
        the text node contains at least one non-whitespace character
      </li>
      <li>
        an ancenstor of the whitespace text node has an attribute of
        <code>xsl:space=&quot;preserve&quot;</code>, and no close ancestor has and
        attribute of <code>xsl:space=&quot;default&quot;</code>.
      </li>
    </ul>
  
    <p>Otherwise, the text node is stripped. Initially the set of 
    whitespace-preserving element names contains all element names, so the
    default behaviour is to preserve all whitespace text nodes.</p>
  
    <p>This seems simple enough, but resolving conflicts between matching
    <code>&lt;xsl:strip-space&gt;</code> and <code>&lt;xsl:preserve-space&gt;</code>
    elements requires a lot of thought. Our first consideration is import
    precedence; the match with the highest import precedence is always chosen.
    Import precedence is determined by the order in which the compared elements
    are visited. (In this case those elements are the top-level
    <code>&lt;xsl:strip-space&gt;</code> and <code>&lt;xsl:preserve-space&gt;</code>
    elements.) This example is taken from the XSLT recommendation:</p>
  
    <ul>
      <li>stylesheet A imports stylesheets B and C in that order;</li>
      <li>stylesheet B imports stylesheet D;</li>
      <li>stylesheet C imports stylesheet E.</li>
    </ul>
  
    <p>Then the order of import precedence (lowest first) is D, B, E, C, A.</p>
  
    <p>Our next consideration is the priority of NameTests (XPath spec):</p>
    <ul>
      <li>
        <code>elements=&quot;&lt;qname&gt;&quot;</code> has priority 0
      </li>
      <li>
        <code>elements=&quot;&lt;namespace&gt;:*&quot;</code> has priority -0.25
      </li>
      <li>
        <code>elements=&quot;*&quot;</code> has priority -0.5
      </li>
    </ul>
  
    <p>It is considered an error if the desicion is still ambiguous after this,
    and it is up to the implementors to decide what the apropriate action is.</p>
  
    <p>With all this complexity, the normal usage for these elements is quite
    smiple; either preserve all whitespace nodes but one type:</p>
  
    <source>&lt;xsl:strip-space elements="foo"/&gt;</source>
  
    <p>or strip all whitespace nodes but one type:</p>
  
    <source>
      &lt;xsl:strip-space elements="*"/&gt;
      &lt;xsl:preserve-space elements="foo"/&gt;</source>
  
    </s2><anchor name="strip"/>
    <s2 title="Stripping nodes">
  
    <p>The ultimate goal of our design would be to totally screen all stripped
    nodes from the translet; to either physically remove them from the DOM or to
    make it appear as if they are not there. The first approach will cause
    problems in cases where multiple translets access the same DOM. In the future
    we wish to let translets run within servlets / JSPs with a common DOM cache.
    This DOM cache will keep copies of DOMs in memory to prevent the same XML
    file from being downloaded and parsed several times. This is a scenarios we
    might see:</p>
  
      <p><img src="DOMInterface.gif" alt="DOMInterface.gif"/></p>
      <p><ref>Figure 1: Multiple translets accessing a common pool of DOMs</ref></p>
  
    <p>The three translets running on this host access a common pool of 4 DOMs.
    The DOMs are accessed through a common DOM interface. Translets accessing
    a single DOM will have a DOMAdapter and a single DOMImpl object behind this
    interface, while translets accessing several DOMs will be given a MultiDOM
    and a set of DOMImpl objects.</p>
  
    <p>The translet to the left may want to strip some nodes from the shared DOM
    in the cache, while the other translets may want to preserve all whitespace
    nodes. Our initial thought then is to keep the DOM as it is and somehow
    screen the left-hand translet of all the whitespace nodes it does not want to
    process. There are a few ways in which we can accomplish this:</p>
  
    <ul>
      <li>
        The translet can, prior to starting to traverse the DOM, send a reference
        to the tables containing information on which nodes we want stripped to
        the DOM interface. The DOM interface is the responsible for hiding all
        stripped whitespace nodes from the iterators and the translet. A problem
        with this approach is that we want to omit the DOM interface layer if
        the translet is only accessing a single DOM. The DOM interface layer will
        only be instanciated by the translet if the stylesheet contained a call
        to the <code>document()</code> function.<br/><br/>
      </li>
      <li>
        The translet can provide its iterators with information on which nodes it
        does not want to see. The translet is still shielded from unwanted
        whitespace nodes, but it has the hassle of passing extra information over
        to most iterators it ever instanciates. Note that all iterators do not
        need be aware of whitepspace nodes in this case. If you have a look at
        the figure again you will see that only the first level iterator (that is
        the one closest to the DOM or DOM interface) will have to strip off
        whitespace nodes. But, there may be several iterators that operate
        directly on the DOM ( invoked by code handling XSL functions such as
        <code>count()</code>) and every single one of those will need to be told
        which whitespace nodes the translet does not want to see.<br/><br/>
      </li>
      <li>
        The third approach will take advantage of the fact that not all
        translets will want to strip whitespace nodes. The most effective way of
        removing unwanted whitespace nodes is to do it once and for all, before
        the actual traversal of the DOM starts. This can be done by making a
        clone of the DOM with exlusive-access rights for this translet only. We
        still gain performance from the cache because we do not have to pay the
        cost of the delay caused by downloading and parsing the XML source file.
        The cost we have to pay is the time needed for the actual cloning and the
        extra memory we use.<br/><br/>
        Normally one would imagine the translet (or the wrapper class that
        invokes the translet) calls the DOM cache with just an URL and receives
        a reference to an instanciated DOM. The cache will either have built
        this DOM on-demand or just passed back a reference to an existing tree.
        In this case the DOM would need an extra call that a translet would use
        to clone a DOM, passing the existing DOM reference to the cache and
        recieving a new reference to the cloned DOM. The translet can then do
        whatever it wants with this DOM (the cache need not even keep a reference
        to this tree).
      </li>
    </ul>
    
    <p>We are lucky enough to be able to combine the first two approaches. All
    iterators that directly access the DOM (axis iterators) are instanciated by
    calls to the DOM interface layer (the DOM class). The actual iterators are
    created in the DOM implementation layer (the DOMImpl class). So, we can pass
    references to the preserve/strip whitespace tables to the DOM, and the DOM
    will make sure that all axis iterators return node sets with respect to these
    tables.</p>
    </s2><anchor name="filter"/> 
    <s2 title="Filtering whitespace nodes">
  
    <p>For each axis iterator and for <code>DOM.makeStringValue()</code> and
    <code>DOM.stringValueAux()</code> we must apply a filter for eliminating all
    unwanted whitespace nodes. To achive this we must build a very efficient
    predicate for determining if the current node should be stripped or not. This
    predicate is built by <code>Whitespace.compilePredicate()</code>. This method is
    static and builds a predicate for a vector of WhitespaceRule objects. (The
    WhitespaceRule class is defined within the Whitespace class.) Each
    WhitespaceRule object contains information for a single element listed
    in an <code>&lt;xsl:strip/preserve-space&gt;</code> element, and is broken down
    into the following information:</p>
  
    <ul>
      <li>the namespace (can be the default namespace)</li>
      <li>the element name or "<code>*</code>"</li>
      <li>the type of rule; NS:EL, NS:<code>*</code> or <code>*</code></li>
      <li>the priority of the rule (based on import precedence and type)</li>
      <li>the action; either strip or preserver</li>
    </ul>
  
    <p>The Vector of WhitespaceRules is arranged in order of priority and
    redundant rules are removed. A predicate method is then compiled into the
    translet as:</p>
  
  <source>
      public boolean stripSpace(int node);
  </source>
  
    <p>Unfortunately this method cannot be declared static.</p>
  
    <p>When the Stylesheet objectcompiles the <code>topLevel()</code> method of the
    translet it checks for the existance of the <code>stripSpace()</code> method. If
    this method exists the <code>topLevel()</code> will be compiled to pass the
    translet to the DOM as a StripWhitespaceFilter (the translet implements this
    interface when the <code>stripSpace()</code> method is compiled).</p>
  
    <p>All axis iterators and the <code>DOM.makeStringValue()</code> and
    <code>DOM.stringValueAux()</code> methods check for the existance of this filter
    (it is kept in a global variable in the DOM implementation class) and takes
    the appropriate actions. The methods in the DOM for returning axis iterators
    will place a StrippingIterator on top of the axis iterator if the filter is
    present, and the two methods just mentioned will return empty strings for
    whitespace nodes that should be stripped.</p>
   
    </s2>
  </s1>
  
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/xsltc_compiler.xml
  
  Index: xsltc_compiler.xml
  ===================================================================
  <?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 Compiler Design">
      <ul>  
       <li><link anchor="overview">Compiler Overview</link></li>
       <li><link anchor="ast">Building an Abstract Syntax Tree</link></li>
       <li><link anchor="typecheck">Type-check and Cast Expressions</link></li>
       <li><link anchor="compile">Code generation</link></li>
      </ul>
  
      <anchor name="overview"/>
      <s2 title="Compiler overview">
  
      <p>The input stylesheet is parsed using the SAX 1-based parser from Sun's
      Project X:</p>   
      <ul>
        <li><code>com.sun.xml.parser.Parser</code></li>
      </ul>
  
      <p>This parser builds a DOM from the stylesheet document, and hands this
      DOM over to the compiler. The compiler uses its own specialised parser to
      parse XPath expressions and patterns:</p>
      <ul>
        <li><code>com.sun.xslt.compiler.XPathParser</code></li>
      </ul>
      <p>Both parsers are encapsulates in XSLTC's parser class:</p>
      <ul>
        <li><code>com.sun.xslt.compiler.Parser</code></li>
      </ul>
  
      </s2><anchor name="ast"/>
      <s2 title="Building an Abstract Syntax Tree">
      <ul>
        <li><link anchor="mapping">Mapping stylesheet elements to Java classes</link></li>
        <li><link anchor="domxsl">Building a DOM tree from the input XSL file</link></li>      
      </ul>
      <p>The SAX parser builds a standard W3C DOM from the source stylesheet.
      This DOM does not contain all the information needed to represent the
      whole stylesheet. ( Remember that XSL is two languages; XML and XPath.
      The DOM only covers XML. ) The compiler uses the DOM to build an
      abstract syntax tree (AST) that contains all the nodes from the DOM, plus
      additional nodes for the XPath expressions.</p>
      <anchor name="mapping"/>
      <s3 title="Mapping stylesheets elements to Java classes">
      <p>Each XSL element is represented by a class in the
      <code>com.sun.xslt.compiler</code> package. The Parser class contains a
      Hashtable that that maps XSL instructions to classes that inherit from a
      common parent class 'Instruction' (which again inherits from
      'SyntaxTreeNode'). This mapping is set up in the <code>initClasses()</code> method:</p>
  <source>    private void initStdClasses() {
  	try {
  	    initStdClass("template",    "Template");
  	    initStdClass("param",       "Param");
  	    initStdClass("with-param",  "WithParam");
  	    initStdClass("variable",    "Variable");
  	    initStdClass("output",      "Output");
  	    :
  	    :
  	    :
  	}
      }
  
      private void initClass(String elementName, String className)
  	throws ClassNotFoundException {
  	_classes.put(elementName,
  		     Class.forName(COMPILER_PACKAGE + '.' + className));
      }</source>
      </s3><anchor name="domxsl"/>
      <s3 title="Building a DOM tree from the input XSL file">
      <p>The parser instanciates a DOM that holds the input XSL stylesheet. The
      DOM can only handle XML files and will not break up and identify XPath
      patterns/expressions (these are stored as attributes to the various
      nodes in the tree) or calls to XSL functions(). Each XSL instruction gets
      its own node in the DOM, and the XPath patterns/expressions are stored as
      attributes of these nodes. A stylesheet looking like this:</p>
  <source>
      &lt;xsl:stylesheet .......&gt;
        &lt;xsl:template match="chapter"&gt;
          &lt;xsl:text&gt;Chapter&lt;/xsl:text&gt;
          &lt;xslvalue-of select="."&gt;
        &lt;/xsl:template&gt;
      &lt;/xsl&gt;stylesheet&gt;
  </source>
      <p>will be stored in the DOM as indicated in the following picture:</p>
      <p><img src="compiler_DOM.gif" alt="compiler_DOM.gif"/></p>
      <p><ref>Figure 1: DOM containing XSL stylesheet</ref></p>
      <p>The pattern '<code>match="chapter"</code>' and the expression
      '<code>select="."</code>' are stored as attributes for the nodes
      '<code>xsl:template</code>' and '<code>xsl:value-of</code>' respectively.
      These attributes are accessible through the DOM interface.</p>
      </s3>
       <s3 title="Creating the Abstract Syntax Tree from the DOM">
      <p>What we have to do next is to create a tree that also holds the XSL
      specific elements; XPath expressions and patters (with possible filters)
      and calls to XSL functions. This is done by parsing the DOM and creating an
      instance of a subclass of 'SyntaxTreeNode' for each node in the DOM. A node
      in the DOM containing an XSL instruction (ex. "xsl:template") results in an
      instance of the correspoding class derived from the HashTable created by
      the parser (in this case in instance of the 'Template' class).</p>
  
      <p>Each class that inherits SyntaxTreeNode has a vector called
      '<code>_contents</code>' that holds references to all the children of the node
      (if any). Each node has a method called '<code>parseContents()</code>'. It is
      the responsibility of this method to parse any XPath expressions/patterns
      that are expected and found in the node's attributes. The XPath patterns
      and instructions are tokenised using the auto-generated class 'XPathParser'
      (generated using JavaCup and JLex). The tokenised expressions/patterns
      will result in a small sub-tree owned by the syntax tree node.</p>
  
      <p>XSL nodes holding expressions has a pointer called '<code>_select</code>' that
      points to a sub-tree representing the expression. This can be seen for
      instance in the 'Template' class:</p>
      <p><img src="compiler_AST.gif" alt="compiler_AST.gif"/></p>
      <p><ref>Fiugre 2: Sample Abstract Syntax Tree</ref></p>
      <p>In this example _select only points to a single node. In more complex
      expressions the pointer will point to an whole sub-tree.</p>
       </s3>
       </s2><anchor name="typecheck"/>
      <s2 title="Type-check and Cast Expressions">
      <p>In many cases we will need to typecast the top node in the expression
      sub-tree to suit the expected result-type of the expression, or to typecast
      child nodes to suit the allowed types for the various operators in the
      expression. This is done by calling 'typeCheck()' on the root-node in the
      XSL tree. Each SyntaxTree node is responsible for its own type checking
      (ie. the <code>typeCheck()</code> method must be overridden). Let us say that
      out pattern was:</p>
      <p><code>&lt;xsl:value-of select=&quot;1+2.73&quot;/&gt;</code></p>
      <p><img src="typecast.gif" alt="typecast.gif"/></p>
      <p><ref>Figure 3: XPath expression type conflict</ref></p>
      <p>The number 1 is an integer, and the number 2.73 is a real number, so the
      1 has to be promoted to a real. This is done ny inserting a new node between
      the [1] and the [+]. This node will convert the 1 to a real number:</p>
      <p><img src="cast_expression.gif" alt="cast_expression.gif"/></p>
      <p><ref>Figure 4: Type casting</ref></p>
  
      <p>The inserted node is an object of the class CastExpr. The SymbolTable
      that was instanciated in (1) is used to determine what casts are needed for
      the various operators and what return types the various expressions will
      have.</p>
  
      </s2><anchor name="compile"/>
      <s2 title="Code generation">
      <ul>
        <li><link anchor="toplevelelem">Compiling top-level elements</link></li>
        <li><link anchor="templatecode">Compiling template code</link></li>
        <li><link anchor="instrfunc">Compiling XSL instructions and functions</link></li>            
      </ul>
      <p>A general rule is that all classes that represent elements in the XSL
      tree/document, i.e. classes that inherit from SyntaxTreeNode output
      bytecode in the 'translate()' method.</p>
      <anchor name="toplevelelem"/>
      <s3 title="Compiling top-level elements">
      <p>The bytecode that handles top-level elements must be generated before any
      other code. The '<code>translate()</code>' method in these classes are mainly
      called from these methods in the Stylesheet class:</p>
  
  <source>    private String compileBuildKeys(ClassGenerator classGen);
      private String compileTopLevel(ClassGenerator classGen, Enumeration elements);
      private void compileConstructor(ClassGenerator classGen, Output output);</source>
  
      <p>These methods handle most top-level elements, such as global variables
      and parameters, <code>&lt;xsl:output&gt;</code> and
      <code>&lt;xsl:decimal-format&gt;</code> instructions.</p>
      </s3><anchor name="templatecode"/>
      <s3 title="Compiling template code">
      <p>All XPath patterns in <code>&lt;xsl:apply-template&gt;</code> instructions
      are converted into numeric values (known as the pattern's kernel 'type').
      All templates with identical pattern kernel types are grouped together and
      inserted into a table with its assigned type. (This table is found in the
      Mode class. There will be one such table for each mode that is used in the
      stylesheet). This table is used to build a big <code>switch()</code> statement
      in the translet's <code>applyTemplates()</code> method. This method is initially
      called with the root node of the input document.</p>
      <p>The <code>applyTemplates()</code> method determines the node's type and passes
      this type to the <code>switch()</code> statement to look up the matching
      template.</p>
  
      <p>There may be several templates that share the same pattern kernel type.
      Here are a few examples of templates with patterns that all have the same
      kernel type:</p>
  
  <source>    &lt;xsl:template match=&quot;A/C&quot;&gt;
      &lt;xsl:template match=&quot;A/B/C&quot;&gt;
      &lt;xsl:template match=&quot;A | C&quot;&gt;</source>
  
      <p>All these templates will be grouped under the type for <code>&lt;C&gt;</code>
      and will all get the same kernel type (the type for <code>"C"</code>). The last
      template will be grouped both under <code>"C"</code> and <code>"A"</code>. If the
      type identifier for <code>"C"</code> in this case is 8, all these templates will
      be put under <code>case 8:</code> in <code>applyTemplates()</code>'s big
      <code>switch()</code> statement. The Mode class will insert extra code to choose
      which template code to invoke.</p>
      </s3><anchor name="instrfunc"/>
      <s3 title="Compiling XSL instructions and functions">
  
      <p>The template code is generated by calling <code>translate()</code> on each
      Template object in the abstract syntax tree. This call will be propagated
      down the tree and every element will output the bytecodes necessary to
      complete its task.</p>
  
      <p>Each node will call 'translate()' on its children, and possibly on
      objects representing the node's XPath expressions, before outputting its
      own bytecode. In that way the correct sequence of instructions is generated.
      Each one of the child nodes is responsible of creating code that leaves the
      node's output value (if any) on the stack. The typical procedure for the
      parent node is to create code that consumes these values off the stack and
      then leave its own output on the stack for its parent.</p>
  
      <p>The tree-structure of the stylesheet is in this way closely tied with
      the stack-based JVM. The design does not offer any obvious way of extending
      the compiler to output code for other VMs or processors.</p>
     </s3>
    </s2>
  </s1>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/xsltc_dom.xml
  
  Index: xsltc_dom.xml
  ===================================================================
  <?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 Internal DOM">
    <ul>
      <li><link anchor="functionality">General functionlaity</link></li>
      <li><link anchor="components">Components of the internal DOM</link></li>
      <li><link anchor="structure">Internal structure</link></li>
      <li><link anchor="navigation">Tree navigation</link></li>
      <li><link anchor="namespaces">Namespaces</link></li>
      <li><link anchor="w3c">W3C DOM2 navigation support</link></li>
      <li><link anchor="adapter">The DOM adapter - DOMAdapter</link></li>
      <li><link anchor="multiplexer">The DOM multiplexer - MultiDOM</link></li>
      <li><link anchor="builder">The DOM builder - DOMImpl$DOMBuilder</link></li>
    </ul>
  
    <anchor name="functionality"/>
    <s2 title="General functionality">
    <p>The internal DOM gives the translet access to the XML document(s) it has
    to transform. The interface to the internal DOM is specified in the DOM.java
    class. This is the interface that the translet uses to access the DOM. 
    There is also an interface specified for DOM caches -- DOMCache.java</p>
  
    </s2><anchor name="components"/>
    <s2 title="Components of the internal DOM">
  
    <p>This DOM interface is implemented by three classes:</p>
    <ul>
      <li><em>org.apache.xalan.xsltc.dom.DOMImpl</em><br/><br/>
        This is the main DOM class. An instance of this class contains the nodes
        of a <em>single</em> XML document.<br/>br/>
      </li>
      <li><em>org.apache.xalan.xsltc.dom.MultiDOM</em><br/><br/>
        This class is best described as a DOM multiplexer. XSLTC was initially
        designed to operate on a single XML document, and the initial DOM and
        the DOM interface were designed and implemented without the
        <code>document()</code> function in mind. This class will allow a translet
        to access multiple DOMs through the original DOM interface.<br/><br/>
      </li>
      <li><em>org.apache.xalan.xsltc.dom.DOMAdapter</em><br/>br/>
        The DOM adapter is a mediator between a DOMImpl or a MultiDOM object and
        a single translet. A DOMAdapter object contains mappings and reverse
        mappings between node  types in the DOM(s) and node types in the translet.
        This mediator is needed to allow several translets access to a single DOM.
        <br/>br/>
      </li>
      <li><em>org.apache.xalan.xsltc.dom.DocumentCache</em><br/>br/>
        A sample DOM cache (implementing DOMCache) that is used with our sample
        transformation applications.
      </li>
    </ul>
  
    <p><img src="DOMInterface.gif" alt="DOMInterface.gif"/></p>
    <p><ref>Figure 1: Main components of the internal DOM</ref></p>
  
    <p>The figure above shows how several translets can access one or more
    internal DOM from a shared pool of cached DOMs. A translet can also access a
    DOM tree outside of a cache. The Stylesheet class that represents the XSL
    stylesheet to compile contains a flag that indicates if the translet uses the
    <code>document()</code> function. The code compiled into the translet will act
    accordingly and instanciate a MultiDOM object if needed (this code is compiled
     in the compiler's <code>Stylesheet.compileTransform()</code> method).</p>
  
    </s2><anchor name="structure"/>
    <s2 title="Internal Structure">
    <ul>
      <li><link anchor="node-id">Node identification</link></li>
      <li><link anchor="element-nodes">Element nodes</link></li>
      <li><link anchor="attribute-nodes">Attribute nodes</link></li>    
      <li><link anchor="text-nodes">Text nodes</link></li>
      <li><link anchor="comment-nodes">Comment nodes</link></li>    
      <li><link anchor="pi"></link>Processing instructions</li>
    </ul>
    <anchor name="node-id"/>
    <s3 title="Node identifation">
  
    <p>Each node in the DOM is represented by an integer. This integer is an
    index into a series of arrays that describes the node. Most important is
    the <code>_type[]</code> array, which holds the (DOM internal) node type. There
    are some general node types that are described in the DOM.java interface:</p>
  
  <source>
      public final static int ROOT                   = 0;
      public final static int TEXT                   = 1;
      public final static int UNUSED                 = 2;
      public final static int ELEMENT                = 3;
      public final static int ATTRIBUTE              = 4;
      public final static int PROCESSING_INSTRUCTION = 5;
      public final static int COMMENT                = 6;
      public final static int NTYPES                 = 7;
  </source>
  
    <p>Element and attribute nodes will be assigned types based on their expanded
    QNames. The <code>_type[]</code> array is used for this:</p>
  
  <source>
      int    type      = _type[node];             // get node type
  </source>
  
    <p>The node type can be used to look up the element/attribute name in the
    element/attribute name array <code>_namesArray[]</code>:</p>
  
  <source>
      String name      = _namesArray[type-NTYPES]; // get node element name
  </source>
  
    <p>The resulting string contains the full, expanded QName of the element or
    attribute. Retrieving the namespace URI of an element/attribute is done in a
    very similar fashion:</p>
  
  <source>
      int    nstype    = _namespace[type-NTYPES]; // get namespace type
      String namespace = _nsNamesArray[nstype];   // get node namespace name
  </source>
    </s3><anchor name="element-nodes"/>
    <s3 title="Element nodes">
  
    <p>The contents of an element node (child nodes) can be identified using
    the <code>_offsetOrChild[]</code> and <code>_nextSibling[]</code> arrays. The
    <code>_offsetOrChild[]</code> array will give you the first child of an element
    node:</p>
  
  <source>
      int    child     = _offsetOrChild[node];    // first child
      child = _nextSibling[child];                // next child
  </source>
  
    <p>The last child will have a &quot;<code>_nextSibling[]</code>&quot; of 0 (zero).
    This value is OK since the root node (the 0 node) will not be a child of
    any element.</p>
  
    </s3><anchor name="attribute-nodes"/>
    <s3 title="Attribute nodes">
  
    <p>The first attribute node of an element is found by a lookup in the
    <code>_lengthOrAttr[]</code> array using the node index:</p>
  
  <source>
      int    attribute = _offsetOrChild[node];    // first attribute
      attribute = _nextSibling[attribute];        // next attribute
  </source>
  
    <p>The names of attributes are contained in the <code>_namesArray[]</code> just
    like the names of element nodes. The value of attributes are store the same
    way as text nodes:</p>
  
  <source>
      int    offset    = _offsetOrChild[attribute]; // offset into character array
      int    length    = _lengthOrAttr[attribute];  // length of attribute value
      String value     = new String(_text, offset, length);
  </source>
    </s3><anchor name="text-nodes"/>
    <s3 title="Text nodes">
  
    <p>Text nodes are stored identically to attribute values. See the previous
    section on <link anchor="attribute-nodes">attribute nodes</link>.</p>
    </s3><anchor name="comment-nodes"/>
    <s3 title="Comment nodes">
  
    <p>The internal DOM does currently <em>not</em> contain comment nodes. Yes, I
    am quite aware that the DOM has a type assigned to comment nodes, but comments
    are still not inserted into the DOM.</p>
    </s3><anchor name="pi"/>
    <s3 title="Processing instructions">
  
    <p>Processing instructions are handled as text nodes. These nodes are stored
    identically to attribute values. See the previous section on
    <link anchor="attribute-nodes">attribute nodes</link>.</p>
  
    </s3></s2><anchor name="navigation"/>
    <s2 title="Tree navigation">
  
    <p>The DOM implementation contains a series of iterator that implement the
    XPath axis. All these iterators implement the NodeIterator interface and
    extend the NodeIteratorBase base class. These iterators do the job of
    navigating the tree using the <code>_offsetOrChild[]</code>, <code>_nextSibling</code>
    and <code>_parent[]</code> arrays. All iterators that handles XPath axis are
    implemented as a private inner class of DOMImpl. The translet uses a handful
    of methods to instanciate these iterators:</p>
  
  <source>
      public NodeIterator getIterator();
      public NodeIterator getChildren(final int node);
      public NodeIterator getTypedChildren(final int type);
      public NodeIterator getAxisIterator(final int axis);
      public NodeIterator getTypedAxisIterator(final int axis, final int type);
      public NodeIterator getNthDescendant(int node, int n);
      public NodeIterator getNamespaceAxisIterator(final int axis, final int ns);
      public NodeIterator orderNodes(NodeIterator source, int node);
  </source>
  
    <p>There are a few iterators in addition to these, such as sorting/ordering
    iterators and filtering iterators. These iterators are implemented in
    separate classes and can be instanciated directly by the translet.</p>
  
    </s2><anchor name="namespaces"/>
    <s2 title="Namespaces">
  
    <p>Namespace support was added to the internal DOM at a late stage, and the
    design and implementation of the DOM bears a few scars because of this. 
    There is a separate <link idref="xsltc_namespace">design
    document</link> that covers namespaces.</p>
  
    </s2><anchor name="w3c"/>
    <s2 title="W3C DOM2 navigation support">
  
    <p>The DOM has a few methods that give basic W3C-type DOM navigation. These
    methods are:</p>
  
  <source>
      public Node makeNode(int index);
      public Node makeNode(NodeIterator iter);
      public NodeList makeNodeList(int index);
      public NodeList makeNodeList(NodeIterator iter);
  </source>
  
    <p>These methods return instances of inner classes of the DOM that implement
    the W3C Node and NodeList interfaces.</p>
  
    </s2><anchor name="adapter"/>
    <s2 title="The DOM adapter - DOMAdapter">
    <ul>
      <li><link anchor="translet-dom">Translet/DOM type mapping</link></li>
      <li><link anchor="whitespace">Whitespace text-node stripping</link></li>
      <li><link anchor="method-mapping">Method mapping</link></li>
    </ul>
    <anchor name="translet-dom"/>
    <s3 title="Translet/DOM type mapping">
  
    <p>The DOMAdapter class performs the mappings between DOM and translet node
    types, and vice versa. These mappings are necessary in order for the translet
    to correctly identify an element/attribute in the DOM and for the DOM to
    correctly identify the element/attribute type of a typed iterator requested
    by the translet. Note that the DOMAdapter also maps translet namespace types
    to DOM namespace types, and vice versa.</p>
  
    <p>The DOMAdapter class has four global tables that hold the translet/DOM
    type and namespace-type mappings. If the DOM knows an element as type
    19, the DOMAdapter will translate this to some other integer using the
    <code>_mapping[]</code> array:</p>
  
  <source>
      int domType = _mapping[transletType];
  </source>
  
    <p>This action will be performed when the DOM asks what type a specific node
    is. The reverse is done then the translet wants an iterator for a specific
    node type. The DOMAdapter must translate the translet-type to the type used
    internally in the DOM by looking up the <code>_reverse[]</code> array:</p>
  
  <source>
      int transletType = _mapping[domType];
  </source>
  
    <p>There are two additional mapping tables: <code>_NSmapping[]</code> and
    <code>_NSreverse[]</code> that do the same for namespace types.</p>
    </s3><anchor name="whitespace"/>
    <s3 title="Whitespace text-node stripping">
  
    <p>The DOMAdapter class has the additional function of stripping whitespace
    nodes in the DOM. This functionality had to be put in the DOMAdapter, as
    different translets will have different preferences for node stripping.</p>
    </s3><anchor name="method-mapping"/>
    <s3 title="Method mapping">
  
    <p>The DOMAdapter class implements the same <code>DOM</code> interface as the
    DOMImpl class. A DOMAdapter object will look like a DOMImpl tree, but the
    translet can access it directly without being concerned with type mapping
    and whitespace stripping. The <code>getTypedChildren()</code> demonstrates very
    well how this is done:</p>
  
  <source>
      public NodeIterator getTypedChildren(int type) {
          // Get the DOM type for the requested typed iterator
          final int domType = _reverse[type];
          // Now get the typed child iterator from the DOMImpl object
          NodeIterator iterator = _domImpl.getTypedChildren(domType);
          // Wrap the iterator in a WS stripping iterator if child-nodes are text nodes
  	if ((domType == DOM.TEXT) &amp;&amp; (_filter != null))
  	    iterator = _domImpl.strippingIterator(iterator,_mapping,_filter);
  	return(iterator);
      }
  </source>
  
    </s3></s2><anchor name="multiplexer"/>
    <s2 title="The DOM multiplexer - MultiDOM">
  
    <p>The DOM multiplexer class is only used when the compiled stylesheet uses
    the <code>document()</code> function. An instance of the MultiDOM class also
    implements the DOM interface, so that it can be accessed in the same way
    as a DOMAdapter object.</p>
  
    <p>A node in the DOM is identified by an integer. The first 8 bits of this
    integer are used to identify the DOM in which the node belongs, while the
    lower 24 bits are used to identify the node within the DOM:</p>
      <table>
        <tr>
          <td>31-24</td>
          <td>23-16</td>
          <td>16-8</td>
          <td>7-0</td>
        </tr>
        <tr>
          <td>DOM id</td>
          <td colspan="3">node id</td>
        </tr>
      </table>
  
    <p>The DOM multiplexer has an array of DOMAdapter objects. The topmost 8
    bits of the identifier is used to find the correct DOM from the array. Then
    the lower 24 bits are used in calls to methods in the DOMAdapter object:</p>
  
  <source>
      public int getParent(int node) {
  	return _adapters[node>>>24].getParent(node &amp; 0x00ffffff) | node &amp; 0xff000000;
      }
  </source>
  
    <p>Note that the node identifier returned by this method has the same upper 8
    bits as the input node. This is why we <code>OR</code> the result from
    <code>DOMAdapter.getParent()</code> with the top 8 bits of the input node.</p>
  
    </s2><anchor name="builder"/>
    <s2 title="The DOM builder - DOMImpl$DOMBuilder">
    <ul>
      <li><link anchor="startelement">startElement()</link></li>
      <li><link anchor="endelement">endElement()</link></li>
      <li><link anchor="startprefixmapping">startPrefixMapping()</link></li>
      <li><link anchor="endprefixmapping">endPrefixMapping()</link></li>
      <li><link anchor="characters">characters()</link></li>
      <li><link anchor="startdocument">startDocument()</link></li>
      <li><link anchor="enddocument">endDocument()</link></li>
    </ul>
  
    <p>The DOM builder is an inner class of the DOM implementation. The builder
    implements the SAX2 <code>ContentHandler</code> interface and populates the DOM
    by receiving SAX2 events from a SAX2 parser (presently xerces). An instance
    of the DOM builder class can be retrieved from <code>DOMImpl.getBuilder()</code>
    method, and this handler can be set as an XMLReader's content handler:</p>
  
  <source>
      final SAXParserFactory factory = SAXParserFactory.newInstance();
      final SAXParser parser = factory.newSAXParser();
      final XMLReader reader = parser.getXMLReader();
      final DOMImpl dom = new DOMImpl();
      reader.setContentHandler(dom.getBuilder());
  </source>
  
    <p>The DOM builder will start to populate the DOM once the XML parser starts
    generating SAX2 events:</p>
    <anchor name="startelement"/>
    <s3 title="startElement()">
  
    <p>This method can be called in one of two ways; either with the expanded
    QName (the element's separate uri and local name are supplied) or as a
    normal QName (one String on the format prefix:local-name). The DOM stores
    elements as expanded QNames so it needs to know the element's namespace URI.
    Since the URI is not supplied with this call, we have to keep track of
    namespace prefix/uri mappings while we're building the DOM. See 
    <code><link anchor="startprefixmapping">startPrefixMapping()</link></code> below for details on
    namespace handling.</p>
  
    <p>The <code>startElement()</code> inserts the element as a child of the current
    parent element, creates attribute nodes for all attributes in the supplied
    &quot;<code>Attributes</code>&quot; attribute list (by a series of calls to
    <code>makeAttributeNode()</code>), and finally creates the actual element node
    (by calling <code>internElement()</code>, which inserts a new entry in the
    <code>_type[]</code> array).</p>
    </s3><anchor name="endelement"/>
    <s3 title="endElement()">
  
    <p>This method does some cleanup after the <code>startElement()</code> method,
    such as revering <code>xml:space</code> settings and linking the element's
    child nodes.</p>
    </s3><anchor name="startprefixmapping"/>
    <s3 title="startPrefixMapping()">
  
    <p>This method is called for each namespace declaration in the source
    document. The parser should call this method before the prefix is referenced
    in a QName that is passed to the <code>startElement()</code> call. Namespace
    prefix/uri mappings are stored in a Hashtable structure. Namespace prefixes
    are used as the keys in the Hashtable, and each key maps to a Stack that
    contains the various URIs that the prefix maps to. The URI on top of the
    stack is the URI that the prefix currently maps to.</p>
  
    
      <p><img src="namespace_stack.gif" alt="namespace_stack.gif"/></p>
      <p><ref>Figure 2: Namespace handling in the DOM builder</ref></p>
  
  
    <p>Each call to <code>startPrefixMapping()</code> results in a lookup in the
    Hashtable (using the prefix), and a <code>push()</code> of the URI onto the
    Stack that the prefix maps to.</p>
    </s3><anchor name="endprefixmapping"/>
    <s3 title="endPrefixMapping()">
  
    <p>A namespace prefix/uri mapping is closed by locating the Stack for the
    prefix, and then <code>pop()</code>'ing the topmost URI off this Stack.</p>
    </s3><anchor name="characters"/>
    <s3 title="characters()">
  
    <p>Text nodes are stored as simple character sequences in the character array
    <code>_text[]</code>. The start and lenght of a node's text can be determined by
    using the node index to look up <code>_offsetOrChild[]</code> and
    <code>_lengthOrAttribute[]</code>.</p>
  
    <p>We want to re-use character sequences if two or more text nodes have
    identical content. This can be achieved by having two different text node
    indexes map to the same character sequence. The <code>maybeReuseText()</code>
    method is always called before a new character string is stored in the
    <code>_text[]</code> array. This method will locate the offset of an existing
    instance of a character sequence.</p>
    </s3><anchor name="startdocument"/>
    <s3 title="startDocument()">
  
    <p>This method initialises a bunch of data structures that are used by the
    builder. It also pushes the default namespace on the namespace stack (so that
    the &quot;&quot; prefix maps to the <code>null</code> namespace).</p>
    </s3><anchor name="enddocument"/>
    <s3 title="endDocument()">
  
    <p>This method builds the <code>_namesArray[]</code>, <code>_namespace[]</code>
    and <code>_nsNamesArray[]</code> structures from temporary datastructures used
    in the DOM builder.</p>
  
     </s3>
   </s2>
  </s1>   
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/xsltc_namespace.xml
  
  Index: xsltc_namespace.xml
  ===================================================================
  <?xml version="1.0" standalone="no"?>
  <!-- 
   * 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/>.
   -->
  <!DOCTYPE s1 SYSTEM "../../style/dtd/document.dtd">
    <s1 title="XSLTC and Namespaces">
    <ul>
      <li><link anchor="functionality">Functionality</link></li>
      <li><link anchor="overview">Namespace overview</link></li>
      <li><link anchor="NSA">The DOM &amp; namespaces</link></li>    
      <li><link anchor="NSB">Namespaces in the XSL stylesheet</link></li>
      <li><link anchor="NSC">Namespaces in the output document</link></li>
    </ul>
    <anchor name="functionality"/>
    <s2 title="Functionality">
  
      <p>Namespaces are used when an XML documents has elements have the same
      name, but are from different contexts, and thus have different meanings
      and interpretations. For instance, a <code>&lt;TITLE&gt;</code> element can
      be a HTML title element in one part of the XML document, while it in other
      parts of the document the <code>&lt;TITLE&gt;</code> element is used for
      encapsulating the title of a play or a book. This sort of confusion is
      very common when reading XML source from multiple documents, but can also
      occur within a single document.</p>
  
      <p>Namespaces have three very important properties: a name, a prefix (an
      alias for its name) and a scope. Namespaces are declared as attributes of
      almost any node in an XML document. The declaration looks like this:</p>
  
  <source>
      &lt;element xmlns:prefix="http://some.site/spec"&gt;....&lt;/element&gt;
  </source>
  
      <p>The <code>"xmlns"</code> tells that this is a namespace declaration. The
      scope of the namespace declaration is the element in which it is defined
      and all the children of that element.The prefix is the local alias we use
      for referencing the namespace, and the URL (it can be anything, really) is
      the name/definition of the namespace. Note that even though the namespace
      definition is normally an URL, it does not have to point to anything. It
      is recommended that it points to a page that describes the elements in the
      namespace, but it does not have to. The prefix can be just about anything
      - or nothing (in which case it is the default namespace). Any prefix,
      including the empty prefix for the default namespace, can be redefined to
      refer to a different namespace at any time in an XML document. This is
      more likely to happen to the default namespace than any other prefix. Here
      is an example of this:</p>
  
      <anchor name="xml_sample_1"/>
  <source>
      &lt;?xml version="1.0"?&gt;
      
      &lt;employees xmlns:postal="http://postal.ie/spec-1.0"
                 xmlns:email="http://www.w3c.org/some-spec-3.2"&gt;
          &lt;employee&gt;
              &lt;name&gt;Bob Worker&lt;/name&gt;
              &lt;postal:address&gt;
                  &lt;postal:street&gt;Nassau Street&lt;/postal:street&gt;
                  &lt;postal:city&gt;Dublin 3&lt;/postal:city&gt;
                  &lt;postal:country&gt;Ireland&lt;/postal:country&gt;
              &lt;/postal:address&gt;
              &lt;email:address&gt;bob.worker@hisjob.ie&lt;/email:address&gt;
          &lt;/employee&gt;
      &lt;/employees&gt;
  </source>
  
      <p>This short document has two namespace declarations, one with the prefix
      <code>"postal"</code> and another with the prefix <code>"email"</code>. The
      prefixes are used to distinguish between elements for e-mail addresses and
      regular postal addresses. In addition to these two namespaces there is also
      an initial (unnamed) default namespace being used for the
      <code>&lt;name&gt;</code> and <code>&lt;employee&gt;</code> tags. The scope of the
      default namespace is in this case the whole document, while the scope of
      the other two declared namespaces is the <code>&lt;employees&gt;</code>
      element and its children.</p>
  
      <p>By changing the default namespace we could have made the document a
      little bit simpler and more readable:</p>
  
      <anchor name="xml_sample_2"/>
  <source>
      &lt;?xml version="1.0"?&gt;
      
      &lt;employees xmlns:email="http://www.w3c.org/some-spec-3.2"&gt;
          &lt;employee&gt;
              &lt;name&gt;Bob Worker&lt;/name&gt;
              &lt;address xmlns="http://postal.ie/spec-1.0"&gt;
                  &lt;street&gt;Nassau Street&lt;/street&gt;
                  &lt;city&gt;Dublin 3&lt;/city&gt;
                  &lt;country&gt;Ireland&lt;/country&gt;
              &lt;/address&gt;
              &lt;email:address&gt;bob.worker@hisjob.ie&lt;/email:address&gt;
          &lt;/employee&gt;
      &lt;/employees&gt;
  </source>
  
      <p>The default namespace is redefined for the <code>&lt;address&gt;</code> node
      and its children, so there is no need to specify the street as
      <code>&lt;postal:street&gt;</code> - just plain <code>&lt;street&gt;</code> is
      sufficient. Note that this also applies to the <code>&lt;address&gt;</code>
      where the namespace is first defined. This is in effect a redefinition of
      the default namespace.</p>
    </s2><anchor name="overview"/>
    <s2 title="Namespace overview">
  
      <p>Namespaces will have to be handled in three separate parts of the XSLT
      compiler:</p>
  
      <anchor name="all_namespaces"/>
        <p><img src="all_namespaces.gif" alt="all_namespaces.gif"/></p>
        <p><ref>Figure 1: Namespace handlers in the XSLTC</ref></p>
  
      <p>The most obvious is the namespaces in the source XML document
      (marked <link anchor="NSA">"NS A"</link> in figure 1). These namespaces will be
      handled by our DOM implementation class. The source XSL stylesheet also
      has its own set of namespaces (<link idref="NSB">"NS B"</link>) - one of which
      is the XSL namespace. These namespaces will be handled at run-time and
      whatever information that is needed to process there should be compiled
      into the translet. There is also a set of namespaces that will be used in
      the resulting document (<link idref="NSC">"NS C"</link>). This is an
      intersection of the first two. The output document should not contain any
      more namespace declarations than necessary.</p>
  
      </s2><anchor name="NSA"/>
      <s2 title="The DOM &amp; namespaces">
      <ul>
        <li><link anchor="dom-namespace">DOM node types and namespace types</link></li>
        <li><link anchor="assign">Assigning namespace types to DOM nodes</link></li>                
      </ul>
      <anchor name="dom-namespace"/>
      <s3 title="DOM node types and namespace types">
  
      <p>Refer to the XSLTC <link idref="xsltc_runtime">runtime
      environment design</link> document for a description of node types before
      proceeding. In short, each node in the our DOM implementation is
      represented by a simple integer. By using this integer as an index into an
      array called <code>_type[]</code> we can find the type of the node.</p>
  
      <p>The type of the node is an integer representing the type of element the
      node is. All elements <code>&lt;bob&gt;</code> will be given the same type,
      all text nodes will be given the same type, and so on. By using the node
      type as an index an array called <code>_namesArray[]</code> we can find the
      name of the element type - in this case "bob". This code fragment shows
      how you can, with our current implementation, find the name of a node:</p>
  
  <source>
      int    node = iterator.getNext();  // get next node
      int    type = _type[node];         // get node type
      String name = _namesArray[type];   // get node name
  </source>
  
      <p>We want to keep the one-type-per-node arrangement, since that lets us
      produce fairly efficient code. One type in the DOM maps to one type in
      the compiled translet. What we could do to represent the namespace for
      each node in the DOM is to add a <code>_namespaceType[]</code> array that holds
      namespace types. Each node type maps to a namespace type, and each
      namespace type maps to a namespace name (and a prefix with a limited
      scope):</p>
  
      <anchor name="type_mappings"/>
      <p><img src="type_mappings.gif" alt="type_mappings.gif"/></p>
        <p><ref>Figure 2: Mapping between node types/names, namespace types/names</ref></p>
  
      <p>This code fragment shows how we could get the namespace name for a node:</p>
  
  <source>
      int    node      = iterator.getNext();    // get next node
      int    type      = _type[node];           // get node type
      int    nstype    = _namespace[type];      // get namespace type
      String name      = _namesArray[type];     // get node element name
      String namespace = _nsNamesArray[nstype]; // get node namespace name
  </source>
  
      <p>Note that namespace prefixes are not included here. Namespace prefixes
      are local to the XML document and will be expanded to the full namespace
      names when the nodes are put into the DOM. This, however, is not a trivial
      matter.</p>
      </s3><anchor name="assign"/>
      <s3 title="Assigning namespace types to DOM nodes">
  
      <p>We cannot simply have a single namespace prefix array similar to the
      <code>_namespaceArray[]</code> array for mapping a namespace type to a single
      prefix. This because prefixes can refer to different namespaces depending
      on where in the document the prefixes are being used. In our last example's
      <link idref="xml_sample_2">XML fragment</link> the empty prefix <code>""</code>
      initially referred to the default namespace (the one with no name - just
      like a Clint Eastwood character). Later on in the document the empty
      prefix is changed to refer to a namespace called 
      <code>"http://postal.ie/spec-1.0"</code>.</p>
  
      <p>Namespace prefixes are only relevant at the time when the XML document
      is parsed and the DOM is built. Once we have the DOM completed we only need
      a table that maps each node type to a namespace type, and another array of
      all the names of the different namespaces. So what we want to end up with
      is something like this:</p>
  
       <p><img src="dom_namespace1.gif" alt="dom_namespace1.gif"/></p>
       <p><ref>Figure 3: Each namespace references in the DOM gets one entry</ref></p>
  
      <p>The namespace table has one entry for each namespace, nomatter how many
      prefixes were used ro reference this namespace in the DOM. To build this
      array we need a temporary data structure used by the DOM builder. This
      structure is a hashtable - where the various prefixes are used for the
      hash values. The contents of each entry in the table will be a small stack
      where previous meanings of each prefix will be stored:</p>
  
       <p><img src="dom_namespace2.gif" alt="dom_namespace2.gif"/></p>
       <p><ref>Figure 4: Temporary data structure used by the DOM builder</ref></p>
  
      <p>When the first node is encountered we define a new namespace
      <code>"foo"</code> and assign this namespace type/index 1 (the default 
      namespace <code>""</code> has index 0). At the same time we use the prefix
      <code>"A"</code> for a lookup in the hashtable. This gives us
      an integer stack used for the prefix <code>"A"</code>. We push the namespace
      type 1 on this stack. From now on, until <code>"A"</code> is pop'ed off this
      stack, the prefix <code>"A"</code> will map to namespace type 1, which
      represents the namespace URI <code>"foo"</code>.</p>
  
      <p>We then encounter the next node with a new namespace definition with
      the same namespace prefix, we create a new namespace <code>"bar"</code> and
      we put that in the namespace table under type 2. Again we use the prefix
      <code>"A"</code> as an entry into the namespace prefix table and we get the
      same integer stack. We now push namespace type 2 on the stack, so that
      namespace prefix <code>"A"</code> maps to namespace URI <code>"bar"</code>. When
      we have traversed this node's children we need to pop the integer off the
      stack, so when we're back at the first node the prefix <code>"A"</code> again
      will point to namespace type 0, which maps to <code>"foo"</code>. To keep
      track of what nodes had what namespace declarations, we use a namespace
      declaration stack:</p>
  
      <p><img src="dom_namespace3.gif" alt="dom_namespace3.gif"/></p>
       <p><ref>Figure 5: Namespace declaration stack</ref></p>
       
      <p>Every namespace declaration is pushed on the namespace declaration
      stack. This stack holds the node index for where the namespace was
      declared, and a reference to the prefix stack for this declaration.
      The <code>endElement()</code> method of the DOMBuilder class will need to
      remove namespace declaration for the node that is closed. This is done
      by first checking the namespace declaration stack for any namespaces
      declared by this node. If any declarations are found these are un-declared
      by poping the namespace prefixes off the respective prefix stack(s), and
      then poping the entry/entries for this node off the namespace declaration
      stack.</p>
  
      <p>The <code>endDocument()</code> method will build an array that contains
      all namespaces used in the source XML document - <code>_nsNamesArray[]</code>
      - which holds the URIs of all refered namespaces. This method also builds
      an array that maps all DOM node types to namespace types. This two arrays
      are accessed through two new methods in the DOM interface:</p>
  
  <source>
      public String getNamespaceName(int node);
      public int    getNamespaceType(int node);
  </source>
  
    </s3></s2><anchor name="NSB"/>
    <s2 title="Namespaces in the XSL stylesheet">
    <ul>
      <li><link anchor="store-access">Storing and accessing namespace information</link></li>
      <li><link anchor="mapdom-stylesheet">Mapping DOM namespaces to stylesheet namespaces</link></li>
      <li><link anchor="wildcards">Wildcards and namespaces</link></li>
    </ul>
      <anchor name="store-access"/>
      <s3 title="Storing and accessing namespace information">
      <p>The SymbolTable class has three datastructures that are used to hold
      namespace information:</p>
  
      <ul>
        <li>
          First there is the <code>_namespaces[]</code> Hashtable that maps the names
          of in-scope namespace to their respective prefixes. Each key in the
          Hashtable object has a stack. A new prefix is pushed on the stack for
          each new declaration of a namespace.
        </li>
        <li>
          Then there is the <code>_prefixes[]</code> Hashtable. This has the reverse
          function of the <code>_namespaces[]</code> Hashtable - it maps from
          prefixes to namespaces.
        </li>
        <li>
          There is also a hashtable that is used for implementing the
          <code>&lt;xsl:namespace-alias&gt;</code> element. The keys in this
          hashtable is taken from the <code>stylesheet-prefix</code> attribute of
          this element, and the resulting prefix (from the <code>result-prefix</code>
          attribute) is used as the value for each key.
        </li>
      </ul>
  
      <p>The SymbolTable class offers 4 methods for accessing these data
      structures:</p>
  
  <source>
      public void   pushNamespace(String prefix, String uri);
      public void   popNamespace(String prefix);
      public String lookupPrefix(String uri);
      public String lookupNamespace(String prefix);
  </source>
  
      <p>These methods are wrapped by two methods in the Parser class (a Parser
      object alwas has a SymbolTable object):</p>
  <source>
      // This method pushes all namespaces declared within a single element
      public void pushNamespaces(ElementEx element);
      // This method pops all namespaces declared within a single element
      public void popNamespaces(ElementEx element);
  </source>
  
      <p>The translet class has, just like the DOM, a <code>namesArray[]</code>
      structure for holding the expanded QNames of all accessed elements. The
      compiled translet fills this array in its constructor. When the translet
      has built the DOM (a DOMImpl object), it passes the DOM to the a DOM
      adapter (a DOMAdapter object) together with the names array. The DOM
      adapter then maps the translet's types to the DOM's types.</p>
     </s3><anchor name="mapdom-stylesheet"/>
    <s3 title="Mapping DOM namespaces and stylesheet namespaces">
  
      <p>Each entry in the DOM's <code>_namesArray[]</code> is expanded to contain
      the full QName, so that instead of containing <code>prefix:localname</code> it
      will now contain <code>namespace-uri:localname</code>. In this way the expanded
      QName in the translet will match the exanded QName in the DOM. This assures
      matches on full QNames, but does not do much for <code>match="A:*"</code> type
      XPath patterns. This is where our main challenge lies.</p>
      </s3><anchor name="wildcards"/>
      <s3 title="Wildcards and namespaces">
  
      <p>The original implementation of the XSLTC runtime environment would
      only allow matches on "<code>*</code>" and "<code>@*</code>" patterns. This was
      achieved by mapping all elements that could not be mapped to a translet
      type to 3 (DOM.ELEMENT type), and similarly all unknown attributes to
      type 4 (DOM.ATTRIBUTE type). The main <code>switch()</code> statement in
      <code>applyTemplates()</code> would then have a separate "<code>case()</code>"
      for each of these. (Under each <code>case()</code> you might have to check
      for the node's parents in case you were matching on "<code>path/*</code>"-type
      patterns.) This figure shows how that was done:</p>
  
      <anchor name="match_namespace1"/>
      <p><img src="match_namespace1.gif" alt="match_namespace1.gif"/></p>
      <p><ref>Figure 6: Previous pattern matching</ref></p>
  
      <p>The "Node test" box here represents the "<code>switch()</code>" statement.
      The "Node parent test" box represent each "<code>case:</code>" for that 
      <code>switch()</code> statement. There is one <code>case:</code> for each know
      translet node type. For each node type we have to check for any parent
      patterns - for instance, for the pattern "<code>/foo/bar/baz</code>", we will
      get a match with <code>case "baz"</code>, and we have to check that the parent
      node is "<code>bar</code>" and that the grandparent is "<code>foo</code>" before
      we can say that we have a hit. The "Element parent test" is the test that
      is done all DOM nodes that do not directly match any translet types. This
      is the test for "<code>*</code>" or "<code>foo/*</code>". Similarly we have a
      "<code>case:</code>" for match on attributes ("<code>@*</code>").</p>
  
      <p>What we now want to achieve is to insert a check for patterns on the
      format "<code>ns:*</code>", "<code>foo/ns:*</code>" or "<code>ns:@*</code>", which
      this figure illustrates:</p>
  
      <anchor name="match_namespace2"/>
        <p><img src="match_namespace2.gif" alt="match_namespace2.gif"/></p>
        <p><ref>Figure 7: Pattern matching with namespace tests</ref></p>
  
  
      <p>Each node in the DOM needs a namespace type as well as the QName type.
      With this type we can match wildcard rules to any specific namespace.
      So after any checks have been done on the whole QName of a node (the type),
      we can match on the namespace type of the node. The main dispatch
      <code>switch()</code> in <code>applyTemplates()</code> must be changed from this:</p>
  
      <source>
          public void applyTemplates(DOM dom, NodeIterator iterator,
                                     TransletOutputHandler handler) {
  
              // Get next node from iterator
              while ((node = iterator.next()) != END) {
                  // Get internal node type
                  final int type = DOM.getType(node);
                  switch(type) {
                  case DOM.ROOT:      // Match on "/" pattern
                      handleRootNode();       
                      break;
                  case DOM.TEXT:      // Handle text nodes
                      handleText();
                      break;
                  case DOM.ELEMENT:   // Match on "*" pattern
                      handleWildcardElement();
                      break;
                  case DOM.ATTRIBUTE: // Handle on "@*" pattern
                      handleWildcardElement();
                      break;
                  case nodeType1:     // Handle 1st known element type
                      compiledCodeForType1();
                      break;
                      :
                      :
                      :
                  case nodeTypeN:   // Handle nth known element type
                      compiledCodeForTypeN();
                      break;
                  default:
                     NodeIterator newIterator = DOM.getChildren(node);
                     applyTemplates(DOM, newIterator, handler);
                     break;
                  }
              }
              return;
          }
  </source>
  
      <p>To something like this:</p>
  
      <source>
          public void applyTemplates(DOM dom, NodeIterator iterator,
                                     TransletOutputHandler handler) {
  
              // Get next node from iterator
              while ((node = iterator.next()) != END) {
  
                  // First run check on node type
                  final int type = DOM.getType(node);
                  switch(type) {
                  case DOM.ROOT:      // Match on "/" pattern
                      handleRootNode();
                      continue;
                  case DOM.TEXT:      // Handle text nodes
                      handleText();
                      continue;
                  case DOM.ELEMENT:   // Not handled here!!!
                      break;
                  case DOM.ATTRIBUTE: // Not handled here!!!
                      break;
                  case nodeType1:     // Handle 1st known element type
                      if (compiledCodeForType1() == match) continue;
                      break;
                      :
                      :
                      :
                  case nodeTypeN:     // Handle nth known element type
                      if (compiledCodeForTypeN() == match) continue;
                      break;
                  default:
                      break;
                  }
  
                  // Then run check on namespace type
                  final int namespace = DOM.getNamespace(type);
                  switch(namespace) {
                  case 0: // Handle nodes matching 1st known namespace
                      if (handleThisNamespace() == match) continue;
                      break;
                  case 1: // Handle nodes matching 2nd known namespace
                      if (handleOtherNamespace() == match) continue;
                      break;
                  }
  
                  // Finally check on element/attribute wildcard
                  if (type == DOM.ELEMENT) {
                      if (handleWildcardElement() == match)
                          continue;
                      else {
                         // The default action for elements
                         NodeIterator newIterator = DOM.getChildren(node);
                         applyTemplates(DOM, newIterator, handler);
                      }
                  }
                  else if (type == DOM.ATTRIBUTE) {
                      handleWildcardAttribute();
                      continue; 
                  }
              }
          }
  </source>
  
      <p>First note that the default action (iterate on children) does not hold for
      attributes, since attribute nodes do not have children. Then note that the way
      the three levels of tests are ordered is consistent with the way patterns
      should be prioritised:</p>
  
      <ul>
  
        <li><em>Match on element/attribute types:</em></li>
          <ul>
            <li><code>match="/"</code> - match on the root node</li>
            <li><code>match="B"</code> - match on any B element</li>
            <li><code>match="A/B"</code> - match on B elements with A parent</li>
            <li><code>match="A | B"</code> - match on B or A element</li>
            <li><code>match="foo:B"</code> - match on B element within "foo" namespace</li>
          </ul>
          <li><em>Match on namespace:</em></li>
          <ul>
            <li><code>match="foo:*"</code> - match on any element within "foo" namespace</li>
            <li><code>match="foo:@*"</code> - match on any attribute within "foo" namespace</li>
            <li><code>match="A/foo:*"</code> - match on any element within "foo" namespace with A parent</li>
            <li><code>match="A/foo:@*"</code> - match on any attribute within "foo" namespace with A parent</li>
          </ul>      
  
        <li><em>Match on wildcard:</em> </li>
          <ul>
            <li><code>match="*"</code> - match on any element</li>
            <li><code>match="@*"</code> - match on any attribute</li>
            <li><code>match="A/*"</code> - match on any element with A parent</li>
            <li><code>match="A/@*"</code> - match on any attribute with A parent</li>
          </ul>
       
      </ul>
  
       </s3></s2><anchor name="NSC"/>
       <s2 title="Namespaces in the output document">
  
      <p>These are the categories of namespaces that end up in the output
      document:</p>
  
      <ul>
        <li>
          Namespaces used in literal elements/attributes in the stylesheet. These
          namespaces should be declared <em>once</em> before use in the output
          document. These elements are copied to the output document independent
          of namespaces in the input XML document. However, the namespaces can
          be declared using the same prefix, such that a namespace used by a
          literal result element can overshadow a namespace from the DOM.
        </li>
        <li>
          Namespaces from elements in the stylesheet that match elements in the
          DOM. No namespaces from the DOM should be copied to the output document
          unless they are actually referenced in the stylesheet. No namespaces
          from the stylesheet should be copied to the output document unless the
          elements in which they are references match elements in the DOM.
        </li>
      </ul>
  
        <anchor name="output_namespaces1"/>
        <p><img src="output_namespaces1.gif" alt="output_namespaces1.gif"/></p>
        <p><ref>Figure 8: Namespace declaration in the output document</ref></p>    
  
      <p>Any literal element that ends up in the output document must declare all
      namespaces that were declared in the <code>&lt;xsl:stylesheet&lt;</code>
      element. Exceptions are namespaces that are listed in this element's
      <code>exclude-result-prefixes</code> or <code>extension-element-prefixes</code>
      attributes. These namespaces should only be declared if they are referenced
      in the output.</p>
  
      <p>Literal elements should only declare namespaces when necessary. A
      literal element should only declare a namespace in the case where it
      references a namespace using prefix that is not in scope for this
      namespace. The output handler will take care of this problem. All namespace
      declarations are put in the output document using the output handler's
      <code>declarenamespace()</code> method. This method will monitor all namespace
      declarations and make sure that no unnecessary declarations are output.
      The datastructures used for this are similar to those used to track
      namespaces in the XSL stylesheet:</p>
  
      <anchor name="output_namespaces2"/>
      <p><img src="output_namespaces2.gif" alt="output_namespaces2.gif"/></p>
        <p><ref>Figure 9: Handling Namespace declarations in the output document</ref></p>
  
   </s2>
  </s1>
  
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/xsltc_runtime.xml
  
  Index: xsltc_runtime.xml
  ===================================================================
  <?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 runtime environment">
    <ul>
      <li><link anchor="overview">Runtime overview</link></li>
      <li><link anchor="translet">The compiled translet</link></li>
      <li><link anchor="types">External/internal type mapping</link></li>    
      <li><link anchor="mainloop">Main program loop</link></li>
  
    </ul>
    <anchor name="overview"/>
    <s2 title="Runtime overview">
      <p>The actual transformation of the input XML document is initiated by
      one of these classes:</p>
  
      <ul>
        <li>
          <code>com.sun.xslt.runtime.DefaultRun</code> (runs in a terminal)
        </li>
        <li>
          <code>com.sun.xslt.demo.applet.TransformApplet</code> (runs in an applet)
        </li>
        <li>
          <code>com.sun.xslt.demo.servlet.Translate</code> (runs in a servlet)
        </li>
      </ul>
  
      <p>Any one of these classes will have to go through the folloing steps in
      order to initiate a transformation:</p>
  
      <ul>
        <li>
          Instanciate the translet object. The name of the translet (ie. class)
          to use is passed to us as a string. We use this string as a parameter
          to the static method <code>Class.forName(String name)</code> to get a
          reference to a translet object.
        </li>
        <li>
          Instanciate a <code>com.sun.xsl.parser.Parser</code> object to parse the
          input XML file, and instanciate a DOM (we have our own DOM
          implementation especially designed for XSLTC) where we store the
          input document.
        </li>
        <li>
          Pass any parameters to the translet (currently only possible when
          running the transformation in a terminal using DefaultRun)
        </li>
        <li>
          Instanciate a handler for the result document. This handler must be
          extend the <code>TransletOutputHandler</code> class.
        </li>
        <li>
          Invoke the <code>transform()</code> method on the translet, passing the
          instanciated DOM and the output handler as parameters.
        </li>
      </ul>
  
      </s2><anchor name="translet"/>
      <s2 title="The compiled translet">
  
      <p>A translet is always a subclass of <code>AbstractTranslet</code>. As well
      as having access to the public/protected methods in this class, the
      translet is compiled with these methods:</p>
  
      <p><code>public void transform(DOM, NodeIterator, TransletOutputHandler);</code></p>
  
      <p>This method is passed a <code>DOMImpl</code> object. Depending on whether
      the stylesheet had any calls to the <code>document()</code> function this
      method will either generate a <code>DOMAdapter</code> object (when only one
      XML document is used as input) or a <code>MultiDOM</code> object (when there
      are more than one XML input documents). This DOM object is passed on to
      the <code>topLevel()</code> method.</p>
  
      <p>When the <code>topLevel()</code> method returns we initiate the output
      document by calling <code>startDocument()</code> on the supplied output
      handler object. We then call <code>applyTemplates()</code> to get the actual
      output contents, before we close the output document by calling
      <code>endDocument()</code> on the output handler.</p>
  
      <p><code>public void topLevel(DOM, NodeIterator, TransletOutputHandler);</code></p>
  
      <p>This method handles all of these top-level elements:</p>
      <ul>
        <li><code>&lt;xsl:output&gt;</code></li>
        <li><code>&lt;xsl:decimal-format&gt;</code></li>
        <li><code>&lt;xsl:key&gt;</code></li>
        <li><code>&lt;xsl:param&gt;</code> (for global parameters)</li>
        <li><code>&lt;xsl:variable&gt;</code> (for global variables)</li>
      </ul>
  
      <p><code>public void applyTemplates(DOM, NodeIterator, TransletOutputHandler);</code></p>
  
      <p>This is the method that produces the actual output. Its central element
      is a big <code>switch()</code> statement that is used to choose the available
      templates for the various node in the input document. See the chapter
      <link anchor="mainloop">Main Program Loop</link> for details on this method.</p>
  
      <p><code>public void &lt;init&gt; ();</code></p>
      <anchor name="namesarray"/>
      <p>The translet's constructor initializes a table
      of all the elements we want to search for in the XML input document.
      This table is called the <code>namesArray</code> and it is passed to the DOM
      holding the input XML document.</p>
  
      <p>The constructor also initializes any <code>DecimalFormatSymbol</code>
      objects that are used to format numbers before passing them to the
      output handler.</p>
  
      <p><code>public boolean stripSpace(int nodeType);</code></p>
  
      <p>This method is only present if any <code>&lt;xsl:strip-space&gt;</code> or
      <code>&lt;xsl:preserve-space&gt;</code> elements are present in the stylesheet.
      If that is the case, the translet implements the
      <code>StripWhitespaceFilter</code> interface by containing this method.</p>
  
      </s2><anchor name="types"/>
      <s2 title="External/internal type mapping">
  
      <anchor name="external-types"/>
  
      <p>This is the very core of XSL transformations: <em>Read carefully!!!</em></p>
  
      <p>Every node in the input XML document(s) is assigned a type by the
      DOM builder class. This type is an integer value which represents the
      element, so that for instance all <code>&lt;bob&gt;</code> elements in the
      input document will be given type <ref>7</ref> and can be referred to by using
      that integer. These types can be used for lookups in the
      <link anchor="namesarray">namesArray</link> table to get the actual
      element name (in this case "bob"). These types are referred to as
      <em>external types</em> or <em>DOM types</em>, as they are types known only
      to the DOM and the DOM builder.</p>
  
      <anchor name="internal-types"/>
  
      <p>Similarly the translet assignes types to all element and attribute names
      that are referenced in the stylesheet. These types are referred to as
      <em>internal types</em> or <em>translet types</em>.</p>
  
      <p>It is not very probable that there will be a one-to-one mapping between
      internal and external types. There will most often be elements in the DOM
      (ie. the input document) that are not mentioned in the stylesheet, and
      there could be elements in the stylesheet that do not match any elements
      in the DOM. Here is an example:</p>
  
  <source>
        &lt;?xml version="1.0"?&gt;
        &lt;xsl:stylesheet version="1.0" xmlns:xsl="blahblahblah"&gt;
  
        &lt;xsl:template match="/"&gt;
          &lt;xsl:for-each select="//B"&gt;
            &lt;xsl:apply-templates select="." /&gt;
          &lt;/xsl:for-each&gt;
          &lt;xsl:for-each select="C"&gt;
            &lt;xsl:apply-templates select="." /&gt;
          &lt;/xsl:for-each&gt;
          &lt;xsl:for-each select="A/B"&gt;
            &lt;xsl:apply-templates select="." /&gt;
          &lt;/xsl:for-each&gt;
        &lt;/xsl:template&gt;
  
      &lt;/xsl:stylesheet&gt;
  </source>
  
      <p>In this stylesheet we are looking for elements <code>&lt;B&gt;</code>,
      <code>&lt;C&gt;</code> and <code>&lt;A&gt;</code>. For this example we can assume
      that these element types will be assigned the values 0, 1 and 2. Now, lets
      say we are transforming this XML document:</p>
  
  <source>
        &lt;?xml version="1.0"?&gt;
  
        &lt;A&gt;
          The crocodile cried:
          &lt;F&gt;foo&lt;/F&gt;
          &lt;B&gt;bar&lt;/B&gt;
          &lt;B&gt;baz&lt;/B&gt;
        &lt;/A&gt;
  </source>
  
      <p>This XML document has the elements <code>&lt;A&gt;</code>,
      <code>&lt;B&gt;</code> and <code>&lt;F&gt;</code>, which we assume are assigned the
      types 7, 8 and 9 respectively  (the numbers below that are assigned for
      specific element types, such as the root node, text nodes, etc.). This
      causes a mismatch between the type used for <code>&lt;B&gt;</code> in the
      translet and the type used for <code>&lt;B&gt;</code> in the DOM. Th
      DOMAdapter class (which mediates between the DOM and the translet) has been
      given two tables for convertint between the two types; <code>mapping</code> for
      mapping from internal to external types, and <code>reverseMapping</code> for
      the other way around.</p>
  
      <p>The translet contains a <code>String[]</code> array called
      <code>namesArray</code>. This array will contain all the element and attribute
      names that were referenced in the stylesheet. In our example, this array
      would contain these string (in this specific order): &quot;B&quot;, 
      &quot;C&quot; and &quot;A&quot;. This array is passed as one of the
      parameters to the DOM adapter constructor (the other adapter is the DOM
      itself). The DOM adapter passes this table on to the DOM. The DOM has
      a hashtable that maps known element names to external types. The DOM goes
      through the <code>namesArray</code> from the DOM sequentially, looks up each
      name in the hashtable, and is then able to map the internal type to an
      external type. The result is then passed back to the DOM adapter.</p>
  
      <p>The reverse is done for external types. External types that are not
      interesting for the translet (such as the type for <code>&lt;F&gt;</code>
      elements in the example above) are mapped to a generic <code>"ELEMENT"</code>
      type 3, and are more or less ignored by the translet.</p>
  
      <p>It is important that we separate the DOM from the translet. In several
      cases we want the DOM as a structure completely independent from the
      translet - even though the DOM is a structure internal to XSLTC. One such
      case is when transformations are offered by a servlet as a web service.
      Any DOM that is built should potentially be stored in a cache and made
      available for simultaneous access by several translet/servlet couples.</p>
  
      <p><img src="runtime_type_mapping.gif" alt="runtime_type_mapping.gif"/></p>
      <p><ref>Figure 1: Two translets accessing a single dom using different type mappings</ref></p>
  
      </s2><anchor name="mainloop"/>
      <s2 title="Main program loop">
  
      <p>The main loop in the translet is found in the <code>applyTemplates()</code>
      method. This method goes through these steps:</p>
  
      <ul>
        <li>
          Get the next node from the node iterator
        </li>
        <li>
          Get the internal type of this node. The DOMAdapter object holds the
          internal/external type mapping table, and it will supply the translet
          with the internal type of the current node.
        </li>
        <li>
          Execute a switch statement on the internal node type. There will be
          one "case" label for each recognised node type - this includes the
          first 7 internal node types.
        </li>
      </ul>
  
      <p>The root node will have internal type 0 and will cause any initial
      literal elements to be output. Text nodes will have internal node type 1
      and will simply be dumped to the output handler. Unrecognized elements
      will have internal node type 3 and will be given the default treatment
      (a new iterator is created for the node's children, and this iterator
      is passed with a recursive call to <code>applyTemplates()</code>).
      Unrecognised attribute nodes (type 4) will be handled like text nodes.
      The <code>switch()</code> statement in <code>applyTemplates</code> will thereby
      look something like this:</p>
  
  <source>
          public void applyTemplates(DOM dom, NodeIterator,
                                     TransletOutputHandler handler) {
  
              // get nodes from iterator
              while ((node = iterator.next()) != END) {
                  // get internal node type
                  switch(DOM.getType(node)) {
  
                  case 0: // root
                      outputPreable(handler);
                      break;
                  case 1: // text
                      DOM.characters(node,handler);
                      break;
                  case 3: // unrecognised element
                      NodeIterator newIterator = DOM.getChildren(node);
                      applyTemplates(DOM,newIterator,handler);
                      break;
                  case 4: // unrecognised attribute
                      DOM.characters(node,handler);
                      break;
                  case 7: // elements of type &lt;B&gt;
                      someCompiledCode();
                      break;
                  case 8: // elements of type &lt;C&gt;
                      otherCompiledCode();
                      break;
                  default:
                      break;
                  }
              }
          }
  </source>
  
      <p>Each recognised element will have its own piece of compiled code.</p>
  
      <p>Note that each "case" will not lead directly to a single template.
      There may be several templates that match node type 7
      (say <code>&lt;B&gt;</code>). In the sample stylesheet in the previous chapter
      we have to templates that would match a node <code>&lt;B&gt;</code>. We have
      one <code>match="//B"</code> (match just any <code>&lt;B&gt;</code> element) and
      one <code>match="A/B"</code> (match a <code>&lt;B&gt;</code> element that is a
      child of a <code>&lt;A&gt;</code> element). In this case we would have to
      compile code that first gets the type of the current node's parent, and
      then compared this type with the type for <code>&lt;A&gt;</code>. If there was
      no match we will have executed the first <code>&lt;xsl:for-each&gt;</code>
      element, but if there was a match we will have executed the last one.
      Consequentally, the compiler will generate the following code:</p>
  
  <source>
          switch(DOM.getType(node)) {
            :
            :
          case 7: // elements of type &lt;B&gt;
              int parent = DOM.getParent(node);
              if (DOM.getType(parent) == 9) // type 9 = elements &lt;A&gt;
                  someCompiledCode();
              else
                  evenOtherCompiledCode();
              break;
            :
            :
          }
  </source>
  
      <p>We could do the same for namespaces, that is, assign a numeric value
      to every namespace that is references in the stylesheet, and use an
      <code>"if"</code> statement for each namespace that needs to be checked for
      each type. Lets say we had a stylesheet like this:</p>
  
  <source>
        &lt;?xml version="1.0"?&gt;
        &lt;xsl:stylesheet version="1.0" xmlns:xsl="blahblahblah"&gt;
  
        &lt;xsl:template match="/"
            xmlns:foo="http://foo.com/spec"
            xmlns:bar="http://bar.net/ref"&gt;
          &lt;xsl:for-each select="foo:A"&gt;
            &lt;xsl:apply-templates select="." /&gt;
          &lt;/xsl:for-each&gt;
          &lt;xsl:for-each select="bar:A"&gt;
            &lt;xsl:apply-templates select="." /&gt;
          &lt;/xsl:for-each&gt;
        &lt;/xsl:template&gt;
  
      &lt;/xsl:stylesheet&gt;
  </source>
  
      <p>And a stylesheet like this:</p>
  
  <source>
        &lt;?xml version="1.0"?&gt;
  
        &lt;DOC
            xmlns:foo="http://foo.com/spec"
            xmlns:bar="http://bar.net/ref"&gt;
          &lt;foo:A&gt;In foo namespace&lt;/foo:A&gt;
          &lt;bar:A&gt;In bar namespace&lt;/bar:A&gt;
        &lt;/DOC&gt;
  </source>
  
      <p>We could still keep the same type for all <code>&lt;A&gt;</code> elements
      regardless of what namespace they are in, and use the same <code>"if"</code>
      structure within the <code>switch()</code> statement above. The other option
      is to assign different types to <code>&lt;foo:A&gt;</code> and
      <code>&lt;bar:A&gt;</code> elements.</p>
  
    </s2>
  </s1>
  
  
  1.1                  xml-xalan/java/xdocs/sources/xsltc/xsltover.xml
  
  Index: xsltover.xml
  ===================================================================
  <?xml version="1.0" standalone="no"?>
  <!DOCTYPE s1 SYSTEM "../../style/dtd/document.dtd">
  
  <!--
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   -->
   
  
  <s1 title="XSLT Compiler and Runtime">
     
     <s2 title="Using the Command-Line Utility">
  
     </s2>
  </s1>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org