You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mo...@apache.org on 2001/05/01 15:16:24 UTC

cvs commit: xml-xalan/java/src/org/apache/xalan/xsltc/runtime AbstractTranslet.java AttributeList.java DefaultRun.java DefaultSAXOutputHandler.java TextOutput.java

morten      01/05/01 06:16:23

  Modified:    java/src/org/apache/xalan/xsltc/compiler LiteralElement.java
                        Parser.java SymbolTable.java Template.java
                        XslElement.java
               java/src/org/apache/xalan/xsltc/dom DOMImpl.java
                        DTDMonitor.java DocumentCache.java
                        LoadDocument.java
               java/src/org/apache/xalan/xsltc/runtime
                        AbstractTranslet.java AttributeList.java
                        DefaultRun.java DefaultSAXOutputHandler.java
                        TextOutput.java
  Log:
  xsltc/compiler/LiteralElement.java and
  xsltc/compiler/XslElement.java:
    o) moved handling of xsl:exclude-result-prefixes and
       xsl:extension-element-prefixes to compiler/SymbolTable.java
    o) improved handling of namespaces.
  xsltc/compiler/Parser.java:
    o) added two static QName instances containing xsl:exclude-result-prefixes
       and xsl:extension-element-prefixes (for comparisons in SymbolTable)
  xsltc/compiler/SymbolTable.java:
    o) added global handling of xsl:exclude-result-prefixes and
       xsl:extension-element-prefixes. Namespace declarations are (if possible)
       excluded in the respective element and its children.
  xsltc/dom/DOMImpl.java:
    o) added loads of comments to most methods
    o) updated DOM builder inner class to handle SAX2 events
    o) improved and simplified namespace handling
  
  PR: n/a
  Obtained from: n/a
  Submitted by:	Morten@xml.apache.org
  Reviewed by:	Nobody
  
  Revision  Changes    Path
  1.2       +52 -59    xml-xalan/java/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
  
  Index: LiteralElement.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/LiteralElement.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LiteralElement.java	2001/04/17 18:51:34	1.1
  +++ LiteralElement.java	2001/05/01 13:16:18	1.2
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: LiteralElement.java,v 1.1 2001/04/17 18:51:34 sboag Exp $
  + * @(#)$Id: LiteralElement.java,v 1.2 2001/05/01 13:16:18 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -67,7 +67,7 @@
   import java.util.Hashtable;
   import java.util.Enumeration;
   import java.util.Vector;
  -import java.util.StringTokenizer;
  +
   import org.w3c.dom.*;
   import com.sun.xml.tree.ElementEx;
   
  @@ -78,7 +78,6 @@
       private String _name;
       private QName _qname;
       private Hashtable _accessedPrefixes = null;
  -    private final Hashtable _exclude = new Hashtable();
       private LiteralElement _parent;
   
       /**
  @@ -98,12 +97,23 @@
       }
   
       /**
  +     * Returns the namespace URI for which a prefix is pointing to
  +     */
  +    public String lookupNamespace(String prefix) {
  +	if (_accessedPrefixes == null)
  +	    return(null);
  +	else
  +	    return((String)_accessedPrefixes.get(prefix));
  +    }
  +
  +    /**
        * Method used to keep track of what namespaces that are references by
        * this literal element and its attributes. The output must contain a
        * definition for each namespace, so we stuff them in a hashtable.
        */
       public void registerNamespace(String prefix, String uri,
   				  SymbolTable stable, boolean declared) {
  +
   	// Check if the parent has a declaration for this namespace
   	if (_parent != null) {
   	    final String parentUri = _parent.lookupNamespace(prefix);
  @@ -135,16 +145,6 @@
       }
   
       /**
  -     * Returns the namespace URI for which a prefix is pointing to
  -     */
  -    public String lookupNamespace(String prefix) {
  -	if (_accessedPrefixes == null)
  -	    return(null);
  -	else
  -	    return((String)_accessedPrefixes.get(prefix));
  -    }
  -
  -    /**
        * Translates the prefix of a QName according to the rules set in
        * the attributes of xsl:stylesheet. Also registers a QName to assure
        * that the output element contains the necessary namespace declarations.
  @@ -163,8 +163,7 @@
   	// Check if we must translate the prefix
   	final String alternative = stable.lookupPrefixAlias(prefix);
   	if (alternative != null) {
  -	    String uri = stable.lookupNamespace(prefix);
  -	    _exclude.put(uri, uri);
  +	    stable.excludeNamespaces(prefix);
   	    prefix = alternative;
   	}
   
  @@ -183,36 +182,13 @@
       }
   
       /**
  -     *
  -     */
  -    private void excludeNamespaces(String prefixes, SymbolTable stable) {
  -
  -	// Get prefixes and traverse them
  -	StringTokenizer tokens = new StringTokenizer(prefixes);
  -	while (tokens.hasMoreTokens()) {
  -	    // Get next prefix - special case for default namespace
  -	    String prefix = tokens.nextToken();
  -	    if (prefix.equals("#default")) prefix = "";
  -	    // Get the matching URI and store in hashtable.
  -	    String uri = stable.lookupNamespace(prefix);
  -	    if (uri != null) _exclude.put(uri, uri);
  -	}
  -	
  -    }
  -
  -    int called = 0;
  -    
  -    /**
        * Determines the final QName for the element and its attributes.
        * Registers all namespaces that are used by the element/attributes
        */
       public void parseContents(ElementEx element, Parser parser) {
   	final SymbolTable stable = parser.getSymbolTable();
  -
  -	// Create hashtable to hold namespace URIs
  -	_exclude.put("","");
   
  -	// Get any literal element ancestor
  +	// Find the closest literal element ancestor (if there is one)
   	SyntaxTreeNode _parent = getParent();
   	while ((_parent != null) && !(_parent instanceof LiteralElement))
   	    _parent = _parent.getParent();
  @@ -225,50 +201,67 @@
   	// Process all attributes and register all namespaces they use
   	final NamedNodeMap attributes = element.getAttributes();
   	for (int i = 0; i < attributes.getLength(); i++) {
  +
   	    final Attr attribute = (Attr)attributes.item(i);
   	    final QName qname = parser.getQName(attribute.getName());
   	    final String val = attribute.getValue();
   
  -	    // Namespace declarations are handled separately !!!
  -	    if (qname != parser.getUseAttributeSets()) {
  -		// First check that the attribute is not in the XSL namespace
  -		if (qname.getPrefix() != null) {
  -		    final String ns = stable.lookupNamespace(qname.getPrefix());
  -		    if ((ns != null) && (ns.equals(XSLT_URI))) {
  -			final String local = qname.getLocalPart();
  -			if (local.equals("exclude-result-prefixes"))
  -			    excludeNamespaces(val, stable);
  -			continue;
  -		    }
  -		}
  -		// Then add the attribute to the element
  +	    // Handle xsl:use-attribute-sets
  +	    if (qname == parser.getUseAttributeSets()) {
  +		addElement(new UseAttributeSets(val, parser));
  +	    }
  +	    // Handle xsl:extension-element-prefixes
  +	    else if (qname == parser.getExtensionElementPrefixes()) {
  +		stable.excludeNamespaces(val);
  +	    }
  +	    // Handle xsl:exclude-result-prefixes
  +	    else if (qname == parser.getExcludeResultPrefixes()) {
  +		stable.excludeNamespaces(val);
  +	    }
  +	    // Ignore other attributes in XSL namespace
  +	    else if (qname.getNamespace() == XSLT_URI) {
  +		
  +	    }
  +	    // Handle literal attributes (attributes not in XSL namespace)
  +	    else {
  +		// Namespace declarations are handled separately !!!
   		final String name = translateQName(qname,stable);
   		if (!name.startsWith("xmlns"))
   		    addElement(new LiteralAttribute(name, val, parser));
   	    }
  -	    else {
  -		addElement(new UseAttributeSets(val, parser));
  -	    }
   	}
   
   	// Register all namespaces that are in scope, except for those that
   	// are listed in the xsl:stylesheet element's *-prefixes attributes
  -	final Hashtable   exclude = stable.getExcludedNamespaces();
   	final Enumeration include = stable.getInScopeNamespaces();
   	while (include.hasMoreElements()) {
   	    final String prefix = (String)include.nextElement();
   	    if (!prefix.equals("xml")) {
   		final String uri = stable.lookupNamespace(prefix);
   		if ((uri != null) && (!uri.equals(XSLT_URI))) {
  -		    if ((exclude.get(uri) == null) &&
  -			(_exclude.get(uri) == null)) {
  +		    if (!stable.isExcludedNamespace(uri))
   			registerNamespace(prefix,uri,stable,true);
  -		    }
   		}
   	    }
   	}
   
   	parseChildren(element, parser);
  +
  +	// Process all attributes and register all namespaces they use
  +	for (int i = 0; i < attributes.getLength(); i++) {
  +	    final Attr attribute = (Attr)attributes.item(i);
  +	    final QName qname = parser.getQName(attribute.getName());
  +	    final String val = attribute.getValue();
  +
  +	    // Handle xsl:extension-element-prefixes
  +	    if (qname == parser.getExtensionElementPrefixes()) {
  +		stable.unExcludeNamespaces(val);
  +	    }
  +	    // Handle xsl:exclude-result-prefixes
  +	    else if (qname == parser.getExcludeResultPrefixes()) {
  +		stable.unExcludeNamespaces(val);
  +	    }
  +	}
       }
   
       /**
  
  
  
  1.2       +15 -1     xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Parser.java
  
  Index: Parser.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Parser.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Parser.java	2001/04/17 18:51:42	1.1
  +++ Parser.java	2001/05/01 13:16:19	1.2
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: Parser.java,v 1.1 2001/04/17 18:51:42 sboag Exp $
  + * @(#)$Id: Parser.java,v 1.2 2001/05/01 13:16:19 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -97,6 +97,8 @@
       private Hashtable   _qNames;
       private Hashtable   _namespaces;
       private QName       _useAttributeSets;
  +    private QName       _excludeResultPrefixes;
  +    private QName       _extensionElementPrefixes;
       private Hashtable   _variableScope;
       private Stylesheet  _currentStylesheet;
       private SymbolTable _symbolTable; // Maps QNames to syntax-tree nodes
  @@ -134,6 +136,10 @@
   	initSymbolTable();
   	
   	_useAttributeSets = getQName(XSLT_URI, XSL, "use-attribute-sets");
  +	_excludeResultPrefixes
  +	    = getQName(XSLT_URI, XSL, "exclude-result-prefixes");
  +	_extensionElementPrefixes
  +	    = getQName(XSLT_URI, XSL, "extension-element-prefixes");
       }
       
       public void addVariable(Variable var) {
  @@ -256,6 +262,14 @@
   
       public QName getUseAttributeSets() {
   	return _useAttributeSets;
  +    }
  +
  +    public QName getExtensionElementPrefixes() {
  +	return _extensionElementPrefixes;
  +    }
  +
  +    public QName getExcludeResultPrefixes() {
  +	return _excludeResultPrefixes;
       }
       
       /**	
  
  
  
  1.2       +53 -17    xml-xalan/java/src/org/apache/xalan/xsltc/compiler/SymbolTable.java
  
  Index: SymbolTable.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/SymbolTable.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SymbolTable.java	2001/04/17 18:51:48	1.1
  +++ SymbolTable.java	2001/05/01 13:16:19	1.2
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: SymbolTable.java,v 1.1 2001/04/17 18:51:48 sboag Exp $
  + * @(#)$Id: SymbolTable.java,v 1.2 2001/05/01 13:16:19 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -66,6 +66,7 @@
   import java.util.Vector;
   import java.util.Hashtable;
   import java.util.Enumeration;
  +import java.util.StringTokenizer;
   
   import org.apache.xalan.xsltc.compiler.util.*;
   
  @@ -233,30 +234,65 @@
       }
   
       /**
  -     * Adds a namespace to the list of URIs that should _NOT_ be included
  -     * in all literal result elements
  +     *
        */
  -    public void excludeNamespace(String prefix) {
  -	String uri;
  -	if (prefix.equals("#default"))
  -	    uri = lookupNamespace("");
  +    public void excludeURI(String uri) {
  +	if (uri == null) return;
  +	Integer refcnt = (Integer)_excludedURI.get(uri);
  +	if (refcnt == null)
  +	    refcnt = new Integer(1);
   	else
  -	    uri = lookupNamespace(prefix);
  -	if (uri != null) {
  -	    _excludedURI.put(uri,uri);
  +	    refcnt = new Integer(refcnt.intValue() + 1);
  +	_excludedURI.put(uri,refcnt);
  +    }
  +
  +    /**
  +     *
  +     */
  +    public void excludeNamespaces(String prefixes) {
  +	if (prefixes != null) {
  +	    StringTokenizer tokens = new StringTokenizer(prefixes);
  +	    while (tokens.hasMoreTokens()) {
  +		final String prefix = tokens.nextToken();
  +		final String uri;
  +		if (prefix.equals("#default"))
  +		    uri = lookupNamespace("");
  +		else
  +		    uri = lookupNamespace(prefix);
  +		if (uri != null) excludeURI(uri);
  +	    }
   	}
       }
   
  -    public void excludeURI(String uri) {
  -	if (uri != null) _excludedURI.put(uri, uri);
  +    /**
  +     *
  +     */
  +    public boolean isExcludedNamespace(String uri) {
  +	if (uri == null) return false;
  +	final Integer refcnt = (Integer)_excludedURI.get(uri);
  +	if (refcnt == null) return false;
  +	if (refcnt.intValue() > 0) return true;
  +	return false;
       }
   
       /**
  -     * Returns a hashtable with all namespace URIs that should _NOT_
  -     * be included in literal result elements (unless referenced within
  -     * the element).
  +     *
        */
  -    public Hashtable getExcludedNamespaces() {
  -	return(_excludedURI);
  +    public void unExcludeNamespaces(String prefixes) {
  +	if (prefixes != null) {
  +	    StringTokenizer tokens = new StringTokenizer(prefixes);
  +	    while (tokens.hasMoreTokens()) {
  +		final String prefix = tokens.nextToken();
  +		final String uri;
  +		if (prefix.equals("#default"))
  +		    uri = lookupNamespace("");
  +		else
  +		    uri = lookupNamespace(prefix);
  +		Integer refcnt = (Integer)_excludedURI.get(uri);
  +		if (refcnt != null)
  +		    _excludedURI.put(uri, new Integer(refcnt.intValue() - 1));
  +	    }
  +	}	
       }
   }
  +
  
  
  
  1.2       +1 -3      xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Template.java
  
  Index: Template.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Template.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Template.java	2001/04/17 18:51:48	1.1
  +++ Template.java	2001/05/01 13:16:19	1.2
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: Template.java,v 1.1 2001/04/17 18:51:48 sboag Exp $
  + * @(#)$Id: Template.java,v 1.2 2001/05/01 13:16:19 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -281,8 +281,6 @@
   	final InstructionList il = methodGen.getInstructionList();
   
   	if (_disabled) return;
  -
  -
   	// bug fix #4433133, add a call to named template from applyTemplates 
   	String className = _stylesheet.getClassName();
   	final String DOM_CLASS_SIG = classGen.getDOMClassSig();
  
  
  
  1.2       +19 -10    xml-xalan/java/src/org/apache/xalan/xsltc/compiler/XslElement.java
  
  Index: XslElement.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/XslElement.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XslElement.java	2001/04/17 18:51:54	1.1
  +++ XslElement.java	2001/05/01 13:16:19	1.2
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: XslElement.java,v 1.1 2001/04/17 18:51:54 sboag Exp $
  + * @(#)$Id: XslElement.java,v 1.2 2001/05/01 13:16:19 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -101,28 +101,30 @@
       public void parseContents(ElementEx element, Parser parser) {
   
   	final SymbolTable stable = parser.getSymbolTable();
  +
  +	// First try to get namespace from the namespace attribute
   	String namespace = element.getAttribute("namespace");
  +
  +	// If that is undefied we use the prefix in the supplied QName
   	String name = element.getAttribute("name");
   	QName qname = parser.getQNameSafe(name);
   	final String prefix = qname.getPrefix();
  -
  -	// Ignore this element if it refers to a non-existant namespace
   	if ((namespace == null || namespace == "") && (prefix != null)) {
   	    namespace = stable.lookupNamespace(prefix); 
   	    if (namespace == null) {
   		parser.addWarning(new ErrorMsg(ErrorMsg.NSPUNDEF_ERR, prefix));
   		parseChildren(element, parser);
  -		_ignore = true;
  +		_ignore = true; // Ignore the element if prefix is undeclared
   		return;
   	    }
   	}
   
  -	// Ignore this element if it has an illegal local name
  +	// Next check that the local part of the QName is legal (no whitespace)
   	if (qname.getLocalPart().indexOf(' ') > -1) {
   	    parser.addWarning(new ErrorMsg("You can't call an element \""+
   					   qname.getLocalPart()+"\""));
   	    parseChildren(element, parser);
  -	    _ignore = true;
  +	    _ignore = true; // Ignore the element if the local part is invalid
   	    return;
   	}
   
  @@ -132,11 +134,12 @@
   	    _namespace = new AttributeValueTemplate(namespace,parser);
   	    // Get the current prefix for that namespace (if any)
   	    _namespacePrefix = stable.lookupPrefix(namespace);
  -	    // Declare the namespace
  -	    if ((_namespacePrefix = prefix) == null)
  -		_namespacePrefix = ""; // redeclare default namespace
  +	    // Is it the default namespace?
  +	    if ((_namespacePrefix = prefix) == null) _namespacePrefix = "";
  +	    // Make this prefix-namespace mapping in scope (in symbol table)
   	    stable.pushNamespace(_namespacePrefix,namespace);
   
  +	    // Construct final element QName
   	    if (_namespacePrefix.equals(""))
   		name = qname.getLocalPart();
   	    else
  @@ -145,6 +148,7 @@
   
   	_name = AttributeValue.create(this, name, parser);
   
  +	// Handle the 'use-attribute-sets' attribute
   	final String useSets = element.getAttribute("use-attribute-sets");
   	if (useSets.length() > 0) {
   	    addElement(new UseAttributeSets(useSets, parser));
  @@ -152,6 +156,7 @@
   
   	parseChildren(element, parser);
   
  +	// Make any prefix-namespace mapping out-of-scope
   	if (_namespace != null) stable.popNamespace(_namespacePrefix);
       }
   
  @@ -170,12 +175,15 @@
   
       /**
        * Compiles code that emits the element with the necessary namespace
  -     * definitions.
  +     * definitions. The element itself is ignored if the element definition
  +     * was in any way erronous, but the child nodes are still processed.
  +     * See the overriden translateContents() method as well.
        */
       public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
   	final ConstantPoolGen cpg = classGen.getConstantPool();
   	final InstructionList il = methodGen.getInstructionList();
   
  +	// Ignore this element if not correctly declared
   	if (!_ignore) {
   	    // Compile code that emits the element start tag
   	    il.append(methodGen.loadHandler());
  @@ -199,6 +207,7 @@
   	// Compile code that emits the element attributes and contents
   	translateContents(classGen, methodGen);
   
  +	// Ignore this element if not correctly declared
   	if (!_ignore) {
   	    // Compile code that emits the element end tag
   	    il.append(methodGen.endElement());
  
  
  
  1.3       +2416 -2345xml-xalan/java/src/org/apache/xalan/xsltc/dom/DOMImpl.java
  
  Index: DOMImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/DOMImpl.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DOMImpl.java	2001/04/19 14:27:42	1.2
  +++ DOMImpl.java	2001/05/01 13:16:20	1.3
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: DOMImpl.java,v 1.2 2001/04/19 14:27:42 curcuru Exp $
  + * @(#)$Id: DOMImpl.java,v 1.3 2001/05/01 13:16:20 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -76,11 +76,14 @@
   import java.util.Hashtable;
   import java.util.Dictionary;
   import java.util.Enumeration;
  +import java.util.Stack;
  +
   import org.w3c.dom.Node;
   import org.w3c.dom.NodeList;
   import org.w3c.dom.DOMException;
   import org.w3c.dom.NamedNodeMap;
   import org.w3c.dom.Document;
  +
   import org.xml.sax.*;
   import org.apache.xalan.xsltc.*;
   import org.apache.xalan.xsltc.util.IntegerArray;
  @@ -92,468 +95,520 @@
       // empty String for null attribute values
       private final static String EMPTYSTRING = "";
   
  -
       // empty iterator to be returned when there are no children
  -    private final static NodeIterator EMPTYITERATOR =
  -         new NodeIterator() {
  -                  public NodeIterator reset() { return this; }
  -                  public NodeIterator setStartNode(int node) { return this; }
  -                  public int next() { return NULL; }
  -                  public void setMark() {}
  -                  public void gotoMark() {}
  -                  public int getLast() { return 0; }
  -                  public int getPosition() { return 0; }
  -                  public NodeIterator cloneIterator() { return this; }
  -                  public boolean isReverse() { return false; }
  -                  public NodeIterator resetOnce() { return this; }
  -             };
  -
  -    // empty attribute list to be returned for nodes with no attributes
  -    private static final AttributeList EmptyAttributes =
  -         new AttributeList() {
  -                  public int getLength() { return 0; }
  -                  public String getName(int i) { return null; }
  -                  public String getType(int i) { return null; }
  -                  public String getValue(int i) { return null; }
  -                  public String getType(String name) { return null; }
  -                  public String getValue(String name) { return null; }
  -             };
  +    private final static NodeIterator EMPTYITERATOR = new NodeIterator() {
  +	    public NodeIterator reset() { return this; }
  +	    public NodeIterator setStartNode(int node) { return this; }
  +	    public int next() { return NULL; }
  +	    public void setMark() {}
  +	    public void gotoMark() {}
  +	    public int getLast() { return 0; }
  +	    public int getPosition() { return 0; }
  +	    public NodeIterator cloneIterator() { return this; }
  +	    public boolean isReverse() { return false; }
  +	    public NodeIterator resetOnce() { return this; }
  +	};
   
  -    // document tree representation data structures
  +    // Contains the number of nodes and attribute nodes in the tree
       private int       _treeNodeLimit;
       private int       _firstAttributeNode;
  +
  +    // Node-to-type, type-to-name, and name-to-type mappings
       private short[]   _type;
  -    private short[]   _namespace;
  +    private Hashtable _types = null;
  +    private String[]  _namesArray;
  +
  +    // Tree navigation arrays
       private int[]     _parent;
       private int[]     _nextSibling;
  -    private int[]     _offsetOrChild;
  -    private int[]     _lengthOrAttr;
  +    private int[]     _offsetOrChild; // Serves two purposes !!!
  +    private int[]     _lengthOrAttr;  // Serves two purposes !!!
  +
  +    // Holds contents of text/comment nodes and attribute values
       private char[]    _text;
  -    private String[]  _namesArray;
  -    private String[]  _nsNamesArray;
  -    private BitArray  _whitespace;
  -    private short[]   _mapping = null;
   
  -    private Hashtable _types = null;
  +    // Namespace related stuff
  +    private String[]  _nsNamesArray;
  +    private short[]   _namespace;
       private Hashtable _nsIndex = new Hashtable();
  +    private int       _nsCounter = 0;
   
  -    private String    _documentURI;
  +    // Tracks which textnodes are whitespaces and which are not
  +    private BitArray  _whitespace; // takes xml:space into acc.
   
  -    private int nsCounter = 0;
  +    // The URI to this document
  +    private String    _documentURI;
   
  -    private String generateNamespacePrefix() {
  -         return(new String("ns"+Integer.toString(nsCounter++)));
  -    }
  +    // Support for access/navigation through org.w3c.dom API
  +    private Node[] _nodes;
  +    private NodeList[] _nodeLists;
  +    private static NodeList EmptyNodeList;
  +    private static NamedNodeMap EmptyNamedNodeMap;
   
  +    /**
  +     * Define the origin of the document from which the tree was built
  +     */
       public void setDocumentURI(String uri) {
  -         _documentURI = uri;
  +	_documentURI = uri;
       }
   
  +    /**
  +     * Returns the origin of the document from which the tree was built
  +     */
       public String getDocumentURI() {
  -         return(_documentURI);
  +	return(_documentURI);
       }
   
  -    public void setFilter(StripWhitespaceFilter filter) { }
  +    /**
  +     * Generates a namespace prefix for URIs that have no associated
  +     * prefix. Can happen quite frequently since we do not store
  +     * namespace prefixes in the tree (we only store the URIs).
  +     */
  +    private String generateNamespacePrefix() {
  +	return(new String("ns"+Integer.toString(_nsCounter++)));
  +    }
   
  +    /**
  +     * Returns 'true' if a specific node is an element (of any type)
  +     */
       private boolean isElement(final int node) {
  -         return ((node < _treeNodeLimit) && (_type[node] >= NTYPES));
  +	return ((node < _treeNodeLimit) && (_type[node] >= NTYPES));
       }
   
  +    /**
  +     * Returns the number of nodes in the tree (used for indexing)
  +     */
       public int getSize() {
  -         return(_type.length);
  +	return(_type.length);
       }
   
  +    /**
  +     * Returns true if node1 comes before node2 in document order
  +     */
       public boolean lessThan(int node1, int node2) {
  -         if ((node2 < _treeNodeLimit) && (node1 < node2))
  -             return(true);
  -         else
  -             return(false);
  +	if ((node2 < _treeNodeLimit) && (node1 < node2))
  +	    return(true);
  +	else
  +	    return(false);
       }
   
  -    // Support for access/navigation through org.w3c.dom API
  -    private Node[] _nodes;
  -
  +    /**
  +     * Create an org.w3c.dom.Node from a node in the tree
  +     */
       public Node makeNode(int index) {
  -    if (_nodes == null) {
  -             _nodes = new Node[_type.length];
  -         }
  -         return _nodes[index] != null
  -             ? _nodes[index]
  -             : (_nodes[index] = new NodeImpl(index));
  +	if (_nodes == null) {
  +	    _nodes = new Node[_type.length];
  +	}
  +	return _nodes[index] != null
  +	    ? _nodes[index]
  +	    : (_nodes[index] = new NodeImpl(index));
       }
   
  +    /**
  +     * Create an org.w3c.dom.Node from a node in an iterator
  +     * The iterator most be started before this method is called
  +     */
       public Node makeNode(NodeIterator iter) {
  -         return makeNode(iter.next());         // iter must be started
  +	return makeNode(iter.next());
       }
  -
  -    private NodeList[] _nodeLists;
   
  +    /**
  +     * Create an org.w3c.dom.NodeList from a node in the tree
  +     */
       public NodeList makeNodeList(int index) {
  -         if (_nodeLists == null) {
  -             _nodeLists = new NodeList[_type.length];
  -         }
  -         return _nodeLists[index] != null
  -             ? _nodeLists[index]
  -             : (_nodeLists[index] = new NodeListImpl(index));
  +	if (_nodeLists == null) {
  +	    _nodeLists = new NodeList[_type.length];
  +	}
  +	return _nodeLists[index] != null
  +	    ? _nodeLists[index]
  +	    : (_nodeLists[index] = new NodeListImpl(index));
       }
   
  +    /**
  +     * Create an org.w3c.dom.NodeList from a node iterator
  +     * The iterator most be started before this method is called
  +     */
       public NodeList makeNodeList(NodeIterator iter) {
  -         return new NodeListImpl(iter);         // iter must be started
  +	return new NodeListImpl(iter);
       }
   
  -    private final class NotSupportedException extends DOMException {
  -         public NotSupportedException() {
  -             super(NOT_SUPPORTED_ERR, "modification not supported");
  -         }
  -    } // end of NotSupportedException
  -         
  -    private static NodeList EmptyNodeList;
  -    private static NamedNodeMap EmptyNamedNodeMap;
  -         
  +    /**
  +     * Create an empty org.w3c.dom.NodeList
  +     */
       private NodeList getEmptyNodeList() {
  -         return EmptyNodeList != null
  -             ? EmptyNodeList
  -             : (EmptyNodeList = new NodeListImpl(new int[0]));
  +	return EmptyNodeList != null
  +	    ? EmptyNodeList
  +	    : (EmptyNodeList = new NodeListImpl(new int[0]));
       }
   
  +    /**
  +     * Create an empty org.w3c.dom.NamedNodeMap
  +     */
       private NamedNodeMap getEmptyNamedNodeMap() {
  -         return EmptyNamedNodeMap != null
  -             ? EmptyNamedNodeMap
  -             : (EmptyNamedNodeMap = new NamedNodeMapImpl(new int[0]));
  +	return EmptyNamedNodeMap != null
  +	    ? EmptyNamedNodeMap
  +	    : (EmptyNamedNodeMap = new NamedNodeMapImpl(new int[0]));
       }
   
  +    /**
  +     * Exception thrown by methods in inner classes implementing
  +     * various org.w3c.dom interfaces (below)
  +     */
  +    private final class NotSupportedException extends DOMException {
  +	public NotSupportedException() {
  +	    super(NOT_SUPPORTED_ERR, "modification not supported");
  +	}
  +    }
  +
  +    /**************************************************************
  +     * Implementation of org.w3c.dom.NodeList
  +     */
       private final class NodeListImpl implements NodeList {
  -         private final int[] _nodes;
  +	private final int[] _nodes;
  +
  +	public NodeListImpl(int node) {
  +	    _nodes = new int[1];
  +	    _nodes[0] = node;
  +	}
   
  -         public NodeListImpl(int node) {
  -             _nodes = new int[1];
  -             _nodes[0] = node;
  -         }
  -
  -         public NodeListImpl(int[] nodes) {
  -             _nodes = nodes;
  -         }
  -                  
  -         public NodeListImpl(NodeIterator iter) {
  -             final IntegerArray list = new IntegerArray();
  -             int node;
  -             while ((node = iter.next()) != NodeIterator.END) {
  -                  list.add(node);
  -             }         
  -             _nodes = list.toIntArray();         
  -         }
  -
  -         public int getLength() {
  -             return _nodes.length;
  -         }
  -                  
  -         public Node item(int index) {
  -             return makeNode(_nodes[index]);
  -         }
  -    } // end of NodeListImpl
  +	public NodeListImpl(int[] nodes) {
  +	    _nodes = nodes;
  +	}
                     
  -    private final class NamedNodeMapImpl implements NamedNodeMap {
  -         private final int[] _nodes;
  +	public NodeListImpl(NodeIterator iter) {
  +	    final IntegerArray list = new IntegerArray();
  +	    int node;
  +	    while ((node = iter.next()) != NodeIterator.END) {
  +		list.add(node);
  +	    }         
  +	    _nodes = list.toIntArray();         
  +	}
  +
  +	public int getLength() {
  +	    return _nodes.length;
  +	}
                     
  -         public NamedNodeMapImpl(int[] nodes) {
  -             _nodes = nodes;
  -         }
  -                  
  -         public int getLength() {
  -             return _nodes.length;
  -         }
  -                  
  -         public Node getNamedItem(String name) {
  -             for (int i = 0; i < _nodes.length; i++) {
  -                  if (name.equals(getNodeName(_nodes[i]))) {
  -                      return makeNode(_nodes[i]);
  -                  }
  -             }
  -             return null;
  -         }
  -                  
  -         public Node item(int index) {
  -             return makeNode(_nodes[index]);
  -         }
  -                  
  -         public Node removeNamedItem(String name) {
  -             throw new NotSupportedException();
  -         }
  -                  
  -         public Node setNamedItem(Node node) {
  -             throw new NotSupportedException();
  -         }
  -
  -         public Node getNamedItemNS(String uri, String local) {
  -             return(getNamedItem(uri+':'+local));
  -         }
  -
  -         public Node setNamedItemNS(Node node) {
  -             throw new NotSupportedException();
  -         }
  -
  -         public Node removeNamedItemNS(String uri, String local) {
  -             throw new NotSupportedException();
  -         }
  +	public Node item(int index) {
  +	    return makeNode(_nodes[index]);
  +	}
  +    }
   
  -    } // end of NamedNodeMapImpl
  -         
  +                  
  +    /**************************************************************
  +     * Implementation of org.w3c.dom.NamedNodeMap
  +     */
  +    private final class NamedNodeMapImpl implements NamedNodeMap {
  +
  +	private final int[] _nodes;
  +		
  +	public NamedNodeMapImpl(int[] nodes) {
  +	    _nodes = nodes;
  +	}
  +		
  +	public int getLength() {
  +	    return _nodes.length;
  +	}
  +		
  +	public Node getNamedItem(String name) {
  +	    for (int i = 0; i < _nodes.length; i++) {
  +		if (name.equals(getNodeName(_nodes[i]))) {
  +		    return makeNode(_nodes[i]);
  +		}
  +	    }
  +	    return null;
  +	}
  +		
  +	public Node item(int index) {
  +	    return makeNode(_nodes[index]);
  +	}
  +		
  +	public Node removeNamedItem(String name) {
  +	    throw new NotSupportedException();
  +	}
  +		
  +	public Node setNamedItem(Node node) {
  +	    throw new NotSupportedException();
  +	}
  +
  +	public Node getNamedItemNS(String uri, String local) {
  +	    return(getNamedItem(uri+':'+local));
  +	}
  +
  +	public Node setNamedItemNS(Node node) {
  +	    throw new NotSupportedException();
  +	}
  +
  +	public Node removeNamedItemNS(String uri, String local) {
  +	    throw new NotSupportedException();
  +	}
  +
  +    }
  +
  +
  +    /**************************************************************
  +     * Implementation of org.w3c.dom.Node
  +     */
       private final class NodeImpl implements Node {
  -         private final int _index;
   
  -         public NodeImpl(int index) {
  -             _index = index;
  -         }
  -
  -         public short getNodeType() {
  -             switch (_type[_index]) {
  -             case ROOT:
  -                  return Node.DOCUMENT_NODE;
  -                  
  -             case TEXT:
  -                  return Node.TEXT_NODE;
  -                  
  -             case PROCESSING_INSTRUCTION:
  -                  return Node.PROCESSING_INSTRUCTION_NODE;
  -                  
  -             case COMMENT:
  -                  return Node.COMMENT_NODE;
  -                  
  -             default:
  -                  return _index < _treeNodeLimit
  -                      ? Node.ELEMENT_NODE : Node.ATTRIBUTE_NODE;
  -             }
  -         }
  -                  
  -         public Node getParentNode() {
  -             final int parent = getParent(_index);
  -             return parent > NULL ? makeNode(parent) : null;
  -         }
  -                  
  -         public Node appendChild(Node node) throws DOMException {
  -             throw new NotSupportedException();
  -         }
  -                  
  -         public Node cloneNode(boolean deep) {
  -             // it can be supported if need be
  -             // with and additional field to signify
  -             // whether it is a deep or shallow clone
  -             throw new NotSupportedException();
  -         }
  -                  
  -         public NamedNodeMap getAttributes() {
  -             if (getNodeType() == Node.ELEMENT_NODE) {
  -                  int attribute = _lengthOrAttr[_index];
  -                  if (attribute != NULL) {
  -                      final IntegerArray attributes = new IntegerArray(4);
  -                      do {
  -                           attributes.add(attribute);
  -                      }
  -                      while ((attribute = _nextSibling[attribute]) != 0);
  -                      return new NamedNodeMapImpl(attributes.toIntArray());
  -                  }
  -                  else {
  -                      return getEmptyNamedNodeMap();
  -                  }
  -             }
  -             else {
  -                  return null;
  -             }
  -         }
  -
  -         public NodeList getChildNodes() {
  -             if (hasChildNodes()) {
  -                  final IntegerArray children = new IntegerArray(8);
  -                  int child = _offsetOrChild[_index];
  -                  do {
  -                      children.add(child);
  -                  }
  -                  while ((child = _nextSibling[child]) != 0);
  -                  return new NodeListImpl(children.toIntArray());
  -             }
  -             else {
  -                  return getEmptyNodeList();
  -             }
  -         }
  -                  
  -         public Node getFirstChild() {
  -             return hasChildNodes()
  -                  ? makeNode(_offsetOrChild[_index])
  -                  : null;
  -         }
  -                  
  -         public Node getLastChild() {
  -             return hasChildNodes()
  -                  ? makeNode(lastChild(_index))
  -                  : null;
  -         }
  -                  
  -         public Node getNextSibling() {
  -             final int next = _nextSibling[_index];
  -             return next != 0 ? makeNode(next) : null;
  -         }
  -                  
  -         public String getNodeName() {
  -             switch (_type[_index]) {
  -             case ROOT:
  -                  return "#document";
  -                  
  -             case TEXT:
  -                  return "#text";
  -                  
  -             case PROCESSING_INSTRUCTION:
  -                  return "***PI Name NYI";
  -                  
  -             case COMMENT:
  -                  return "#comment";
  -                  
  -             default:
  -                  return DOMImpl.this.getNodeName(_index);
  -             }
  -         }
  -                  
  -         public String getNodeValue() throws DOMException {
  -             return DOMImpl.this.getNodeValue(_index);
  -         }
  -                  
  -         public Document getOwnerDocument() {
  -             return null;
  -         }
  -                  
  -         //??? how does it work with attributes
  -         public Node getPreviousSibling() {
  -             int node = _parent[_index];
  -             if (node > NULL) {
  -                  int prev = -1;
  -                  node = _offsetOrChild[node];
  -                  while (node != _index) {
  -                      node = _nextSibling[prev = node];
  -                  }
  -                  if (prev != -1) {
  -                      return makeNode(prev);
  -                  }
  -             }
  -             return null;
  -         }
  -                  
  -         public boolean hasChildNodes() {
  -             switch (getNodeType()) {
  -             case Node.ELEMENT_NODE:
  -             case Node.DOCUMENT_NODE:
  -                  return _offsetOrChild[_index] != 0;
  -
  -             default:
  -                  return false;
  -             }
  -         }
  -                  
  -         public Node insertBefore(Node n1, Node n2) throws DOMException {
  -             throw new NotSupportedException();
  -         }
  -                  
  -         public Node removeChild(Node n) throws DOMException {
  -             throw new NotSupportedException();
  -         }
  -                  
  -         public Node replaceChild(Node n1, Node n2) throws DOMException {
  -             throw new NotSupportedException();
  -         }
  -                  
  -         public void setNodeValue(String s) throws DOMException {
  -             throw new NotSupportedException();
  -         }
  -
  -         public void normalize() {
  -             throw new NotSupportedException();
  -         }
  -
  -         public boolean isSupported(String feature, String version) {
  -             return false;
  -         }
  -
  -         public String getNamespaceURI() {
  -             return _nsNamesArray[_namespace[_type[_index] - NTYPES]];
  -         }
  -
  -         public String getPrefix() {
  -             return null; // We don't know with the current DOM implementation
  -         }
  -
  -         public void setPrefix(String prefix) {
  -             throw new NotSupportedException();
  -         }
  -
  -         public String getLocalName() {
  -             final String qname = _namesArray[_type[_index] - NTYPES];
  -             final int col = qname.lastIndexOf(':');
  -             return qname.substring(col+1);
  -         }
  -
  -         public boolean hasAttributes() {
  -             return (_lengthOrAttr[_index] != NULL);
  -         }
  +	private final int _index;
   
  -    } // end of NodeImpl
  +	public NodeImpl(int index) {
  +	    _index = index;
  +	}
  +
  +	public short getNodeType() {
  +	    switch (_type[_index]) {
  +	    case ROOT:
  +		return Node.DOCUMENT_NODE;
  +		
  +	    case TEXT:
  +		return Node.TEXT_NODE;
  +		
  +	    case PROCESSING_INSTRUCTION:
  +		return Node.PROCESSING_INSTRUCTION_NODE;
  +		
  +	    case COMMENT:
  +		return Node.COMMENT_NODE;
  +		
  +	    default:
  +		return _index < _treeNodeLimit
  +		    ? Node.ELEMENT_NODE : Node.ATTRIBUTE_NODE;
  +	    }
  +	}
  +		
  +	public Node getParentNode() {
  +	    final int parent = getParent(_index);
  +	    return parent > NULL ? makeNode(parent) : null;
  +	}
  +		
  +	public Node appendChild(Node node) throws DOMException {
  +	    throw new NotSupportedException();
  +	}
  +		
  +	public Node cloneNode(boolean deep) {
  +	    throw new NotSupportedException();
  +	}
  +		
  +	public NamedNodeMap getAttributes() {
  +	    if (getNodeType() == Node.ELEMENT_NODE) {
  +		int attribute = _lengthOrAttr[_index];
  +		if (attribute != NULL) {
  +		    final IntegerArray attributes = new IntegerArray(4);
  +		    do {
  +			attributes.add(attribute);
  +		    }
  +		    while ((attribute = _nextSibling[attribute]) != 0);
  +		    return new NamedNodeMapImpl(attributes.toIntArray());
  +		}
  +		else {
  +		    return getEmptyNamedNodeMap();
  +		}
  +	    }
  +	    else {
  +		return null;
  +	    }
  +	}
  +
  +	public NodeList getChildNodes() {
  +	    if (hasChildNodes()) {
  +		final IntegerArray children = new IntegerArray(8);
  +		int child = _offsetOrChild[_index];
  +		do {
  +		    children.add(child);
  +		}
  +		while ((child = _nextSibling[child]) != 0);
  +		return new NodeListImpl(children.toIntArray());
  +	    }
  +	    else {
  +		return getEmptyNodeList();
  +	    }
  +	}
  +		
  +	public Node getFirstChild() {
  +	    return hasChildNodes()
  +		? makeNode(_offsetOrChild[_index])
  +		: null;
  +	}
  +		
  +	public Node getLastChild() {
  +	    return hasChildNodes()
  +		? makeNode(lastChild(_index))
  +		: null;
  +	}
  +		
  +	public Node getNextSibling() {
  +	    final int next = _nextSibling[_index];
  +	    return next != 0 ? makeNode(next) : null;
  +	}
  +		
  +	public String getNodeName() {
  +	    switch (_type[_index]) {
  +	    case ROOT:
  +		return "#document";
  +	    case TEXT:
  +		return "#text";
  +	    case PROCESSING_INSTRUCTION:
  +		return "***PI Name NYI";
  +	    case COMMENT:
  +		return "#comment";
  +	    default:
  +		return DOMImpl.this.getNodeName(_index);
  +	    }
  +	}
  +		
  +	public String getNodeValue() throws DOMException {
  +	    return DOMImpl.this.getNodeValue(_index);
  +	}
  +		
  +	public Document getOwnerDocument() {
  +	    return null;
  +	}
  +		
  +	//??? how does it work with attributes
  +	public Node getPreviousSibling() {
  +	    int node = _parent[_index];
  +	    if (node > NULL) {
  +		int prev = -1;
  +		node = _offsetOrChild[node];
  +		while (node != _index) {
  +		    node = _nextSibling[prev = node];
  +		}
  +		if (prev != -1) {
  +		    return makeNode(prev);
  +		}
  +	    }
  +	    return null;
  +	}
  +		
  +	public boolean hasChildNodes() {
  +	    switch (getNodeType()) {
  +	    case Node.ELEMENT_NODE:
  +	    case Node.DOCUMENT_NODE:
  +		return _offsetOrChild[_index] != 0;
  +
  +	    default:
  +		return false;
  +	    }
  +	}
  +		
  +	public Node insertBefore(Node n1, Node n2) throws DOMException {
  +	    throw new NotSupportedException();
  +	}
  +		
  +	public Node removeChild(Node n) throws DOMException {
  +	    throw new NotSupportedException();
  +	}
  +		
  +	public Node replaceChild(Node n1, Node n2) throws DOMException {
  +	    throw new NotSupportedException();
  +	}
  +		
  +	public void setNodeValue(String s) throws DOMException {
  +	    throw new NotSupportedException();
  +	}
  +
  +	public void normalize() {
  +	    throw new NotSupportedException();
  +	}
  +
  +	public boolean isSupported(String feature, String version) {
  +	    return false;
  +	}
  +
  +	public String getNamespaceURI() {
  +	    return _nsNamesArray[_namespace[_type[_index] - NTYPES]];
  +	}
  +
  +	public String getPrefix() {
  +	    return null; // We don't know with the current DOM implementation
  +	}
  +
  +	public void setPrefix(String prefix) {
  +	    throw new NotSupportedException();
  +	}
  +
  +	public String getLocalName() {
  +	    final String qname = _namesArray[_type[_index] - NTYPES];
  +	    final int col = qname.lastIndexOf(':');
  +	    return qname.substring(col+1);
  +	}
  +
  +	public boolean hasAttributes() {
  +	    return (_lengthOrAttr[_index] != NULL);
  +	}
   
  -    public Filter getTypeFilter(int type) {
  -         return new TypeFilter(type);
       }
   
  -    // single copy of ElementFilter
  +    // A single copy (cache) of ElementFilter
       private Filter _elementFilter;
   
  +    /**
  +     * Returns a filter that lets only element nodes through
  +     */
       private Filter getElementFilter() {
  -         return _elementFilter != null
  -             ? _elementFilter
  -             : (_elementFilter = new Filter() {
  -                      public boolean test(int node) {
  -                           return isElement(node);
  -                      }
  -                  });
  +	if (_elementFilter == null) {
  +	    _elementFilter = new Filter() {
  +		    public boolean test(int node) {
  +			return isElement(node);
  +		    }
  +		};
  +	}
  +	return _elementFilter;
       }
   
  +    /**
  +     * Implementation of a filter that only returns nodes of a
  +     * certain type (instanciate through getTypeFilter()).
  +     */
       private final class TypeFilter implements Filter {
  -         private final int _nodeType;
  +	private final int _nodeType;
                     
  -         public TypeFilter(int type) {
  -             _nodeType = type;
  -         }
  -                  
  -         public boolean test(int node) {
  -             return _type[node] == _nodeType;
  -         }
  -    } // end of TypeFilter
  +	public TypeFilter(int type) {
  +	    _nodeType = type;
  +	}
  +                  
  +	public boolean test(int node) {
  +	    return _type[node] == _nodeType;
  +	}
  +    }
  +
  +    /**
  +     * Returns a node type filter (implementation of Filter)
  +     */
  +    public Filter getTypeFilter(int type) {
  +	return new TypeFilter(type);
  +    }
   
   
       /**************************************************************
        * Iterator that returns all children of a given node
        */
       private final class ChildrenIterator extends NodeIteratorBase {
  -         // child to return next
  -         private int _currentChild;
  +	// child to return next
  +	private int _currentChild;
            
  -         public NodeIterator setStartNode(final int node) {
  -             if (_isRestartable) {
  -                  _currentChild = hasChildren(node)
  -                      ? _offsetOrChild[_startNode = node] : END;
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  -
  -         public int next() {
  -             final int node = _currentChild;
  -             _currentChild = _nextSibling[node];
  -             return returnNode(node);
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _currentChild;
  -         }
  -
  -         public void gotoMark() {
  -             _currentChild = _markedNode;
  -         }
  +	public NodeIterator setStartNode(final int node) {
  +	    if (_isRestartable) {
  +		_currentChild = hasChildren(node)
  +		    ? _offsetOrChild[_startNode = node] : END;
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
  +
  +	public int next() {
  +	    final int node = _currentChild;
  +	    _currentChild = _nextSibling[node];
  +	    return returnNode(node);
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _currentChild;
  +	}
  +
  +	public void gotoMark() {
  +	    _currentChild = _markedNode;
  +	}
   
       } // end of ChildrenIterator
   
  @@ -562,40 +617,40 @@
        * Iterator that returns the parent of a given node
        */
       private final class ParentIterator extends NodeIteratorBase {
  -         // candidate parent node
  -         private int _node;
  -         private int _nodeType = -1;
  -         
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  _node = _parent[_startNode = node];
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  +	// candidate parent node
  +	private int _node;
  +	private int _nodeType = -1;
  +         
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		_node = _parent[_startNode = node];
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
                
  -         public NodeIterator setNodeType(final int type) {
  -             _nodeType = type;
  -             return this;
  -         }
  -
  -         public int next() {
  -             int result = _node;
  -             if ((_nodeType != -1) && (_type[_node] != _nodeType))
  -                  result = END;
  -             else
  -                  result = _node;
  -             _node = END;
  -             return returnNode(result);
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _node;
  -         }
  -
  -         public void gotoMark() {
  -             _node = _markedNode;
  -         }
  +	public NodeIterator setNodeType(final int type) {
  +	    _nodeType = type;
  +	    return this;
  +	}
  +
  +	public int next() {
  +	    int result = _node;
  +	    if ((_nodeType != -1) && (_type[_node] != _nodeType))
  +		result = END;
  +	    else
  +		result = _node;
  +	    _node = END;
  +	    return returnNode(result);
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _node;
  +	}
  +
  +	public void gotoMark() {
  +	    _node = _markedNode;
  +	}
       } // end of ParentIterator
   
   
  @@ -606,41 +661,41 @@
        * for efficiency (both speed and size of translet).
        */
       private final class TypedChildrenIterator extends NodeIteratorBase {
  -         private final int _nodeType;
  -         // node to consider next
  -         private int _currentChild;
  -         
  -         public TypedChildrenIterator(int nodeType) {
  -             _nodeType = nodeType;
  -         }
  -
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  _currentChild = hasChildren(node)
  -                      ? _offsetOrChild[_startNode = node] : END;
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  -
  -         public int next() {
  -             for (int node = _currentChild; node != END;
  -                   node = _nextSibling[node]) {
  -                  if (_type[node] == _nodeType) {
  -                      _currentChild = _nextSibling[node];
  -                      return returnNode(node);
  -                  }
  -             }
  -             return END;
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _currentChild;
  -         }
  -
  -         public void gotoMark() {
  -             _currentChild = _markedNode;
  -         }
  +	private final int _nodeType;
  +	// node to consider next
  +	private int _currentChild;
  +         
  +	public TypedChildrenIterator(int nodeType) {
  +	    _nodeType = nodeType;
  +	}
  +
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		_currentChild = hasChildren(node)
  +		    ? _offsetOrChild[_startNode = node] : END;
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
  +
  +	public int next() {
  +	    for (int node = _currentChild; node != END;
  +		 node = _nextSibling[node]) {
  +		if (_type[node] == _nodeType) {
  +		    _currentChild = _nextSibling[node];
  +		    return returnNode(node);
  +		}
  +	    }
  +	    return END;
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _currentChild;
  +	}
  +
  +	public void gotoMark() {
  +	    _currentChild = _markedNode;
  +	}
       } // end of TypedChildrenIterator
   
   
  @@ -651,40 +706,40 @@
        * iterator is used for efficiency (both speed and size of translet).
        */
       private final class NamespaceChildrenIterator extends NodeIteratorBase {
  -         private final int _nsType;
  -         private int _currentChild;
  +	private final int _nsType;
  +	private int _currentChild;
            
  -         public NamespaceChildrenIterator(final int type) {
  -             _nsType = type;
  -         }
  -
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  _currentChild = hasChildren(node)
  -                      ? _offsetOrChild[_startNode = node] : END;
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  -
  -         public int next() {
  -             for (int node = _currentChild; node != END; 
  -                   node = _nextSibling[node]) {
  -                  if (getNamespaceType(node) == _nsType) {
  -                      _currentChild = _nextSibling[node];
  -                      return returnNode(node);
  -                  }
  -             }
  -             return END;
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _currentChild;
  -         }
  -
  -         public void gotoMark() {
  -             _currentChild = _markedNode;
  -         }
  +	public NamespaceChildrenIterator(final int type) {
  +	    _nsType = type;
  +	}
  +
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		_currentChild = hasChildren(node)
  +		    ? _offsetOrChild[_startNode = node] : END;
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
  +
  +	public int next() {
  +	    for (int node = _currentChild; node != END; 
  +		 node = _nextSibling[node]) {
  +		if (getNamespaceType(node) == _nsType) {
  +		    _currentChild = _nextSibling[node];
  +		    return returnNode(node);
  +		}
  +	    }
  +	    return END;
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _currentChild;
  +	}
  +
  +	public void gotoMark() {
  +	    _currentChild = _markedNode;
  +	}
   
       } // end of TypedChildrenIterator
   
  @@ -694,44 +749,44 @@
        */
       private final class NamespaceAttributeIterator extends NodeIteratorBase {
   
  -         private final int _nsType;
  -         private int _attribute;
  +	private final int _nsType;
  +	private int _attribute;
            
  -         public NamespaceAttributeIterator(int nsType) {
  -             super();
  -             _nsType = nsType;
  -         }
  -                  
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  for (node = _lengthOrAttr[_startNode = node];
  -                       node != NULL && getNamespaceType(node) != _nsType;
  -                       node = _nextSibling[node]);
  -                  _attribute = node;
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  -                  
  -         public int next() {
  -             final int save = _attribute;
  -             int node = save;
  -             _attribute = _nextSibling[_attribute];
  -             for (node = _lengthOrAttr[_startNode = node];
  -                   node != NULL && getNamespaceType(node) != _nsType;
  -                   node = _nextSibling[node]);
  -             _attribute = node;
  -
  -             return returnNode(save);
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _attribute;
  -         }
  -
  -         public void gotoMark() {
  -             _attribute = _markedNode;
  -         }
  +	public NamespaceAttributeIterator(int nsType) {
  +	    super();
  +	    _nsType = nsType;
  +	}
  +                  
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		for (node = _lengthOrAttr[_startNode = node];
  +		     node != NULL && getNamespaceType(node) != _nsType;
  +		     node = _nextSibling[node]);
  +		_attribute = node;
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
  +                  
  +	public int next() {
  +	    final int save = _attribute;
  +	    int node = save;
  +	    _attribute = _nextSibling[_attribute];
  +	    for (node = _lengthOrAttr[_startNode = node];
  +		 node != NULL && getNamespaceType(node) != _nsType;
  +		 node = _nextSibling[node]);
  +	    _attribute = node;
  +
  +	    return returnNode(save);
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _attribute;
  +	}
  +
  +	public void gotoMark() {
  +	    _attribute = _markedNode;
  +	}
            
       } // end of TypedChildrenIterator
   
  @@ -740,27 +795,27 @@
        * Iterator that returns all siblings of a given node.
        */
       private class FollowingSiblingIterator extends NodeIteratorBase {
  -         private int _node;
  +	private int _node;
            
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  _node = _startNode = node;
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  -                  
  -         public int next() {
  -             return returnNode(_node = _nextSibling[_node]);
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _node;
  -         }
  -
  -         public void gotoMark() {
  -             _node = _markedNode;
  -         }
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		_node = _startNode = node;
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
  +                  
  +	public int next() {
  +	    return returnNode(_node = _nextSibling[_node]);
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _node;
  +	}
  +
  +	public void gotoMark() {
  +	    _node = _markedNode;
  +	}
       } // end of FollowingSiblingIterator
   
   
  @@ -768,19 +823,19 @@
        * Iterator that returns all following siblings of a given node.
        */
       private final class TypedFollowingSiblingIterator
  -         extends FollowingSiblingIterator {
  -         private final int _nodeType;
  +	extends FollowingSiblingIterator {
  +	private final int _nodeType;
   
  -         public TypedFollowingSiblingIterator(int type) {
  -             _nodeType = type;
  -         }
  -         
  -         public int next() {
  -             int node;
  -             while ((node = super.next()) != NULL && _type[node] != _nodeType) {
  -             }
  -             return node;
  -         }
  +	public TypedFollowingSiblingIterator(int type) {
  +	    _nodeType = type;
  +	}
  +         
  +	public int next() {
  +	    int node;
  +	    while ((node = super.next()) != NULL && _type[node] != _nodeType) {
  +	    }
  +	    return node;
  +	}
   
       } // end of TypedFollowingSiblingIterator
   
  @@ -789,32 +844,32 @@
        * Iterator that returns attribute nodes (of what nodes?)
        */
       private final class AttributeIterator extends NodeIteratorBase {
  -         private int _attribute;
  +	private int _attribute;
            
  -         // assumes caller will pass element nodes
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  _attribute = isElement(node)
  -                      ? _lengthOrAttr[_startNode = node]
  -                      : NULL;
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  -                  
  -         public int next() {
  -             final int node = _attribute;
  -             _attribute = _nextSibling[_attribute];
  -             return returnNode(node);
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _attribute;
  -         }
  -
  -         public void gotoMark() {
  -             _attribute = _markedNode;
  -         }
  +	// assumes caller will pass element nodes
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		_attribute = isElement(node)
  +		    ? _lengthOrAttr[_startNode = node]
  +		    : NULL;
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
  +                  
  +	public int next() {
  +	    final int node = _attribute;
  +	    _attribute = _nextSibling[_attribute];
  +	    return returnNode(node);
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _attribute;
  +	}
  +
  +	public void gotoMark() {
  +	    _attribute = _markedNode;
  +	}
       } // end of AttributeIterator
   
   
  @@ -822,38 +877,38 @@
        * Iterator that returns attribute nodes of a given type
        */
       private final class TypedAttributeIterator extends NodeIteratorBase {
  -         private final int _nodeType;
  -         private int _attribute;
  +	private final int _nodeType;
  +	private int _attribute;
            
  -         public TypedAttributeIterator(int nodeType) {
  -             _nodeType = nodeType;
  -         }
  -                  
  -         // assumes caller will pass element nodes
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  for (node = _lengthOrAttr[_startNode = node];
  -                       node != NULL && _type[node] != _nodeType;
  -                       node = _nextSibling[node]);
  -                  _attribute = node;
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  -                  
  -         public int next() {
  -             final int node = _attribute;
  -             _attribute = NULL;         // singleton iterator
  -             return returnNode(node);
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _attribute;
  -         }
  -
  -         public void gotoMark() {
  -             _attribute = _markedNode;
  -         }
  +	public TypedAttributeIterator(int nodeType) {
  +	    _nodeType = nodeType;
  +	}
  +                  
  +	// assumes caller will pass element nodes
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		for (node = _lengthOrAttr[_startNode = node];
  +		     node != NULL && _type[node] != _nodeType;
  +		     node = _nextSibling[node]);
  +		_attribute = node;
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
  +                  
  +	public int next() {
  +	    final int node = _attribute;
  +	    _attribute = NULL;         // singleton iterator
  +	    return returnNode(node);
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _attribute;
  +	}
  +
  +	public void gotoMark() {
  +	    _attribute = _markedNode;
  +	}
       } // end of TypedAttributeIterator
   
   
  @@ -861,39 +916,39 @@
        * Iterator that returns preceding siblings of a given node
        */
       private class PrecedingSiblingIterator extends NodeIteratorBase {
  -         private int _start;
  -         private int _node;
  +	private int _start;
  +	private int _node;
            
  -         public boolean isReverse() {
  -             return true;
  -         }
  -         
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  _node = _offsetOrChild[_parent[_startNode = _start = node]];
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  -                  
  -         public int next() {
  -             if (_node == _start) {
  -                  return NULL;
  -             }
  -             else {
  -                  final int node = _node;
  -                  _node = _nextSibling[node];
  -                  return returnNode(node);
  -             }
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _node;
  -         }
  -
  -         public void gotoMark() {
  -             _node = _markedNode;
  -         }
  +	public boolean isReverse() {
  +	    return true;
  +	}
  +         
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		_node = _offsetOrChild[_parent[_startNode = _start = node]];
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
  +                  
  +	public int next() {
  +	    if (_node == _start) {
  +		return NULL;
  +	    }
  +	    else {
  +		final int node = _node;
  +		_node = _nextSibling[node];
  +		return returnNode(node);
  +	    }
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _node;
  +	}
  +
  +	public void gotoMark() {
  +	    _node = _markedNode;
  +	}
       } // end of PrecedingSiblingIterator
   
   
  @@ -902,19 +957,19 @@
        * a given node
        */
       private final class TypedPrecedingSiblingIterator
  -         extends PrecedingSiblingIterator {
  -         private final int _nodeType;
  +	extends PrecedingSiblingIterator {
  +	private final int _nodeType;
   
  -         public TypedPrecedingSiblingIterator(int type) {
  -             _nodeType = type;
  -         }
  -         
  -         public int next() {
  -             int node;
  -             while ((node = super.next()) != NULL && _type[node] != _nodeType) {
  -             }
  -             return node;
  -         }
  +	public TypedPrecedingSiblingIterator(int type) {
  +	    _nodeType = type;
  +	}
  +         
  +	public int next() {
  +	    int node;
  +	    while ((node = super.next()) != NULL && _type[node] != _nodeType) {
  +	    }
  +	    return node;
  +	}
   
       } // end of PrecedingSiblingIterator
   
  @@ -925,80 +980,80 @@
        * all ancestors.
        */
       private class PrecedingIterator extends NodeIteratorBase {
  -         // start node + ancestors up to ROOTNODE
  -         private int[] _stack = new int[8];
  -         private int _sp, _oldsp;
  -         
  -         //  _node precedes candidates
  -         private int _node;
  -
  -         public boolean isReverse() {
  -             return true;
  -         }
  -         
  -         public NodeIterator cloneIterator() {
  -             _isRestartable = false;
  -             final int[] stackCopy = new int[8];
  -             try {
  -                  final PrecedingIterator clone = 
  -                      (PrecedingIterator)super.clone();
  -                  System.arraycopy(_stack, 0, stackCopy, 0, _stack.length);
  -                  clone._stack = stackCopy; 
  -                  return clone.reset();
  -             }
  -             catch (CloneNotSupportedException e) {
  -                  BasisLibrary.runTimeError("Iterator clone not supported.");
  -                  return null;
  -             }
  -         }
  -         
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  // iterator is not a clone
  -                  int parent, index;
  -                  _startNode = node;
  -                  _node = ROOTNODE;
  -                  _stack[index = 0] = node;
  -                  if (node > ROOTNODE) {
  -                      while ((parent = _parent[node]) != ROOTNODE) {
  -                           if (++index == _stack.length) {
  -                               final int[] stack = new int[index + 4];
  -                               System.arraycopy(_stack, 0, stack, 0, index);
  -                               _stack = stack;
  -                           }
  -                           _stack[index] = node = parent;
  -                      }
  -                  }
  -                  _oldsp = _sp = index;
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  -                  
  -         public int next() {
  -             final int node = _node + 1;
  -             if ((_sp >= 0) && (node < _stack[_sp])) {
  -                  return returnNode(_node = node);
  -             }
  -             else {
  -                  _node = node;         // skip ancestor
  -                  return --_sp >= 0 ? next() : NULL;
  -             }
  -         }
  -
  -         // redefine NodeIteratorBase's reset
  -         public NodeIterator reset() {
  -             _sp = _oldsp;
  -             return resetPosition();
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _node;
  -         }
  -
  -         public void gotoMark() {
  -             _node = _markedNode;
  -         }
  +	// start node + ancestors up to ROOTNODE
  +	private int[] _stack = new int[8];
  +	private int _sp, _oldsp;
  +         
  +	//  _node precedes candidates
  +	private int _node;
  +
  +	public boolean isReverse() {
  +	    return true;
  +	}
  +         
  +	public NodeIterator cloneIterator() {
  +	    _isRestartable = false;
  +	    final int[] stackCopy = new int[8];
  +	    try {
  +		final PrecedingIterator clone = 
  +		    (PrecedingIterator)super.clone();
  +		System.arraycopy(_stack, 0, stackCopy, 0, _stack.length);
  +		clone._stack = stackCopy; 
  +		return clone.reset();
  +	    }
  +	    catch (CloneNotSupportedException e) {
  +		BasisLibrary.runTimeError("Iterator clone not supported.");
  +		return null;
  +	    }
  +	}
  +         
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		// iterator is not a clone
  +		int parent, index;
  +		_startNode = node;
  +		_node = ROOTNODE;
  +		_stack[index = 0] = node;
  +		if (node > ROOTNODE) {
  +		    while ((parent = _parent[node]) != ROOTNODE) {
  +			if (++index == _stack.length) {
  +			    final int[] stack = new int[index + 4];
  +			    System.arraycopy(_stack, 0, stack, 0, index);
  +			    _stack = stack;
  +			}
  +			_stack[index] = node = parent;
  +		    }
  +		}
  +		_oldsp = _sp = index;
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
  +                  
  +	public int next() {
  +	    final int node = _node + 1;
  +	    if ((_sp >= 0) && (node < _stack[_sp])) {
  +		return returnNode(_node = node);
  +	    }
  +	    else {
  +		_node = node;         // skip ancestor
  +		return --_sp >= 0 ? next() : NULL;
  +	    }
  +	}
  +
  +	// redefine NodeIteratorBase's reset
  +	public NodeIterator reset() {
  +	    _sp = _oldsp;
  +	    return resetPosition();
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _node;
  +	}
  +
  +	public void gotoMark() {
  +	    _node = _markedNode;
  +	}
       } // end of PrecedingIterator
   
   
  @@ -1008,18 +1063,18 @@
        * excludes all ancestors.
        */
       private final class TypedPrecedingIterator extends PrecedingIterator {
  -         private final int _nodeType;
  +	private final int _nodeType;
   
  -         public TypedPrecedingIterator(int type) {
  -             _nodeType = type;
  -         }
  -         
  -         public int next() {
  -             int node;
  -             while ((node = super.next()) != NULL && _type[node] != _nodeType) {
  -             }
  -             return node;
  -         }
  +	public TypedPrecedingIterator(int type) {
  +	    _nodeType = type;
  +	}
  +         
  +	public int next() {
  +	    int node;
  +	    while ((node = super.next()) != NULL && _type[node] != _nodeType) {
  +	    }
  +	    return node;
  +	}
   
       } // end of TypedPrecedingIterator
   
  @@ -1028,35 +1083,35 @@
        * Iterator that returns following nodes of for a given node.
        */
       private class FollowingIterator extends NodeIteratorBase {
  -         //  _node precedes search for next
  -         protected int _node;
  +	//  _node precedes search for next
  +	protected int _node;
                     
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  _startNode = node;
  -                  // find rightmost descendant (or self)
  -                  int current;
  -                  while ((node = lastChild(current = node)) != NULL) {
  -                  }
  -                  _node = current;
  -                  // _node precedes possible following(node) nodes
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		_startNode = node;
  +		// find rightmost descendant (or self)
  +		int current;
  +		while ((node = lastChild(current = node)) != NULL) {
  +		}
  +		_node = current;
  +		// _node precedes possible following(node) nodes
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
                         
  -         public int next() {
  -             final int node = _node + 1;
  -             return node < _treeNodeLimit ? returnNode(_node = node) : NULL;
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _node;
  -         }
  -
  -         public void gotoMark() {
  -             _node = _markedNode;
  -         }
  +	public int next() {
  +	    final int node = _node + 1;
  +	    return node < _treeNodeLimit ? returnNode(_node = node) : NULL;
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _node;
  +	}
  +
  +	public void gotoMark() {
  +	    _node = _markedNode;
  +	}
       } // end of FollowingIterator
   
   
  @@ -1064,22 +1119,22 @@
        * Iterator that returns following nodes of a given type for a given node.
        */
       private final class TypedFollowingIterator extends FollowingIterator {
  -         private final int _nodeType;
  +	private final int _nodeType;
   
  -         public TypedFollowingIterator(int type) {
  -             _nodeType = type;
  -         }
  -                  
  -         public int next() {
  -             final int limit = _treeNodeLimit;
  -             int node = _node + 1;
  -             final int type = _nodeType;
  -             // skipping nodes not of desired type
  -             while (node < limit && _type[node] != type) {
  -                  ++node;
  -             }
  -             return node == limit ? NULL : returnNode(_node = node);
  -         }
  +	public TypedFollowingIterator(int type) {
  +	    _nodeType = type;
  +	}
  +                  
  +	public int next() {
  +	    final int limit = _treeNodeLimit;
  +	    int node = _node + 1;
  +	    final int type = _nodeType;
  +	    // skipping nodes not of desired type
  +	    while (node < limit && _type[node] != type) {
  +		++node;
  +	    }
  +	    return node == limit ? NULL : returnNode(_node = node);
  +	}
       } // end of TypedFollowingIterator
   
   
  @@ -1091,64 +1146,64 @@
        */         
       private class AncestorIterator extends NodeIteratorBase {
   
  -         protected int _index;
  +	protected int _index;
   
  -         public final boolean isReverse() {
  -             return true;
  -         }
  -
  -         public int getLast() {
  -             return(ROOT);
  -         }
  -         
  -         public NodeIterator cloneIterator() {
  -             _isRestartable = false;         // must set to false for any clone
  -             try {
  -                  final AncestorIterator clone = (AncestorIterator)super.clone();
  -                  clone._startNode = _startNode;
  -                  return clone.reset();
  -             } catch (CloneNotSupportedException e) {
  -                  BasisLibrary.runTimeError("Iterator clone not supported.");
  -                  return null;
  -             }
  -         }
  -                  
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  if (_includeSelf)
  -                      _startNode = node;
  -                  else
  -                      _startNode = _parent[node];
  -                  _index = _startNode;
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  -
  -         public NodeIterator reset() {
  -             _index = _startNode;
  -             return resetPosition();
  -         }
  -                  
  -         public int next() {
  -             if (_index >= 0) {
  -                  int bob = _index;
  -                  if (_index == 0)
  -                      _index = -1;
  -                  else
  -                      _index = _parent[_index];
  -                  return returnNode(bob);
  -             }
  -             return(NULL);
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _index;
  -         }
  -
  -         public void gotoMark() {
  -             _index = _markedNode;
  -         }
  +	public final boolean isReverse() {
  +	    return true;
  +	}
  +
  +	public int getLast() {
  +	    return(ROOT);
  +	}
  +         
  +	public NodeIterator cloneIterator() {
  +	    _isRestartable = false;         // must set to false for any clone
  +	    try {
  +		final AncestorIterator clone = (AncestorIterator)super.clone();
  +		clone._startNode = _startNode;
  +		return clone.reset();
  +	    } catch (CloneNotSupportedException e) {
  +		BasisLibrary.runTimeError("Iterator clone not supported.");
  +		return null;
  +	    }
  +	}
  +                  
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		if (_includeSelf)
  +		    _startNode = node;
  +		else
  +		    _startNode = _parent[node];
  +		_index = _startNode;
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
  +
  +	public NodeIterator reset() {
  +	    _index = _startNode;
  +	    return resetPosition();
  +	}
  +                  
  +	public int next() {
  +	    if (_index >= 0) {
  +		int bob = _index;
  +		if (_index == 0)
  +		    _index = -1;
  +		else
  +		    _index = _parent[_index];
  +		return returnNode(bob);
  +	    }
  +	    return(NULL);
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _index;
  +	}
  +
  +	public void gotoMark() {
  +	    _index = _markedNode;
  +	}
       } // end of AncestorIterator
   
   
  @@ -1157,35 +1212,35 @@
        */             
       private final class TypedAncestorIterator extends AncestorIterator {
   
  -         private final int _nodeType;
  +	private final int _nodeType;
                     
  -         public TypedAncestorIterator(int type) {
  -             _nodeType = type;
  -         }
  -
  -         public int next() {
  -             int node;
  -             while ((node = super.next()) != NULL) {
  -                  if (_type[node] == _nodeType)
  -                      return returnNode(node);
  -             }
  -             return(NULL);
  -         }
  -
  -         public int getLast() {
  -             int last = _index;
  -             int curr = _index;
  -
  -             while (curr >= 0) {
  -                  if (curr == 0)
  -                      curr = -1;
  -                  else
  -                      curr = _parent[curr];
  -                  if (_type[curr] == _nodeType)
  -                      last = curr;
  -             }
  -             return(last);
  -         }
  +	public TypedAncestorIterator(int type) {
  +	    _nodeType = type;
  +	}
  +
  +	public int next() {
  +	    int node;
  +	    while ((node = super.next()) != NULL) {
  +		if (_type[node] == _nodeType)
  +		    return returnNode(node);
  +	    }
  +	    return(NULL);
  +	}
  +
  +	public int getLast() {
  +	    int last = _index;
  +	    int curr = _index;
  +
  +	    while (curr >= 0) {
  +		if (curr == 0)
  +		    curr = -1;
  +		else
  +		    curr = _parent[curr];
  +		if (_type[curr] == _nodeType)
  +		    last = curr;
  +	    }
  +	    return(last);
  +	}
   
       } // end of TypedAncestorIterator
   
  @@ -1194,46 +1249,46 @@
        * Iterator that returns the descendants of a given node.
        */             
       private class DescendantIterator extends NodeIteratorBase {
  -         //  _node precedes search for next
  -         protected int _node;
  -         // first node outside descendant range
  -         protected int _limit;
  -
  -         public NodeIterator setStartNode(int node) {
  -             if (_isRestartable) {
  -                  _node = _startNode = _includeSelf ? node - 1 : node;
  -                  // no descendents if no children
  -                  if (hasChildren(node) == false) {
  -                      // set _limit to match next()'s criteria for end
  -                      _limit = node + 1;
  -                  }
  -                  // find leftmost descendant of next sibling
  -                  else if ((node = _nextSibling[node]) == 0) {
  -                      // no next sibling, array end is the limit
  -                      _limit = _treeNodeLimit;
  -                  }
  -                  else {
  -                      _limit = leftmostDescendant(node);
  -                  }
  -                  return resetPosition();
  -             }
  -             return this;
  -         }
  -
  -         public int next() {
  -             if (++_node >= (_limit))
  -                  return(NULL);
  -             else
  -                  return(returnNode(_node));
  -         }
  -
  -         public void setMark() {
  -             _markedNode = _node;
  -         }
  -
  -         public void gotoMark() {
  -             _node = _markedNode;
  -         }
  +	//  _node precedes search for next
  +	protected int _node;
  +	// first node outside descendant range
  +	protected int _limit;
  +
  +	public NodeIterator setStartNode(int node) {
  +	    if (_isRestartable) {
  +		_node = _startNode = _includeSelf ? node - 1 : node;
  +		// no descendents if no children
  +		if (hasChildren(node) == false) {
  +		    // set _limit to match next()'s criteria for end
  +		    _limit = node + 1;
  +		}
  +		// find leftmost descendant of next sibling
  +		else if ((node = _nextSibling[node]) == 0) {
  +		    // no next sibling, array end is the limit
  +		    _limit = _treeNodeLimit;
  +		}
  +		else {
  +		    _limit = leftmostDescendant(node);
  +		}
  +		return resetPosition();
  +	    }
  +	    return this;
  +	}
  +
  +	public int next() {
  +	    if (++_node >= (_limit))
  +		return(NULL);
  +	    else
  +		return(returnNode(_node));
  +	}
  +
  +	public void setMark() {
  +	    _markedNode = _node;
  +	}
  +
  +	public void gotoMark() {
  +	    _node = _markedNode;
  +	}
   
       } // end of DescendantIterator
   
  @@ -1242,23 +1297,23 @@
        * Typed iterator that returns the descendants of a given node.
        */             
       private final class TypedDescendantIterator extends DescendantIterator {
  -         private final int _nodeType;
  +	private final int _nodeType;
                     
  -         public TypedDescendantIterator(int nodeType) {
  -             _nodeType = nodeType;
  -         }
  -                  
  -         public int next() {
  -             final int limit = _limit;
  -             final int type = _nodeType;
  -             int node = _node + 1; // start search w/ next
  -             // while condition == which nodes to skip
  -             // iteration stops when at end or node w/ desired type
  -             while (node < limit && _type[node] != type) {
  -                  ++node;
  -             }
  -             return node < limit ? returnNode(_node = node) : NULL;
  -         }
  +	public TypedDescendantIterator(int nodeType) {
  +	    _nodeType = nodeType;
  +	}
  +                  
  +	public int next() {
  +	    final int limit = _limit;
  +	    final int type = _nodeType;
  +	    int node = _node + 1; // start search w/ next
  +	    // while condition == which nodes to skip
  +	    // iteration stops when at end or node w/ desired type
  +	    while (node < limit && _type[node] != type) {
  +		++node;
  +	    }
  +	    return node < limit ? returnNode(_node = node) : NULL;
  +	}
   
       } // end of TypedDescendantIterator
   
  @@ -1268,34 +1323,34 @@
        */             
       private class NthDescendantIterator extends DescendantIterator {
   
  -         int _pos;
  +	int _pos;
   
  -         public NthDescendantIterator(int pos) {
  -             _pos = pos;
  -             _limit = _treeNodeLimit;
  -         }
  -
  -         // The start node of this iterator is always the root!!!
  -         public NodeIterator setStartNode(int node) {
  -             NodeIterator iterator = super.setStartNode(1);
  -             _limit = _treeNodeLimit;
  -             return iterator;
  -         }
  -
  -         public int next() {
  -             int node;
  -             while ((node = super.next()) != END) {
  -                  int parent = _parent[node];
  -                  int child = _offsetOrChild[parent];
  -                  int pos = 0;
  -
  -                  do {
  -                      if (isElement(child)) pos++;
  -                  } while ((pos < _pos) && (child = _nextSibling[child]) != 0);
  -                  if (node == child) return node;
  -             }
  -             return(END);
  -         }
  +	public NthDescendantIterator(int pos) {
  +	    _pos = pos;
  +	    _limit = _treeNodeLimit;
  +	}
  +
  +	// The start node of this iterator is always the root!!!
  +	public NodeIterator setStartNode(int node) {
  +	    NodeIterator iterator = super.setStartNode(1);
  +	    _limit = _treeNodeLimit;
  +	    return iterator;
  +	}
  +
  +	public int next() {
  +	    int node;
  +	    while ((node = super.next()) != END) {
  +		int parent = _parent[node];
  +		int child = _offsetOrChild[parent];
  +		int pos = 0;
  +
  +		do {
  +		    if (isElement(child)) pos++;
  +		} while ((pos < _pos) && (child = _nextSibling[child]) != 0);
  +		if (node == child) return node;
  +	    }
  +	    return(END);
  +	}
   
       } // end of NthDescendantIterator
   
  @@ -1304,16 +1359,16 @@
        * Iterator that returns a given node only if it is of a given type.
        */             
       private final class TypedSingletonIterator extends SingletonIterator {
  -         private final int _nodeType;
  +	private final int _nodeType;
   
  -         public TypedSingletonIterator(int nodeType) {
  -             _nodeType = nodeType;
  -         }
  -         
  -         public int next() {
  -             final int result = super.next();
  -             return _type[result] == _nodeType ? result : NULL;
  -         }
  +	public TypedSingletonIterator(int nodeType) {
  +	    _nodeType = nodeType;
  +	}
  +         
  +	public int next() {
  +	    final int result = super.next();
  +	    return _type[result] == _nodeType ? result : NULL;
  +	}
       } // end of TypedSingletonIterator
   
   
  @@ -1325,108 +1380,108 @@
        */             
       private final class StrippingIterator extends NodeIteratorBase {
   
  -         private static final int USE_PREDICATE  = 0;
  -         private static final int STRIP_SPACE    = 1;
  -         private static final int PRESERVE_SPACE = 2;
  -
  -         private StripWhitespaceFilter _filter = null;
  -         private short[] _mapping = null;
  -         private final NodeIterator _source;
  -         private boolean _children = false;
  -         private int _action = USE_PREDICATE;
  -         private int _last = -1;
  -
  -         public StrippingIterator(NodeIterator source,
  -                                     short[] mapping,
  -                                     StripWhitespaceFilter filter) {
  -
  -             _filter = filter;
  -             _mapping = mapping;
  -             _source = source;
  -
  -             if (_source instanceof ChildrenIterator ||
  -                  _source instanceof TypedChildrenIterator) {
  -                  _children = true;
  -             }
  -         }
  -
  -         public NodeIterator setStartNode(int node) {
  -             if (_children) {
  -                  if (_filter.stripSpace((DOM)DOMImpl.this, node,
  -                                           _mapping[_type[node]]))
  -                      _action = STRIP_SPACE;
  -                  else
  -                      _action = PRESERVE_SPACE;
  -             }
  -
  -             _source.setStartNode(node);
  -             return resetPosition();
  -         }
  +	private static final int USE_PREDICATE  = 0;
  +	private static final int STRIP_SPACE    = 1;
  +	private static final int PRESERVE_SPACE = 2;
  +
  +	private StripWhitespaceFilter _filter = null;
  +	private short[] _mapping = null;
  +	private final NodeIterator _source;
  +	private boolean _children = false;
  +	private int _action = USE_PREDICATE;
  +	private int _last = -1;
  +
  +	public StrippingIterator(NodeIterator source,
  +				 short[] mapping,
  +				 StripWhitespaceFilter filter) {
  +
  +	    _filter = filter;
  +	    _mapping = mapping;
  +	    _source = source;
  +
  +	    if (_source instanceof ChildrenIterator ||
  +		_source instanceof TypedChildrenIterator) {
  +		_children = true;
  +	    }
  +	}
  +
  +	public NodeIterator setStartNode(int node) {
  +	    if (_children) {
  +		if (_filter.stripSpace((DOM)DOMImpl.this, node,
  +				       _mapping[_type[node]]))
  +		    _action = STRIP_SPACE;
  +		else
  +		    _action = PRESERVE_SPACE;
  +	    }
  +
  +	    _source.setStartNode(node);
  +	    return resetPosition();
  +	}
       
  -         public int next() {
  -             int node;
  -             while ((node = _source.next()) != END) {
  -                  switch(_action) {
  -                  case STRIP_SPACE:
  -                      if (_whitespace.getBit(node)) continue;
  -                      // fall through...
  -                  case PRESERVE_SPACE:
  -                      return returnNode(node);
  -                  case USE_PREDICATE:
  -                      if (_whitespace.getBit(node) &&
  -                           _filter.stripSpace((DOM)DOMImpl.this, node,
  -                                                _mapping[_type[_parent[node]]]))
  -                           continue;
  -                      return returnNode(node);
  -                  }
  -             }
  -             return END;
  -         }
  +	public int next() {
  +	    int node;
  +	    while ((node = _source.next()) != END) {
  +		switch(_action) {
  +		case STRIP_SPACE:
  +		    if (_whitespace.getBit(node)) continue;
  +		    // fall through...
  +		case PRESERVE_SPACE:
  +		    return returnNode(node);
  +		case USE_PREDICATE:
  +		    if (_whitespace.getBit(node) &&
  +			_filter.stripSpace((DOM)DOMImpl.this, node,
  +					   _mapping[_type[_parent[node]]]))
  +			continue;
  +		    return returnNode(node);
  +		}
  +	    }
  +	    return END;
  +	}
       
  -         public void setMark() {
  -             _source.setMark();
  -         }
  -
  -         public void gotoMark() {
  -             _source.gotoMark();
  -         }
  -
  -         public int getLast() {
  -             // Return chached value (if we have it)
  -             if (_last != -1) return _last;
  -
  -             int count = getPosition();
  -             int node;
  -
  -             _source.setMark();
  -             while ((node = _source.next()) != END) {
  -                  switch(_action) {
  -                  case STRIP_SPACE:
  -                      if (_whitespace.getBit(node))
  -                           continue;
  -                      // fall through...
  -                  case PRESERVE_SPACE:
  -                      count++;
  -                      break;
  -                  case USE_PREDICATE:
  -                      if (_whitespace.getBit(node) &&
  -                           _filter.stripSpace((DOM)DOMImpl.this, node,
  -                                                _mapping[_type[_parent[node]]]))
  -                           continue;
  -                      else
  -                           count++;
  -                  }
  -             }
  -             _source.gotoMark();
  -             _last = count;
  -             return(count);
  -         }
  +	public void setMark() {
  +	    _source.setMark();
  +	}
  +
  +	public void gotoMark() {
  +	    _source.gotoMark();
  +	}
  +
  +	public int getLast() {
  +	    // Return chached value (if we have it)
  +	    if (_last != -1) return _last;
  +
  +	    int count = getPosition();
  +	    int node;
  +
  +	    _source.setMark();
  +	    while ((node = _source.next()) != END) {
  +		switch(_action) {
  +		case STRIP_SPACE:
  +		    if (_whitespace.getBit(node))
  +			continue;
  +		    // fall through...
  +		case PRESERVE_SPACE:
  +		    count++;
  +		    break;
  +		case USE_PREDICATE:
  +		    if (_whitespace.getBit(node) &&
  +			_filter.stripSpace((DOM)DOMImpl.this, node,
  +					   _mapping[_type[_parent[node]]]))
  +			continue;
  +		    else
  +			count++;
  +		}
  +	    }
  +	    _source.gotoMark();
  +	    _last = count;
  +	    return(count);
  +	}
   
       } // end of StrippingIterator
   
       public NodeIterator strippingIterator(NodeIterator iterator, short[] mapping,
  -                                StripWhitespaceFilter filter) {
  -         return(new StrippingIterator(iterator, mapping, filter));
  +					  StripWhitespaceFilter filter) {
  +	return(new StrippingIterator(iterator, mapping, filter));
       }
                                   
   
  @@ -1436,100 +1491,101 @@
        */             
       private final class OrderedIterator extends NodeIteratorBase {
   
  -         private BitArray  _nodes = null;
  -         private int       _save = 0;
  -         private int       _mark = 0;
  -         private int       _start = 0;
  -         private int       _node = -1;
  -         private int       _last = 0;
  -
  -         public OrderedIterator(NodeIterator source, int node) {
  -             _nodes = new BitArray(_treeNodeLimit);
  -             source.setStartNode(node);
  -             while ((_node = source.next()) != END) {
  -                  if (_start == -1) _start = _node;
  -                  _last = _node;
  -                  _nodes.setBit(_node);
  -             }
  -             _node = -1;
  -         }
  +	private BitArray  _nodes = null;
  +	private int       _save = 0;
  +	private int       _mark = 0;
  +	private int       _start = 0;
  +	private int       _node = -1;
  +	private int       _last = 0;
  +
  +	public OrderedIterator(NodeIterator source, int node) {
  +	    _nodes = new BitArray(_treeNodeLimit);
  +	    source.setStartNode(node);
  +	    while ((_node = source.next()) != END) {
  +		if (_start == -1) _start = _node;
  +		_last = _node;
  +		_nodes.setBit(_node);
  +	    }
  +	    _node = -1;
  +	}
    
  -         public int next() {
  -             while ((_node < _treeNodeLimit) && (!_nodes.getBit(++_node))) ;
  -             if (_node >= _treeNodeLimit) return(END);
  -             return returnNode(_node);
  -         }
  -
  -         public NodeIterator reset() {
  -             _node = _start - 1;
  -             return(this);
  -         }
  -
  -         public int getLast() {
  -             return(_last);
  -         }
  -         
  -         public void setMark() {
  -             _save = _node;
  -         }
  -
  -         public void gotoMark() {
  -             _node = _save;
  -         }
  -
  -         public NodeIterator setStartNode(int start) {
  -             _start = start;
  -             return((NodeIterator)this);
  -         }
  -
  -         public boolean isReverse() {
  -             return(false);
  -         }
  -
  -         public NodeIterator cloneIterator() {
  -             return((NodeIterator)this);
  -         }
  +	public int next() {
  +	    while ((_node < _treeNodeLimit) && (!_nodes.getBit(++_node))) ;
  +	    if (_node >= _treeNodeLimit) return(END);
  +	    return returnNode(_node);
  +	}
  +
  +	public NodeIterator reset() {
  +	    _node = _start - 1;
  +	    return(this);
  +	}
  +
  +	public int getLast() {
  +	    return(_last);
  +	}
  +         
  +	public void setMark() {
  +	    _save = _node;
  +	}
  +
  +	public void gotoMark() {
  +	    _node = _save;
  +	}
  +
  +	public NodeIterator setStartNode(int start) {
  +	    _start = start;
  +	    return((NodeIterator)this);
  +	}
  +
  +	public boolean isReverse() {
  +	    return(false);
  +	}
  +
  +	public NodeIterator cloneIterator() {
  +	    return((NodeIterator)this);
  +	}
   
       } // end of OrderedIterator
   
  +
       /**
  -     *
  +     * Encapsulates an iterator in an OrderedIterator to ensure node order
        */
       public NodeIterator orderNodes(NodeIterator source, int node) {
  -         return new OrderedIterator(source, node);
  +	return new OrderedIterator(source, node);
       }
   
       /**
        * Returns the leftmost descendant of a node (bottom left in sub-tree)
        */
       private int leftmostDescendant(int node) {
  -         int current;
  -         while (_type[current = node] >= NTYPES 
  -                && (node = _offsetOrChild[node]) != NULL) {
  -         }
  -         return current;
  +	int current;
  +	while (_type[current = node] >= NTYPES 
  +	       && (node = _offsetOrChild[node]) != NULL) {
  +	}
  +	return current;
       }
   
       /**
        * Returns index of last child or 0 if no children
        */
       private int lastChild(int node) {
  -         if (isElement(node) || node == ROOTNODE) {
  -             int child;
  -             if ((child = _offsetOrChild[node]) != NULL) {
  -                  while ((child = _nextSibling[node = child]) != NULL) {
  -                  }
  -                  return node;
  -             }
  -         }
  -         return 0;
  +	if (isElement(node) || node == ROOTNODE) {
  +	    int child;
  +	    if ((child = _offsetOrChild[node]) != NULL) {
  +		while ((child = _nextSibling[node = child]) != NULL) {
  +		}
  +		return node;
  +	    }
  +	}
  +	return 0;
       }
   
       /**
        * Returns the parent of a node
        */
       public int getParent(final int node) {
  -         return _parent[node];
  +	return _parent[node];
       }
   
       /**
  @@ -1537,130 +1593,147 @@
        */
       public int getTypedPosition(NodeIterator iterator, int type, int node) {
   
  -         // Just return the basic position if no type is specified
  -         if (type == -1) type = _type[node];
  -         //if (type == -1) return(iterator.getPosition()); DEAD WRONG!!!!
  -
  -         int match = 1;
  -         int curr  = 0;
  -         iterator.reset();
  -
  -         while ( ((curr = iterator.next()) != NULL) && (curr != node)) {
  -             if (_type[curr] == type) match++;
  -         }
  -         return match;         
  +	// Just return the basic position if no type is specified
  +	if (type == -1) type = _type[node];
  +	//if (type == -1) return(iterator.getPosition()); DEAD WRONG!!!!
  +
  +	int match = 1;
  +	int curr  = 0;
  +	iterator.reset();
  +
  +	while ( ((curr = iterator.next()) != NULL) && (curr != node)) {
  +	    if (_type[curr] == type) match++;
  +	}
  +	return match;         
       }
   
       /**
        * Returns an iterator's last node of a given type
        */
       public int getTypedLast(NodeIterator iterator, int type, int node) {
  -         // Just return the basic position if no type is specified
  -         if (type == -1) return(iterator.getLast());
  +	// Just return the basic position if no type is specified
  +	if (type == -1) return(iterator.getLast());
   
  -         int match = 0;
  -         int curr  = 0;
  -         iterator.setMark();
  -         iterator.reset();
  -
  -         while ((curr = iterator.next()) != NULL) {
  -             if (_type[curr] == type) match++;
  -         }
  -         iterator.gotoMark();
  -         return match;         
  +	int match = 0;
  +	int curr  = 0;
  +	iterator.setMark();
  +	iterator.reset();
  +
  +	while ((curr = iterator.next()) != NULL) {
  +	    if (_type[curr] == type) match++;
  +	}
  +	iterator.gotoMark();
  +	return match;         
       }
   
  -         
       /**
        * Returns singleton iterator containg the document root
        * Works for them main document (mark == 0)
        */
       public NodeIterator getIterator() {
  -         return new SingletonIterator(ROOTNODE);
  +	return new SingletonIterator(ROOTNODE);
       }
   
  +    /**
  +     * Returns the type of a specific node
  +     */
       public int getType(final int node) {
  -         if (node >= _type.length)
  -             return(0);
  -         else
  -             return _type[node];
  +	if (node >= _type.length)
  +	    return(0);
  +	else
  +	    return _type[node];
       }
       
  +    /**
  +     * Returns the namespace type of a specific node
  +     */
       public int getNamespaceType(final int node) {
  -         final int type = _type[node];
  -         if (type >= NTYPES)
  -             return(_namespace[type-NTYPES]);
  -         else
  -             return(0); // default namespace
  +	final int type = _type[node];
  +	if (type >= NTYPES)
  +	    return(_namespace[type-NTYPES]);
  +	else
  +	    return(0); // default namespace
       }
   
  +    /**
  +     * Returns the node-to-type mapping array
  +     */
       public short[] getTypeArray() {
  -         return _type;
  +	return _type;
       }
   
  +    /**
  +     * Returns the (String) value of any node in the tree
  +     */
       public String getNodeValue(final int node) {
  -         if (node == NULL) return EMPTYSTRING;
  -         switch(_type[node]) {
  -         case ROOT:
  -             return getNodeValue(_offsetOrChild[node]);
  -         case TEXT:
  -             return makeStringValue(node);
  -         default:
  -             return node < _treeNodeLimit
  -                  ? getElementValue(node) // element string value
  -                  : makeStringValue(node); // attribute value
  -         }
  +	if (node == NULL) return EMPTYSTRING;
  +	switch(_type[node]) {
  +	case ROOT:
  +	    return getNodeValue(_offsetOrChild[node]);
  +	case TEXT:
  +	    return makeStringValue(node);
  +	default:
  +	    return node < _treeNodeLimit
  +		? getElementValue(node) // element string value
  +		: makeStringValue(node); // attribute value
  +	}
       }
   
  +    /**
  +     * Sets up a translet-to-dom type mapping table
  +     */
       private Hashtable setupMapping(String[] namesArray) {
  -         final int nNames = namesArray.length;
  -         final Hashtable types = new Hashtable(nNames);
  -         for (int i = 0; i < nNames; i++) {
  -             types.put(namesArray[i], new Integer(i + NTYPES));
  -         }
  -         return types;
  +	final int nNames = namesArray.length;
  +	final Hashtable types = new Hashtable(nNames);
  +	for (int i = 0; i < nNames; i++) {
  +	    types.put(namesArray[i], new Integer(i + NTYPES));
  +	}
  +	return types;
       }
   
  +    /**
  +     * Returns the internal type associated with an expaneded QName
  +     */
       public int getGeneralizedType(final String name) {
  -         final Integer type = (Integer)_types.get(name);
  -         if (type == null) {
  -             // memorize default type
  -             final int code = name.charAt(0) == '@' ? ATTRIBUTE : ELEMENT;
  -             _types.put(name, new Integer(code));
  -             return code;
  -         }
  -         else {
  -             return type.intValue();
  -         }
  +	final Integer type = (Integer)_types.get(name);
  +	if (type == null) {
  +	    // memorize default type
  +	    final int code = name.charAt(0) == '@' ? ATTRIBUTE : ELEMENT;
  +	    _types.put(name, new Integer(code));
  +	    return code;
  +	}
  +	else {
  +	    return type.intValue();
  +	}
       }
   
       /**
        * Get mapping from DOM element/attribute types to external types
        */
       public short[] getMapping(String[] names) {
  -         final int namesLength = names.length;
  -         final int mappingLength = _namesArray.length + NTYPES;
  -         final short[] result = new short[mappingLength];
  -
  -         // primitive types map to themselves
  -         for (int i = 0; i < NTYPES; i++)
  -             result[i] = (short)i;
  -
  -         // extended types initialized to "beyond caller's types"
  -         // unknown element or Attr
  -         for (int i = NTYPES; i < mappingLength; i++) {
  -             final String name = _namesArray[i - NTYPES];
  -             final int atPos = name.lastIndexOf(':')+1;
  -             result[i] = (short)(name.charAt(atPos) == '@'
  -                                    ? ATTRIBUTE : ELEMENT);
  -         }
  -
  -         // actual mapping of caller requested names
  -         for (int i = 0; i < namesLength; i++) {
  -             result[getGeneralizedType(names[i])] = (short)(i + NTYPES);
  -         }
  +	final int namesLength = names.length;
  +	final int mappingLength = _namesArray.length + NTYPES;
  +	final short[] result = new short[mappingLength];
  +
  +	// primitive types map to themselves
  +	for (int i = 0; i < NTYPES; i++)
  +	    result[i] = (short)i;
  +
  +	// extended types initialized to "beyond caller's types"
  +	// unknown element or Attr
  +	for (int i = NTYPES; i < mappingLength; i++) {
  +	    final String name = _namesArray[i - NTYPES];
  +	    final int atPos = name.lastIndexOf(':')+1;
  +	    result[i] = (short)(name.charAt(atPos) == '@'
  +				? ATTRIBUTE : ELEMENT);
  +	}
  +
  +	// actual mapping of caller requested names
  +	for (int i = 0; i < namesLength; i++) {
  +	    result[getGeneralizedType(names[i])] = (short)(i + NTYPES);
  +	}
                
  -         return(result);
  +	return(result);
   
       }
   
  @@ -1668,1272 +1741,1270 @@
        * Get mapping from external element/attribute types to DOM types
        */
       public short[] getReverseMapping(String[] names) {
  -         final short[] result = new short[names.length + NTYPES];
  -         // primitive types map to themselves
  -         for (int i = 0; i < NTYPES; i++) {
  -             result[i] = (short)i;
  -         }
  -         // caller's types map into appropriate dom types
  -         for (int i = 0; i < names.length; i++) {
  -             result[i + NTYPES] = (short)getGeneralizedType(names[i]);
  -             if (result[i + NTYPES] == ELEMENT)
  -                  result[i + NTYPES] = NO_TYPE;
  -         }
  -         return(result);
  +	final short[] result = new short[names.length + NTYPES];
  +	// primitive types map to themselves
  +	for (int i = 0; i < NTYPES; i++) {
  +	    result[i] = (short)i;
  +	}
  +	// caller's types map into appropriate dom types
  +	for (int i = 0; i < names.length; i++) {
  +	    result[i + NTYPES] = (short)getGeneralizedType(names[i]);
  +	    if (result[i + NTYPES] == ELEMENT)
  +		result[i + NTYPES] = NO_TYPE;
  +	}
  +	return(result);
       }
   
       /**
        * Get mapping from DOM namespace types to external namespace types
        */
       public short[] getNamespaceMapping(String[] namespaces) {
  -         final int nsLength = namespaces.length;
  -         final int mappingLength = _nsNamesArray.length;
  -         final short[] result = new short[mappingLength];
  -
  -         // Initialize all entries to -1
  -         for (int i=0; i<mappingLength; i++)
  -             result[i] = (-1);
  -
  -         for (int i=0; i<nsLength; i++) {
  -             Integer type = (Integer)_nsIndex.get(namespaces[i]);
  -             if (type != null) {
  -                  result[type.intValue()] = (short)i;
  -             }
  -         }
  +	final int nsLength = namespaces.length;
  +	final int mappingLength = _nsNamesArray.length;
  +	final short[] result = new short[mappingLength];
  +
  +	// Initialize all entries to -1
  +	for (int i=0; i<mappingLength; i++)
  +	    result[i] = (-1);
  +
  +	for (int i=0; i<nsLength; i++) {
  +	    Integer type = (Integer)_nsIndex.get(namespaces[i]);
  +	    if (type != null) {
  +		result[type.intValue()] = (short)i;
  +	    }
  +	}
   
  -         return(result);
  +	return(result);
       }
   
       /**
        * Get mapping from external namespace types to DOM namespace types
        */
       public short[] getReverseNamespaceMapping(String[] namespaces) {
  -         final int length = namespaces.length;
  -         final short[] result = new short[length];
  +	final int length = namespaces.length;
  +	final short[] result = new short[length];
   
  -         for (int i=0; i<length; i++) {
  -             Integer type = (Integer)_nsIndex.get(namespaces[i]);
  -             if (type == null)
  -                  result[i] = -1;
  -             else
  -                  result[i] = type.shortValue();
  -         }
  +	for (int i=0; i<length; i++) {
  +	    Integer type = (Integer)_nsIndex.get(namespaces[i]);
  +	    if (type == null)
  +		result[i] = -1;
  +	    else
  +		result[i] = type.shortValue();
  +	}
   
  -         return(result);
  +	return(result);
       }
   
  +    /**
  +     * Dump the whole tree to a file (serialized)
  +     */
       public void writeExternal(ObjectOutput out) throws IOException {
  -         out.writeInt(_treeNodeLimit);
  -         out.writeObject(_type);
  -         out.writeObject(_parent);
  -         out.writeObject(_nextSibling);
  -         out.writeObject(_offsetOrChild);
  -         out.writeObject(_lengthOrAttr);
  -         out.writeObject(_text);
  -         out.writeObject(_namesArray);
  -         out.writeObject(_whitespace);
  -         out.flush();
  +	out.writeInt(_treeNodeLimit);
  +	out.writeObject(_type);
  +	out.writeObject(_namespace);
  +	out.writeObject(_parent);
  +	out.writeObject(_nextSibling);
  +	out.writeObject(_offsetOrChild);
  +	out.writeObject(_lengthOrAttr);
  +	out.writeObject(_text);
  +	out.writeObject(_namesArray);
  +	out.writeObject(_nsNamesArray);
  +	out.writeObject(_whitespace);
  +	out.flush();
       }
   
  +    /**
  +     * Read the whole tree from a file (serialized)
  +     */
       public void readExternal(ObjectInput in)
  -         throws IOException, ClassNotFoundException {
  -         _treeNodeLimit = in.readInt();
  -         _type          = (short[])in.readObject();
  -         _parent        = (int[])in.readObject();
  -         _nextSibling   = (int[])in.readObject();
  -         _offsetOrChild = (int[])in.readObject();
  -         _lengthOrAttr  = (int[])in.readObject();
  -         _text          = (char[])in.readObject();
  -         _namesArray    = (String[])in.readObject();
  -         _whitespace    = (BitArray)in.readObject();
  -
  -         _types         = setupMapping(_namesArray);
  +	throws IOException, ClassNotFoundException {
  +	_treeNodeLimit = in.readInt();
  +	_type          = (short[])in.readObject();
  +	_namespace     = (short[])in.readObject();
  +	_parent        = (int[])in.readObject();
  +	_nextSibling   = (int[])in.readObject();
  +	_offsetOrChild = (int[])in.readObject();
  +	_lengthOrAttr  = (int[])in.readObject();
  +	_text          = (char[])in.readObject();
  +	_namesArray    = (String[])in.readObject();
  +	_nsNamesArray  = (String[])in.readObject();
  +	_whitespace    = (BitArray)in.readObject();
  +	_types         = setupMapping(_namesArray);
       }
   
  +    /**
  +     * Constructor - defaults to 32K nodes
  +     */
       public DOMImpl() {
  -         this(32*1024);
  +	this(32*1024);
       }
            
  +    /**
  +     * Constructor - defines initial size
  +     */
       public DOMImpl(final int size) {
  -         _type          = new short[size];
  -         _parent        = new int[size];
  -         _nextSibling   = new int[size];
  -         _offsetOrChild = new int[size];
  -         _lengthOrAttr  = new int[size];
  -         _text          = new char[size * 10];
  -         _whitespace    = new BitArray(size);
  -         // _namesArray will be allocated at endDocument
  +	_type          = new short[size];
  +	_parent        = new int[size];
  +	_nextSibling   = new int[size];
  +	_offsetOrChild = new int[size];
  +	_lengthOrAttr  = new int[size];
  +	_text          = new char[size * 10];
  +	_whitespace    = new BitArray(size);
  +	// _namesArray[] and _nsNamesArray are allocated in endDocument
       }
   
  -    public void print(int node, int level) {
  -         switch(_type[node]) {
  -         case ROOT:
  -             print(_offsetOrChild[node], level);
  -             break;
  -
  -         case TEXT:
  -             System.out.print(makeStringValue(node));
  -             break;
  -
  -         case PROCESSING_INSTRUCTION:
  -         case COMMENT:
  -             System.out.println("***PI/CMT***");
  -             break;
  -
  -         default:                  // element
  -             final String name = getNodeName(node);
  -             System.out.print("<" + name);
  -             for (int a = _lengthOrAttr[node]; a != NULL; a = _nextSibling[a]) {
  -                  System.out.print("\n" + getNodeName(a) +
  -                                     "=\"" + makeStringValue(a) + "\"");
  -             }
  -             System.out.print('>');
  -             for (int child = _offsetOrChild[node]; child != NULL;
  -                   child = _nextSibling[child]) {
  -                  print(child, level + 1);
  -             }
  -             System.out.println("</" + name + '>');
  -             break;
  -         }
  -    }
  -
       /**
  -     * Returns the name of a node type (attribute or element).
  -     * Look at it again (better way to differenciate attributes).
  +     * Prints the whole tree to standard output
        */
  -    /*
  -    private String namedNodeName(final int type) {
  -         final String rawName = _namesArray[type - NTYPES];
  -
  -         return rawName.charAt(0) == '@' ? rawName.substring(1) : rawName;
  +    public void print(int node, int level) {
  +	switch(_type[node]) {
  +	case ROOT:
  +	    print(_offsetOrChild[node], level);
  +	    break;
  +
  +	case TEXT:
  +	    System.out.print(makeStringValue(node));
  +	    break;
  +
  +	case PROCESSING_INSTRUCTION:
  +	case COMMENT:
  +	    System.out.println("***PI/CMT***");
  +	    break;
  +
  +	default:                  // element
  +	    final String name = getNodeName(node);
  +	    System.out.print("<" + name);
  +	    for (int a = _lengthOrAttr[node]; a != NULL; a = _nextSibling[a]) {
  +		System.out.print("\n" + getNodeName(a) +
  +				 "=\"" + makeStringValue(a) + "\"");
  +	    }
  +	    System.out.print('>');
  +	    for (int child = _offsetOrChild[node]; child != NULL;
  +		 child = _nextSibling[child]) {
  +		print(child, level + 1);
  +	    }
  +	    System.out.println("</" + name + '>');
  +	    break;
  +	}
       }
  -    */
   
       /**
        * Returns the name of a node (attribute or element).
        */
       public String getNodeName(final int node) {
  -         // Get the node type and make sure that it is within limits
  -         final short type = _type[node];
  -         if (type == DOM.PROCESSING_INSTRUCTION)
  -             return("a-pi");
  -         else if (type < NTYPES)
  -             return EMPTYSTRING;
  -
  -         // Get node's name (attribute or element)
  -         final String rawName = _namesArray[type - NTYPES];
  -         // Make sure attributes are returned without the leading '@'
  -         if (node < _firstAttributeNode)
  -             return(rawName);
  -         else {
  -             final int col = rawName.lastIndexOf(':');
  -             if (col < 0)
  -                  return(rawName.substring(1));
  -             else
  -                  return(rawName.substring(0,col)+':'+rawName.substring(col+2));
  -         }
  +	// Get the node type and make sure that it is within limits
  +	final short type = _type[node];
  +	if (type == DOM.PROCESSING_INSTRUCTION)
  +	    return("a-pi");
  +	else if (type < NTYPES)
  +	    return EMPTYSTRING;
  +
  +	// Get node's name (attribute or element)
  +	final String rawName = _namesArray[type - NTYPES];
  +	// Make sure attributes are returned without the leading '@'
  +	if (node < _firstAttributeNode)
  +	    return(rawName);
  +	else {
  +	    final int col = rawName.lastIndexOf(':');
  +	    if (col < 0)
  +		return(rawName.substring(1));
  +	    else
  +		return(rawName.substring(0,col)+':'+rawName.substring(col+2));
  +	}
       }
   
  +    /**
  +     * Returns the namespace URI to which a node belongs
  +     */
       public String getNamespaceName(final int node) {
  -         final int type = getNamespaceType(node);
  -         return(_nsNamesArray[type]);
  +	final int type = getNamespaceType(node);
  +	return(_nsNamesArray[type]);
       }
   
  +    /**
  +     * Returns the string value of a single text/comment node or
  +     * attribute value (they are all stored in the same array).
  +     */
       private String makeStringValue(final int node) {
  -         return new String(_text, _offsetOrChild[node], _lengthOrAttr[node]);
  +	return new String(_text, _offsetOrChild[node], _lengthOrAttr[node]);
       }
   
  +    /**
  +     * Don't know if this is ever used (shouldn't be with the explicit
  +     * external/internal type mapping - this is really ugly)
  +     */
  +    /*
       public String getAttributeValue(final int eType,
  -                                        final int node,
  -                                        final short[] reverseMapping) {
  -         return getAttributeValue(reverseMapping[eType], node);
  +				    final int node,
  +				    final short[] reverseMapping) {
  +	return getAttributeValue(reverseMapping[eType], node);
       }
  -    
  -    public String getAttributeValue(final int gType, final int element) {
  -         for (int attr = _lengthOrAttr[element];
  -              attr != NULL;
  -              attr = _nextSibling[attr]) {
  -             if (_type[attr] == gType) {
  -                  return makeStringValue(attr);
  -             }
  -         }
  -         return EMPTYSTRING;
  +    */
  +
  +    /**
  +     * Returns the value of a given attribute type of a given element
  +     */
  +    public String getAttributeValue(final int type, final int element) {
  +	for (int attr = _lengthOrAttr[element];
  +	     attr != NULL;
  +	     attr = _nextSibling[attr]) {
  +	    if (_type[attr] == type) return makeStringValue(attr);
  +	}
  +	return EMPTYSTRING;
       }
   
  +    /**
  +     * Returns the attribute node of a given type (if any) for an element
  +     */
       public int getAttributeNode(final int gType, final int element) {
  -         for (int attr = _lengthOrAttr[element]; attr != NULL;
  -              attr = _nextSibling[attr]) {
  -             if (_type[attr] == gType) {
  -                  return attr;
  -             }
  -         }
  -         return NULL;
  +	for (int attr = _lengthOrAttr[element]; attr != NULL;
  +	     attr = _nextSibling[attr]) {
  +	    if (_type[attr] == gType) {
  +		return attr;
  +	    }
  +	}
  +	return NULL;
  +    }
  +
  +    /**
  +     * Returns true if a given element has an attribute of a given type
  +     */
  +    public boolean hasAttribute(final int type, final int node) {
  +	for (int attr = _lengthOrAttr[node]; attr != NULL;
  +	     attr = _nextSibling[attr]) {
  +	    if (_type[attr] == type) {
  +		return true;
  +	    }
  +	}
  +	return false;
       }
   
  -    // for testing
  +    /**
  +     * This method is for testing/debugging only
  +     */
       public String getAttributeValue(final String name, final int element) {
  -         return getAttributeValue(getGeneralizedType(name), element);
  +	return getAttributeValue(getGeneralizedType(name), element);
       }
       
  -    public boolean hasAttribute(final int gType, final int node) {
  -         for (int attr = _lengthOrAttr[node]; attr != NULL;
  -              attr = _nextSibling[attr]) {
  -             if (_type[attr] == gType) {
  -                  return true;
  -             }
  -         }
  -         return false;
  -    }
  -
  +    /**
  +     * Returns true if the given element has any children
  +     */
       private boolean hasChildren(final int node) {
  -         if (node < _treeNodeLimit) {
  -             final int type = _type[node];
  -             return(((type >= NTYPES) || (type == ROOT)) &&
  -                     (_offsetOrChild[node] != 0));
  -         }
  -         return(false);
  +	if (node < _treeNodeLimit) {
  +	    final int type = _type[node];
  +	    return(((type >= NTYPES) || (type == ROOT)) &&
  +		   (_offsetOrChild[node] != 0));
  +	}
  +	return(false);
       }
   
  +    /**
  +     * Returns an iterator with all the children of a given node
  +     */
       public NodeIterator getChildren(final int node) {
  -         if (hasChildren(node)) {
  -             return(new ChildrenIterator());
  -         }
  -         else {
  -             return(EMPTYITERATOR);
  -         }
  +	if (hasChildren(node)) {
  +	    return(new ChildrenIterator());
  +	}
  +	else {
  +	    return(EMPTYITERATOR);
  +	}
       }
   
  -    // shortcut for a popular one
  +    /**
  +     * Returns an iterator with all children of a specific type
  +     * for a given node (element)
  +     */
       public NodeIterator getTypedChildren(final int type) {
  -         return(new TypedChildrenIterator(type));
  +	return(new TypedChildrenIterator(type));
       }
   
  +    /**
  +     * This is a shortcut to the iterators that implement the
  +     * supported XPath axes (only namespace::) is not supported.
  +     * Returns a bare-bones iterator that must be initialized
  +     * with a start node (using iterator.setStartNode()).
  +     */
       public NodeIterator getAxisIterator(final int axis) {
  -         NodeIterator iterator = null;
  +	NodeIterator iterator = null;
   
  -         switch (axis) {
  -         case Axis.SELF:
  -             iterator = new SingletonIterator();
  -             break;
  -         case Axis.CHILD:
  -             iterator = new ChildrenIterator();
  -             break;
  -         case Axis.PARENT:
  -             return(new ParentIterator());
  -         case Axis.ANCESTOR:
  -             return(new AncestorIterator());
  -         case Axis.ANCESTORORSELF:
  -             return((new AncestorIterator()).includeSelf());
  -         case Axis.ATTRIBUTE:
  -             return(new AttributeIterator());
  -         case Axis.DESCENDANT:
  -             iterator = new DescendantIterator();
  -             break;
  -         case Axis.DESCENDANTORSELF:
  -             iterator = (new DescendantIterator()).includeSelf();
  -             break;
  -         case Axis.FOLLOWING:
  -             iterator = new FollowingIterator();
  -             break;
  -         case Axis.PRECEDING:
  -             iterator = new PrecedingIterator();
  -             break;
  -         case Axis.FOLLOWINGSIBLING:
  -             iterator = new FollowingSiblingIterator();
  -             break;
  -         case Axis.PRECEDINGSIBLING:
  -             iterator = new PrecedingSiblingIterator();
  -             break;
  -         case Axis.NAMESPACE:
  -             return(new TypedAttributeIterator(getGeneralizedType("xmlns")));
  -         default:
  -             BasisLibrary.runTimeError("Error: iterator for axis '" + 
  -                                          Axis.names[axis] + "' not implemented");
  -             System.exit(1);
  -         }
  -         return(iterator);
  +	switch (axis) {
  +	case Axis.SELF:
  +	    iterator = new SingletonIterator();
  +	    break;
  +	case Axis.CHILD:
  +	    iterator = new ChildrenIterator();
  +	    break;
  +	case Axis.PARENT:
  +	    return(new ParentIterator());
  +	case Axis.ANCESTOR:
  +	    return(new AncestorIterator());
  +	case Axis.ANCESTORORSELF:
  +	    return((new AncestorIterator()).includeSelf());
  +	case Axis.ATTRIBUTE:
  +	    return(new AttributeIterator());
  +	case Axis.DESCENDANT:
  +	    iterator = new DescendantIterator();
  +	    break;
  +	case Axis.DESCENDANTORSELF:
  +	    iterator = (new DescendantIterator()).includeSelf();
  +	    break;
  +	case Axis.FOLLOWING:
  +	    iterator = new FollowingIterator();
  +	    break;
  +	case Axis.PRECEDING:
  +	    iterator = new PrecedingIterator();
  +	    break;
  +	case Axis.FOLLOWINGSIBLING:
  +	    iterator = new FollowingSiblingIterator();
  +	    break;
  +	case Axis.PRECEDINGSIBLING:
  +	    iterator = new PrecedingSiblingIterator();
  +	    break;
  +	case Axis.NAMESPACE:
  +	    return(new TypedAttributeIterator(getGeneralizedType("xmlns")));
  +	default:
  +	    BasisLibrary.runTimeError("Error: iterator for axis '" + 
  +				      Axis.names[axis] + "' not implemented");
  +	    System.exit(1);
  +	}
  +	return(iterator);
       }
   
  +    /**
  +     * Similar to getAxisIterator, but this one returns an iterator
  +     * containing nodes of a typed axis (ex.: child::foo)
  +     */
       public NodeIterator getTypedAxisIterator(int axis, int type) {
  -         NodeIterator iterator = null;
  +	NodeIterator iterator = null;
   
  -         /* This causes an error when using patterns for elements that
  -            do not exist in the DOM (translet types which do not correspond
  -            to a DOM type are mapped to the DOM.ELEMENT type).
  -         */
  -
  -         if (type == NO_TYPE) {
  -             return(EMPTYITERATOR);
  -         }
  +	/* This causes an error when using patterns for elements that
  +	   do not exist in the DOM (translet types which do not correspond
  +	   to a DOM type are mapped to the DOM.ELEMENT type).
  +	*/
  +	if (type == NO_TYPE) {
  +	    return(EMPTYITERATOR);
  +	}
           else if (type == ELEMENT) {
  -             iterator = new FilterIterator(getAxisIterator(axis),
  -                                               getElementFilter());
  -         }
  -         else
  -         {
  -             switch (axis) {
  -             case Axis.SELF:
  -                  iterator = new TypedSingletonIterator(type);
  -                  break;
  -             case Axis.CHILD:
  -                  iterator = new TypedChildrenIterator(type);
  -                  break;
  -             case Axis.PARENT:
  -                  return(new ParentIterator().setNodeType(type));
  -             case Axis.ANCESTOR:
  -                  return(new TypedAncestorIterator(type));
  -             case Axis.ANCESTORORSELF:
  -                  return((new TypedAncestorIterator(type)).includeSelf());
  -             case Axis.ATTRIBUTE:
  -                  return(new TypedAttributeIterator(type));
  -             case Axis.DESCENDANT:
  -                  iterator = new TypedDescendantIterator(type);
  -                  break;
  -             case Axis.DESCENDANTORSELF:
  -                  iterator = (new TypedDescendantIterator(type)).includeSelf();
  -                  break;
  -             case Axis.FOLLOWING:
  -                  iterator = new TypedFollowingIterator(type);
  -                  break;
  -             case Axis.PRECEDING:
  -                  iterator = new TypedPrecedingIterator(type);
  -                  break;
  -             case Axis.FOLLOWINGSIBLING:
  -                  iterator = new TypedFollowingSiblingIterator(type);
  -                  break;
  -             case Axis.PRECEDINGSIBLING:
  -                  iterator = new TypedPrecedingSiblingIterator(type);
  -                  break;
  -             default:
  -                  BasisLibrary.runTimeError("Error: typed iterator for axis " + 
  -                                               Axis.names[axis]+"not implemented");
  -             }
  -         }
  -         return(iterator);
  +	    iterator = new FilterIterator(getAxisIterator(axis),
  +					  getElementFilter());
  +	}
  +	else {
  +	    switch (axis) {
  +	    case Axis.SELF:
  +		iterator = new TypedSingletonIterator(type);
  +		break;
  +	    case Axis.CHILD:
  +		iterator = new TypedChildrenIterator(type);
  +		break;
  +	    case Axis.PARENT:
  +		return(new ParentIterator().setNodeType(type));
  +	    case Axis.ANCESTOR:
  +		return(new TypedAncestorIterator(type));
  +	    case Axis.ANCESTORORSELF:
  +		return((new TypedAncestorIterator(type)).includeSelf());
  +	    case Axis.ATTRIBUTE:
  +		return(new TypedAttributeIterator(type));
  +	    case Axis.DESCENDANT:
  +		iterator = new TypedDescendantIterator(type);
  +		break;
  +	    case Axis.DESCENDANTORSELF:
  +		iterator = (new TypedDescendantIterator(type)).includeSelf();
  +		break;
  +	    case Axis.FOLLOWING:
  +		iterator = new TypedFollowingIterator(type);
  +		break;
  +	    case Axis.PRECEDING:
  +		iterator = new TypedPrecedingIterator(type);
  +		break;
  +	    case Axis.FOLLOWINGSIBLING:
  +		iterator = new TypedFollowingSiblingIterator(type);
  +		break;
  +	    case Axis.PRECEDINGSIBLING:
  +		iterator = new TypedPrecedingSiblingIterator(type);
  +		break;
  +	    default:
  +		BasisLibrary.runTimeError("Error: typed iterator for axis " + 
  +					  Axis.names[axis]+"not implemented");
  +	    }
  +	}
  +	    return(iterator);
       }
   
  +    /**
  +     * Do not thing that this returns an iterator for the namespace axis.
  +     * It returns an iterator with nodes that belong in a certain namespace,
  +     * such as with <xsl:apply-templates select="blob/foo:*"/>
  +     * The 'axis' specifies the axis for the base iterator from which the
  +     * nodes are taken, while 'ns' specifies the namespace URI type.
  +     */
       public NodeIterator getNamespaceAxisIterator(int axis, int ns) {
   
  -         NodeIterator iterator = null;
  +	NodeIterator iterator = null;
   
  -         if (ns == NO_TYPE) {
  -             return(EMPTYITERATOR);
  -         }
  -         else {
  -             switch (axis) {
  -             case Axis.CHILD:
  -                  iterator = new NamespaceChildrenIterator(ns);
  -                  break;
  -             case Axis.ATTRIBUTE:
  -                  iterator = new NamespaceAttributeIterator(ns);
  -                  break;
  -             default:
  -                  BasisLibrary.runTimeError("Error: typed iterator for axis " + 
  -                                               Axis.names[axis]+"not implemented");
  -             }
  -         }
  -         return(iterator);
  +	if (ns == NO_TYPE) {
  +	    return(EMPTYITERATOR);
  +	}
  +	else {
  +	    switch (axis) {
  +	    case Axis.CHILD:
  +		iterator = new NamespaceChildrenIterator(ns);
  +		break;
  +	    case Axis.ATTRIBUTE:
  +		iterator = new NamespaceAttributeIterator(ns);
  +		break;
  +	    default:
  +		BasisLibrary.runTimeError("Error: typed iterator for axis " + 
  +					  Axis.names[axis]+"not implemented");
  +	    }
  +	}
  +	return(iterator);
       }
   
  +    /**
  +     * Returns an iterator with all descendants of a node that are of
  +     * a given type.
  +     */
       public NodeIterator getTypedDescendantIterator(int type) {
  -         NodeIterator iterator = new TypedDescendantIterator(type);
  -         iterator.setStartNode(1);
  -         return(iterator);
  -    }    
  +	NodeIterator iterator = new TypedDescendantIterator(type);
  +	iterator.setStartNode(1);
  +	return(iterator);
  +    }
   
  +    /**
  +     * Returns the nth descendant of a node (1 = parent, 2 = gramps)
  +     */
       public NodeIterator getNthDescendant(int node, int n) {
  -         return (new NthDescendantIterator(n));
  +	return (new NthDescendantIterator(n));
       }
   
  +    /**
  +     * Copy the contents of a text-node to an output handler
  +     */
       public void characters(final int textNode, TransletOutputHandler handler)
  -         throws TransletException {
  -         handler.characters(_text,
  -                              _offsetOrChild[textNode],
  -                              _lengthOrAttr[textNode]);
  +	throws TransletException {
  +	handler.characters(_text,
  +			   _offsetOrChild[textNode],
  +			   _lengthOrAttr[textNode]);
       }
   
       /**
        * Copy a node-set to an output handler
        */
       public void copy(NodeIterator nodes, TransletOutputHandler handler)
  -         throws TransletException {
  -         int node;
  -         while ((node = nodes.next()) != NULL) {
  -             copy(node, handler);
  -         }
  +	throws TransletException {
  +	int node;
  +	while ((node = nodes.next()) != NULL) {
  +	    copy(node, handler);
  +	}
       }
   
       /**
        * Copy the whole tree to an output handler
        */
       public void copy(TransletOutputHandler handler) throws TransletException {
  -         copy(ROOTNODE, handler);
  +	copy(ROOTNODE, handler);
       }
   
       /** 
  -     * Copy a single node to an output handler
  +     * Performs a deep copy (ref. XSLs copy-of())
  +     *
  +     * TODO: Copy namespace declarations. Can't be done until we
  +     *       add namespace nodes and keep track of NS prefixes
  +     * TODO: Copy comment nodes
        */
       public void copy(final int node, TransletOutputHandler handler)
  -         throws TransletException {
  +	throws TransletException {
  +
  +	if (node >= _treeNodeLimit) return;
   
  -         if (node >= _treeNodeLimit) {
  -             return;
  -         }
  -
  -         switch(_type[node]) {
  -         case ROOT:
  -             for (int child = _offsetOrChild[node];
  -                   child != NULL;
  -                   child = _nextSibling[child]) {
  -                  copy(child, handler);
  -             }
  -             break;
  -
  -         case PROCESSING_INSTRUCTION:
  -         case COMMENT:
  -             //!!! TODO
  -             break;
  -
  -         case TEXT:
  -             handler.characters(_text,
  -                                  _offsetOrChild[node],
  -                                  _lengthOrAttr[node]);
  -             break;
  -
  -         default:
  -             if (isElement(node)) {
  -                  final String name = getNodeName(node);
  -                  // Copy element name - start tag
  -                  int col = name.lastIndexOf(':');
  -                  if (col > 0) {
  -                      final String prefix = generateNamespacePrefix();
  -                      handler.startElement(prefix+':'+name.substring(col+1));
  -                      handler.attribute("xmlns:"+prefix, name.substring(0,col));
  -                  }
  -                  else {
  -                      handler.startElement(name);
  -                  }
  -
  -                  // Copy element attribute
  -                  for (int attr = _lengthOrAttr[node];
  -                       attr != NULL;
  -                       attr = _nextSibling[attr]) {
  -                      final String aname = getNodeName(attr);
  -                      col = aname.lastIndexOf(':');
  -                      if (col < 0) {
  -                           handler.attribute(aname,makeStringValue(attr));
  -                      }
  -                      else {
  -                           final String prefix = generateNamespacePrefix();
  -                           handler.attribute("xmlns:"+prefix,
  -                                               aname.substring(0,col));
  -                           handler.attribute(prefix+':'+aname.substring(col+1),
  -                                               makeStringValue(attr));
  -                      }
  -                  }
  -                  // Copy element namespace declarations ???
  -                  
  -
  -                  // Copy element children
  -                  for (int child = _offsetOrChild[node];
  -                       child != NULL;
  -                       child = _nextSibling[child]) {
  -                      copy(child, handler);
  -                  }
  -                  handler.endElement(name);
  -             }
  -             else {
  -                  System.err.println("NYI: non element in copy");
  -             }
  -             break;
  -         }
  +	switch(_type[node]) {
  +	case ROOT:
  +	    for (int child = _offsetOrChild[node];
  +		 child != NULL;
  +		 child = _nextSibling[child]) {
  +		copy(child, handler);
  +	    }
  +	    break;
  +	case PROCESSING_INSTRUCTION:
  +	    copyPI(node, handler);
  +	    break;
  +	case COMMENT:
  +	    break;
  +	case TEXT:
  +	    handler.characters(_text,
  +			       _offsetOrChild[node],
  +			       _lengthOrAttr[node]);
  +	    break;
  +	default:
  +	    if (isElement(node)) {
  +		final String name = getNodeName(node);
  +		// Copy element name - start tag
  +		int col = name.lastIndexOf(':');
  +		if (col > 0) {
  +		    final String prefix = generateNamespacePrefix();
  +		    handler.startElement(prefix+':'+name.substring(col+1));
  +		    handler.attribute("xmlns:"+prefix, name.substring(0,col));
  +		}
  +		else {
  +		    handler.startElement(name);
  +		}
  +
  +		// Copy element attribute
  +		for (int attr = _lengthOrAttr[node];
  +		     attr != NULL;
  +		     attr = _nextSibling[attr]) {
  +		    final String aname = getNodeName(attr);
  +		    col = aname.lastIndexOf(':');
  +		    if (col < 0) {
  +			handler.attribute(aname,makeStringValue(attr));
  +		    }
  +		    else {
  +			final String prefix = generateNamespacePrefix();
  +			handler.attribute("xmlns:"+prefix,
  +					  aname.substring(0,col));
  +			handler.attribute(prefix+':'+aname.substring(col+1),
  +					  makeStringValue(attr));
  +		    }
  +		}
  +		// Copy element namespace declarations ???
  +
  +		// Copy element children
  +		for (int child = _offsetOrChild[node];
  +		     child != NULL;
  +		     child = _nextSibling[child]) {
  +		    copy(child, handler);
  +		}
  +		handler.endElement(name);
  +	    }
  +	    else {
  +		System.err.println("NYI: non element in copy");
  +	    }
  +	    break;
  +	}
       }
   
  +    /**
  +     * Copies a processing instruction node to an output handler
  +     */ 
       private void copyPI(final int node, TransletOutputHandler handler)
  -         throws TransletException {
  -         final char[] text = _text;
  -         final int start = _offsetOrChild[node];
  -         final int length = _lengthOrAttr[node];
  -         int i = start + 1;
  -         while (text[i] != ' ') {
  -             ++i;
  -         }
  -         handler.processingInstruction(new String(text, start, i - start),
  -                                          new String(text, i + 1, length - i));
  +	throws TransletException {
  +	final char[] text = _text;
  +	final int start = _offsetOrChild[node];
  +	final int length = _lengthOrAttr[node];
  +	int i = start + 1;
  +	while (text[i] != ' ') {
  +	    ++i;
  +	}
  +	handler.processingInstruction(new String(text, start, i - start),
  +				      new String(text, i + 1, length - i));
       }
   
  +    /**
  +     * Performs a shallow copy (ref. XSLs copy())
  +     *
  +     * TODO: Copy namespace declarations. Can't be done until we
  +     *       add namespace nodes and keep track of NS prefixes
  +     * TODO: Copy comment nodes
  +     */
       public String shallowCopy(final int node, TransletOutputHandler handler)
  -         throws TransletException {
  -         switch(_type[node]) {
  -         case ROOT:
  -             // do nothing
  -             return EMPTYSTRING;
  -             
  -         case TEXT:
  -             handler.characters(_text,
  -                                  _offsetOrChild[node],
  -                                  _lengthOrAttr[node]);
  -             return null;
  -             
  -         case PROCESSING_INSTRUCTION:
  -             copyPI(node, handler);
  -             return null;
  -             
  -         case COMMENT:
  -             // !!! implement; not in the tree currently
  -             return null;
  -             
  -         default:                  // element or attribute
  -             final String name = getNodeName(node);
  -             if (node < _treeNodeLimit) { // element
  -                  handler.startElement(name);
  -                  return name;
  -             }
  -             else {                  // attribute
  -                  handler.attribute(name, makeStringValue(node));
  -                  return null;
  -             }
  -         }
  +	throws TransletException {
  +	switch(_type[node]) {
  +	case ROOT: // do nothing
  +	    return EMPTYSTRING;
  +	case TEXT:
  +	    handler.characters(_text,
  +			       _offsetOrChild[node],
  +			       _lengthOrAttr[node]);
  +	    return null;
  +	case PROCESSING_INSTRUCTION:
  +	    copyPI(node, handler);
  +	    return null;
  +	case COMMENT:
  +	    return null;
  +	default:                  // element or attribute
  +	    final String name = getNodeName(node);
  +	    if (node < _treeNodeLimit) { // element
  +		handler.startElement(name);
  +		return name;
  +	    }
  +	    else {                  // attribute
  +		handler.attribute(name, makeStringValue(node));
  +		return null;
  +	    }
  +	}
       }
  -         
  +
  +    /**
  +     * Returns the string value of the entire tree
  +     */
       public String getStringValue() {
  -         return getElementValue(ROOTNODE);
  +	return getElementValue(ROOTNODE);
       }
   
  +    /**
  +     * Returns the string value of any element
  +     */
       public String getElementValue(final int element) {
  -         // optimization: only create StringBuffer if > 1 child
  -         final int child = _offsetOrChild[element];
  -         return child != NULL
  -             ? (_type[child] == TEXT && _nextSibling[child] == NULL
  -                ? makeStringValue(child)
  -                : stringValueAux(new StringBuffer(), element).toString())
  -             : EMPTYSTRING;
  +	// optimization: only create StringBuffer if > 1 child
  +	final int child = _offsetOrChild[element];
  +	return child != NULL
  +	    ? (_type[child] == TEXT && _nextSibling[child] == NULL
  +	       ? makeStringValue(child)
  +	       : stringValueAux(new StringBuffer(), element).toString())
  +	    : EMPTYSTRING;
       }
   
  +    /**
  +     * Helper to getElementValue() above
  +     */
       private StringBuffer stringValueAux(StringBuffer buffer, final int element) {
  -         for (int child = _offsetOrChild[element];
  -              child != NULL;
  -              child = _nextSibling[child]) {
  -             switch (_type[child]) {
  -             case TEXT:
  -                  /* WHITESPACE
  -                  if (_filter != null) {
  -                      if ((_whitespace.getBit(child)) &&
  -                           (_filter.stripSpace((DOM)this, child, 
  -                                                 _type[_parent[child]]))) {
  -                           break;
  -                      }
  -                  }
  -                  */
  -                  buffer.append(_text,
  -                                 _offsetOrChild[child],
  -                                 _lengthOrAttr[child]);
  -                  break;
  -                  
  -             case PROCESSING_INSTRUCTION:
  -             case COMMENT:
  -                  break;
  +	for (int child = _offsetOrChild[element];
  +	     child != NULL;
  +	     child = _nextSibling[child]) {
  +	    switch (_type[child]) {
  +	    case TEXT:
  +		buffer.append(_text,
  +			      _offsetOrChild[child],
  +			      _lengthOrAttr[child]);
  +		break;
  +                  
  +	    case PROCESSING_INSTRUCTION:
  +	    case COMMENT:
  +		break;
                                       
  -                  // !!! at the moment default can only be an element???
  -             default:
  -                  stringValueAux(buffer, child);
  -             }
  -         }
  -         return buffer;
  +		// !!! at the moment default can only be an element???
  +	    default:
  +		stringValueAux(buffer, child);
  +	    }
  +	}
  +	return buffer;
       }
   
       /**
  -     * Returns the defined language for a node (if any)
  +     * Returns a node' defined language for a node (if any)
        */
       public String getLanguage(int node) {
  -         final Integer langType = (Integer)_types.get("xml:@lang");
  -         if (langType != null) {
  -             final int type = langType.intValue();
  -             while (node != DOM.NULL) {
  -                  int attr = _lengthOrAttr[node];
  -                  while (attr != DOM.NULL) {
  -                      if (_type[attr] == type) {
  -                           return(getNodeValue(attr));
  -                      }
  -                      attr = _nextSibling[attr];
  -                  }
  -                  node = getParent(node);
  -             }
  -         }
  -         return(null);
  +	final Integer langType = (Integer)_types.get("xml:@lang");
  +	if (langType != null) {
  +	    final int type = langType.intValue();
  +	    while (node != DOM.NULL) {
  +		int attr = _lengthOrAttr[node];
  +		while (attr != DOM.NULL) {
  +		    if (_type[attr] == type) {
  +			return(getNodeValue(attr));
  +		    }
  +		    attr = _nextSibling[attr];
  +		}
  +		node = getParent(node);
  +	    }
  +	}
  +	return(null);
       }
   
  -    public HandlerBase getBuilder() {
  -         return new DOMBuilder();
  +    /**
  +     * Returns an instance of the DOMBuilder inner class
  +     * This class will consume the input document through a SAX2
  +     * interface and populate the tree.
  +     */
  +    public ContentHandler getBuilder() {
  +	return new DOMBuilder();
       }
   
  +    /**
  +     * Returns a DOMBuilder class wrapped in a SAX adapter.
  +     * I am not sure if we need this one anymore now that the
  +     * DOM builder's interface is pure SAX2 (must investigate)
  +     */
       public TransletOutputHandler getOutputDomBuilder() {
  -         return new SAXAdapter(getBuilder());
  +	return new SAXAdapter(getBuilder());
       }
   
       /**
  -     * Returns true if a character is an XML whitespace character
  +     * Returns true if a character is an XML whitespace character.
  +     * Order of tests is important for performance ([space] first).
        */
       private static final boolean isWhitespaceChar(char c) {
  -         return c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09;
  +	return c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09;
       }
   
  -
  -    /**************************************************************
  -     * DOM builder class definition
  -     */
  -    private final class DOMBuilder extends HandlerBase {
  -
  -         private final static int REUSABLE_TEXT_SIZE = 32;
  -         private Hashtable _shortTexts           = null;
  -
  -         private Hashtable _names                = null;
  -         private int       _nextNameCode         = NTYPES;
  -         private int[]     _parentStack          = new int[64];
  -         private int[]     _previousSiblingStack = new int[64];
  -         private int       _sp;
  -         private int       _baseOffset           = 0;
  -         private int       _currentOffset        = 0;
  -         private int       _currentNode          = 0;
  -
  -         // attribute node stuff
  -         private int       _currentAttributeNode = 0;
  -         private short[]  _type2        = new short[32];
  -         private int[]    _parent2      = new int[32];
  -         private int[]    _nextSibling2 = new int[32];
  -         private int[]    _offset       = new int[32];
  -         private int[]    _length       = new int[32];
  -
  -         // namespace node stuff
  -         private int       _nsCount      = 0;
  -         private int       _nsLimit      = 32;
  -         private String[]  _nsNames      = new String[_nsLimit];
  -         private Hashtable _nsPrefixes   = new Hashtable();
  -
  -         NSDeclStack _nsDeclarations = new NSDeclStack(64);
  -         
  -         // Stack used to keep track of what whitespace text nodes are protected
  -         // by xml:space="preserve" attributes and which nodes that are not.
  -         private int[]   _xmlSpaceStack = new int[64];
  -         private int     _idx = 1;
  -         private boolean _preserve = false;
  -
  -         private static final String XML_STRING = "xml";
  -         private static final String XMLNS_STRING = "xmlns";
  -         private static final String XMLSPACE_STRING = "xmlns";
  -         private static final String PRESERVE_STRING = "preserve";
  -
  -         /**************************************************************
  -          * Class containing a stack that is used to keep track of the varying
  -          * namespace URIs (types) behind a namespace prefix.
  -          */
  -         private final class NSNodeStack {
  -
  -             private final static int DEFAULT_SIZE = 8;
  -
  -             private int[] _data;
  -             private int _size;
  -             private int _sp = 0;
  -
  -             // Constructor
  -             NSNodeStack(int size) {
  -                  _size = size;
  -                  _data = new int[size];
  -             }
  -
  -             // Default constructor
  -             NSNodeStack() {
  -                  this(DEFAULT_SIZE);
  -             }
  -
  -             // Push a namespace type the prefix will refer to for now
  -             void push(int nsIndex) {
  -                  if (_sp == _size) {
  -                      _size = _size << 1;
  -                      final int[] newData = new int[_size];
  -                      System.arraycopy(_data,0,newData,0,_sp);
  -                      _data = newData;
  -                  }
  -                  _data[_sp++] = nsIndex;
  -             }
  -             
  -             // Pop the current namespace type for this prefix
  -             int pop() {
  -                  if (_sp != 0)
  -                      return(_data[--_sp]);
  -                  else
  -                      return(-1);
  -             }
  -
  -             // Get the current namespace type for this prefix
  -             int get() {
  -                  if (_sp != 0)
  -                      return(_data[_sp-1]);
  -                  else
  -                      return(-1);
  -             }
  -         }
  -
  -
  -         /**************************************************************
  -          * Class containg a stack that is used for keeping track of what nodes
  -          * contained the latest namespace declarations.
  -          */
  -         private final class NSDeclStack {
  -
  -             private final static int DEFAULT_SIZE = 64;
  -
  -             private int _sp = 0;
  -             private int _size = 0;
  -             private NSNodeStack[] _stacks = null;
  -             private int[] _nodes = null;
  -
  -             // Constructor
  -             NSDeclStack(int size) {
  -                  _size = size;
  -                  _stacks = new NSNodeStack[size];
  -                  _nodes = new int[size];
  -             }
  -
  -             NSDeclStack() {
  -                  this(DEFAULT_SIZE);
  -             }
  -
  -             // Push a NS node stack with the node where the decl. was found.
  -             void push(int node, NSNodeStack stack) {
  -                  // time to resize arrays?
  -                  if (_sp == _size) {
  -                      _size = _size << 1;
  -                      final NSNodeStack[] newStacks = new NSNodeStack[_size];
  -                      final int[] newNodes = new int[_size];
  -                      System.arraycopy(_stacks,0,newStacks,0,_sp);
  -                      System.arraycopy(_nodes,0,newNodes,0,_sp);
  -                      _stacks = newStacks;
  -                      _nodes = newNodes;
  -                  }
  -
  -                  // now push the new namespace node
  -                  _nodes[_sp] = node;
  -                  _stacks[_sp] = stack;
  -                  _sp++;
  -             }
  -             
  -             // Pop all namespace declarations for a given node (if any).
  -             void pop(int node) {
  -                  while ((_sp != 0) && (_nodes[_sp-1] == node)) {
  -                      _sp--;
  -                      _stacks[_sp].pop();
  -                      _stacks[_sp] = null;
  -                  }
  -             }
  -         }
  -
  -         /**
  -          * Add a new namespace URI to the _namespaceNames table
  -          */
  -         private int addNamespaceURI(String uri) {
  -             // Check if we already have this URI
  -             Integer index = (Integer)_nsIndex.get(uri);
  -             // Add new namespace type if we do not have this one.
  -             if (index == null) {
  -                  // Resize namespace array if necessary
  -                  if (_nsCount == _nsLimit) {
  -                      _nsLimit = _nsLimit << 1;
  -                      final String[] newData = new String[_nsLimit];
  -                      System.arraycopy(_nsNames,0,newData,0,_nsCount);
  -                      _nsNames = newData;
  -                  }
  -                  index = new Integer(_nsCount);
  -                  _nsIndex.put(uri,index);
  -                  _nsNames[_nsCount++] = uri;
  -             }
  -             return(index.intValue());
  -         }
  -
  -         /**
  -          * Add a new prefix for a namespace type
  -          */
  -         private void addNamespacePrefix(int node, String prefix, int type) {
  -             NSNodeStack stack = (NSNodeStack)_nsPrefixes.get(prefix);
  -             if (stack == null) { // add new namespace prefix in table
  -                  stack = new NSNodeStack(8); // what size ? dynamic ?
  -                  _nsPrefixes.put(prefix,stack);
  -             }
  -             stack.push(type);
  -             _nsDeclarations.push(node,stack);
  -         }
  -
  -         /**
  -          * Add a new namespace - prefix and uri
  -          */
  -         private int addNamespace(int node, String prefix, String uri) {
  -             final int type = addNamespaceURI(uri);
  -             addNamespacePrefix(node,prefix,type);
  -             return(type);
  -         }
  -
  -         /**
  -          * Get the namespace type from a namespace prefix
  -          */
  -         private int getNamespaceType(String prefix) {
  -             // Get the stack for this prefix.
  -             final NSNodeStack stack = (NSNodeStack)_nsPrefixes.get(prefix);
  -             if (stack != null)
  -                  return(stack.get()); // return namespace type id
  -             else
  -                  return(0xffffffff);  //undeclared prefix - should not occur
  -         }
  -
  -         /**
  -          * Get the namespace URI from a namespace type
  -          */
  -         private String getNamespaceURI(int nsType) {
  -             if (nsType < _nsCount)
  -                  return(_nsNames[nsType]);
  -             else
  -                  return(null);
  -         }
  -
  -         /**
  -          * Get the namespace URI from a namespace prefix
  -          */
  -         private String getNamespaceURI(String prefix) {
  -             return(getNamespaceURI(getNamespaceType(prefix)));
  -         }
  -
  -         /**
  -          * Create internal name for an element node
  -          */
  -         private short internElement(String name) throws SAXException {
  -             int i;
  -             
  -             // Expand prefix:localname to full QName
  -             if ((i = name.lastIndexOf(':')) != -1) {
  -                  name = getNamespaceURI(name.substring(0,i))+name.substring(i);
  -             }
  -             // Append default namespace with the name has no prefix
  -             else {
  -                  final String uri = getNamespaceURI(EMPTYSTRING);
  -                  if (!uri.equals(EMPTYSTRING)) name = uri + ':' + name;
  -             }
  -
  -             // Stuff the QName into the names vector & hashtable
  -             Integer obj = (Integer)_names.get(name);
  -             if (obj == null) {
  -                  _names.put(name, obj = new Integer(_nextNameCode++));
  -             }
  -             return (short)obj.intValue();
  -         }
  -
  -         /**
  -          * Create internal name for an attribute node
  -          */
  -         private short internAttribute(String name, boolean xmlAttr)
  -             throws SAXException {
  -
  -             // Leave XML attributes as the are
  -             if (!xmlAttr) {
  -                  int col;
  -                  // Expand prefix:localname to full QName
  -                  if ((col = name.lastIndexOf(':')) != -1) {
  -                      name = getNamespaceURI(name.substring(0,col))+
  -                           ':'+'@'+name.substring(col+1);
  -                  }
  -                  // Append default namespace with the name has no prefix
  -                  else {
  -                      // Attributes with no prefix belong in the "" namespace,
  -                      // and not in the namespace that the "" prefix points to,
  -                      // so the attribute name remains the way it is.
  -                      name = '@'+name;
  -                  }
  -             }
  -             else {
  -                  name = name.substring(0,4)+'@'+name.substring(4);
  -             }
  -
  -             // Stuff the QName into the names vector & hashtable
  -             Integer obj = (Integer)_names.get(name);
  -             if (obj == null) {
  -                  _names.put(name, obj = new Integer(_nextNameCode++));
  -             }
  -
  -             return (short)obj.intValue();
  -         }
  -
  -         /**
  -          * Default constructor for the DOMBuiler class
  -          */
  -         public DOMBuilder() {
  -             _xmlSpaceStack[0] = DOM.ROOTNODE;
  -         }
  -         
  -         /**
  -          * Call this when an xml:space attribute is encountered
  -          */
  -         public void xmlSpaceDefine(String val, final int node) {
  -             final boolean setting = val.equals(PRESERVE_STRING);
  -             if (setting != _preserve) {
  -                  _xmlSpaceStack[_idx++] = node;
  -                  _preserve = setting;
  -             }
  -         }
  -
  -         /**
  -          * Call this from endElement() to revert strip/preserve setting
  -          */
  -         public void xmlSpaceRevert(final int node) {
  -             if (node == _xmlSpaceStack[_idx - 1]) {
  -                  _idx--;
  -                  _preserve = !_preserve;
  -             }
  -         }
  -         
  -         /**
  -          *
  -          */
  -         private int nextNode() {
  -             final int index = _currentNode++;
  -             if (index == _type.length) {
  -                  resizeArrays(_type.length * 2, index);
  -             }
  -             return index;
  -         }
  -
  -         /**
  -          *
  -          */
  -         private int nextAttributeNode() {
  -             final int index = _currentAttributeNode++;
  -             if (index == _type2.length) {
  -                  resizeArrays2(_type2.length * 2, index);
  -             }
  -             return index;
  -         }
  -
  -         /**
  -          *
  -          */
  -         private void resizeTextArray(final int newSize) {
  -             final char[] newText = new char[newSize];
  -             System.arraycopy(_text, 0, newText, 0, _currentOffset);
  -             _text = newText;
  -         }
  -         
  -         /**
  -          *
  -          */
  -         private void linkChildren(final int node) {
  -             _parent[node] = _parentStack[_sp];
  -             if (_previousSiblingStack[_sp] != 0) { // current not first child
  -                  _nextSibling[_previousSiblingStack[_sp]] = node;
  -             }
  -             else {
  -                  _offsetOrChild[_parentStack[_sp]] = node;
  -             }
  -             _previousSiblingStack[_sp] = node;
  -         }
  -
  -         /**
  -          * Creates a text-node and checks if it is a whitespace node.
  -          */
  -         private void maybeCreateTextNode() {
  -             if (_currentOffset > _baseOffset) {
  -                  final int node = nextNode();
  -                  final int limit = _currentOffset;
  -                  // Check if whitespace unless protected by xml:space="preserve"
  -                  if (!_preserve) {
  -                      // Check if this text node is purely whitespace
  -                      int i = _baseOffset;
  -                      while (isWhitespaceChar(_text[i++]) && i < limit) ;
  -                      if ((i == limit) && isWhitespaceChar(_text[i-1]))
  -                           _whitespace.setBit(node);
  -                  }
  -                  _type[node] = TEXT;
  -                  linkChildren(node);
  -                  storeTextRef(node);
  -             }
  -         }
  -
  -         /*
  -          * returns offset new or existing
  -          * updates _baseOffset, _currentOffset state
  -          */
  -         private int maybeReuseText(final int length) {
  -             final int base = _baseOffset;
  -             if (length <= REUSABLE_TEXT_SIZE) {
  -                  // Use a char array instead of string for performance benefit
  -                  char[] chars = new char[length];
  -                  System.arraycopy(_text, base, chars, 0, length);
  -                  final Integer offsetObj = (Integer)_shortTexts.get(chars);
  -
  -                  if (offsetObj != null) {
  -                      _currentOffset = base;       // step back current
  -                      return offsetObj.intValue(); // reuse previous string
  -                  }
  -                  else {
  -                      _shortTexts.put(chars, new Integer(base));
  -                  }
  -             }
  -             _baseOffset = _currentOffset; // advance base to current
  -             return base;
  -         }
  -
  -         /**
  -          *
  -          */
  -         private void storeTextRef(final int node) {
  -             final int length = _currentOffset - _baseOffset;
  -             _offsetOrChild[node] = maybeReuseText(length);
  -             _lengthOrAttr[node]  = length;
  -         }
  -         
  -         /**
  -          *
  -          */
  -         private void storeAttrValRef(final int attributeNode) {
  -             final int length = _currentOffset - _baseOffset;
  -             _offset[attributeNode] = maybeReuseText(length);
  -             _length[attributeNode] = length;
  -         }
  -         
  -         /**
  -          * Part of SAX handler interface - initializes the DOM builder
  -          */
  -         public void startDocument() {
  -             _shortTexts     = new Hashtable();
  -             _names          = new Hashtable();
  -             _sp             = 0;
  -             _parentStack[0] = ROOTNODE;         // root
  -             _currentNode    = ROOTNODE + 1;
  -             _currentAttributeNode = 0;
  -             addNamespace(0,EMPTYSTRING,EMPTYSTRING); // default namespace
  -         }
  -
  -         /**
  -          * Part of SAX handler interfaces - finalizes the DOM
  -          */
  -         public void endDocument() {
  -
  -             maybeCreateTextNode();
  -             _shortTexts = null;
  -             final int namesSize = _nextNameCode - NTYPES;
  -
  -             // Fill the names array
  -             _namesArray = new String[namesSize];
  -             Enumeration keys = _names.keys();
  -             while (keys.hasMoreElements()) {
  -                  final String name = (String)keys.nextElement();
  -                  final Integer idx = (Integer)_names.get(name);
  -                  _namesArray[idx.intValue() - NTYPES] = name;
  -             }
   
  -             _names = null;
  -             _types = setupMapping(_namesArray);
  +    /****************************************************************/
  +    /*               DOM builder class definition                   */
  +    /****************************************************************/
  +    private final class DOMBuilder implements ContentHandler {
  +
  +	private final static int REUSABLE_TEXT_SIZE = 32;
  +	private Hashtable _shortTexts           = null;
  +
  +	private Hashtable _names                = null;
  +	private int       _nextNameCode         = NTYPES;
  +	private int[]     _parentStack          = new int[64];
  +	private int[]     _previousSiblingStack = new int[64];
  +	private int       _sp;
  +	private int       _baseOffset           = 0;
  +	private int       _currentOffset        = 0;
  +	private int       _currentNode          = 0;
  +
  +	// attribute node stuff
  +	private int       _currentAttributeNode = 0;
  +	private short[]  _type2        = new short[32];
  +	private int[]    _parent2      = new int[32];
  +	private int[]    _nextSibling2 = new int[32];
  +	private int[]    _offset       = new int[32];
  +	private int[]    _length       = new int[32];
  +
  +	// Namespace prefix-to-uri mapping stuff
  +	private Hashtable _nsPrefixes   = new Hashtable();
  +	private int       _nsCount      = 0;
  +	
  +	// Stack used to keep track of what whitespace text nodes are protected
  +	// by xml:space="preserve" attributes and which nodes that are not.
  +	private int[]   _xmlSpaceStack = new int[64];
  +	private int     _idx = 1;
  +	private boolean _preserve = false;
  +
  +	private static final String XML_STRING = "xml";
  +	private static final String XMLNS_STRING = "xmlns";
  +	private static final String XMLSPACE_STRING = "xmlns";
  +	private static final String PRESERVE_STRING = "preserve";
  +
  +	/**
  +	 * Default constructor for the DOMBuiler class
  +	 */
  +	public DOMBuilder() {
  +	    _xmlSpaceStack[0] = DOM.ROOTNODE;
  +	}
  +
  +	/**
  +	 * Returns the namespace URI that a prefix currentl maps to
  +	 */
  +	private String getNamespaceURI(String prefix) {
  +	    // Get the stack associated with this namespace prefix
  +	    final Stack stack = (Stack)_nsPrefixes.get(prefix);
  +	    if ((stack != null) && (!stack.empty())) {
  +		return((String)stack.peek());
  +	    }
  +	    else
  +		return(EMPTYSTRING);
  +	}
  +
  +	/**
  +	 * Generate the internal type for an element's expanded QName
  +	 */
  +	private short internElement(String uri, String localname)
  +	    throws SAXException {
  +	    
  +	    final String name;
  +	    if (uri != EMPTYSTRING)
  +		name = uri + ':' + localname;
  +	    else
  +		name = localname;
  +
  +	    // Stuff the QName into the names vector & hashtable
  +	    Integer obj = (Integer)_names.get(name);
  +	    if (obj == null) {
  +		_names.put(name, obj = new Integer(_nextNameCode++));
  +	    }
  +	    return (short)obj.intValue();
  +	}
  +
  +	/**
  +	 * Generate the internal type for an element's expanded QName
  +	 */
  +	private short internElement(String name) throws SAXException {
  +	    // Expand prefix:localname to full QName
  +	    int col = name.lastIndexOf(':');
  +	    if (col > -1) {
  +		final String uri = getNamespaceURI(name.substring(0, col));
  +		name = uri + name.substring(col);
  +	    }
  +	    // Append default namespace with the name has no prefix
  +	    else {
  +		final String uri = getNamespaceURI(EMPTYSTRING);
  +		if (!uri.equals(EMPTYSTRING)) name = uri + ':' + name;
  +	    }
  +
  +	    // Stuff the QName into the names vector & hashtable
  +	    Integer obj = (Integer)_names.get(name);
  +	    if (obj == null) {
  +		_names.put(name, obj = new Integer(_nextNameCode++));
  +	    }
  +	    return (short)obj.intValue();
  +	}
  +
  +	/**
  +	 * Generate the internal type for an attribute's expanded QName
  +	 */
  +	private short internAttribute(String name, boolean xmlAttr)
  +	    throws SAXException {
  +
  +	    // Leave XML attributes as the are
  +	    if (xmlAttr) {
  +		name = name.substring(0,4)+'@'+name.substring(4);
  +	    }
  +	    else {
  +		int col;
  +		// Expand prefix:localname to full QName
  +		if ((col = name.lastIndexOf(':')) != -1)
  +		    name = getNamespaceURI(name.substring(0,col))+
  +			':'+'@'+name.substring(col+1);
  +		// Attributes with no prefix belong in the "" namespace,
  +		// and not in the namespace that the "" prefix points to,
  +		// so the attribute name remains the way it is.
  +		else
  +		    name = '@'+name;
  +	    }
  +
  +	    // Stuff the QName into the names vector & hashtable
  +	    Integer obj = (Integer)_names.get(name);
  +	    if (obj == null) {
  +		_names.put(name, obj = new Integer(_nextNameCode++));
  +	    }
  +	    return (short)obj.intValue();
  +	}
  +	
  +	/**
  +	 * Call this when an xml:space attribute is encountered to
  +	 * define the whitespace strip/preserve settings.
  +	 */
  +	private void xmlSpaceDefine(String val, final int node) {
  +	    final boolean setting = val.equals(PRESERVE_STRING);
  +	    if (setting != _preserve) {
  +		_xmlSpaceStack[_idx++] = node;
  +		_preserve = setting;
  +	    }
  +	}
  +
  +	/**
  +	 * Call this from endElement() to revert strip/preserve setting
  +	 * to whatever it was before the corresponding startElement()
  +	 */
  +	private void xmlSpaceRevert(final int node) {
  +	    if (node == _xmlSpaceStack[_idx - 1]) {
  +		_idx--;
  +		_preserve = !_preserve;
  +	    }
  +	}
  +	
  +	/**
  +	 * Returns the next available node. Increases the various arrays
  +	 * that constitute the node if necessary.
  +	 */
  +	private int nextNode() {
  +	    final int index = _currentNode++;
  +	    if (index == _type.length) {
  +		resizeArrays(_type.length * 2, index);
  +	    }
  +	    return index;
  +	}
  +
  +	/**
  +	 * Returns the next available attribute node. Increases the
  +	 * various arrays that constitute the attribute if necessary
  +	 */
  +	private int nextAttributeNode() {
  +	    final int index = _currentAttributeNode++;
  +	    if (index == _type2.length) {
  +		resizeArrays2(_type2.length * 2, index);
  +	    }
  +	    return index;
  +	}
  +
  +	/**
  +	 * Resize the character array that holds the contents of
  +	 * all text nodes, comments and attribute values
  +	 */
  +	private void resizeTextArray(final int newSize) {
  +	    final char[] newText = new char[newSize];
  +	    System.arraycopy(_text, 0, newText, 0, _currentOffset);
  +	    _text = newText;
  +	}
  +	
  +	/**
  +	 * Links together the children of a node. Child nodes are linked
  +	 * through the _nextSibling array
  +	 */
  +	private void linkChildren(final int node) {
  +	    _parent[node] = _parentStack[_sp];
  +	    if (_previousSiblingStack[_sp] != 0) { // current not first child
  +		_nextSibling[_previousSiblingStack[_sp]] = node;
  +	    }
  +	    else {
  +		_offsetOrChild[_parentStack[_sp]] = node;
  +	    }
  +	    _previousSiblingStack[_sp] = node;
  +	}
  +
  +	/**
  +	 * Creates a text-node and checks if it is a whitespace node.
  +	 */
  +	private int maybeCreateTextNode(boolean isWhitespace) {
  +	    if (_currentOffset > _baseOffset) {
  +		final int node = nextNode();
  +		final int limit = _currentOffset;
  +		// Tag as whitespace node if the parser tells us that it is...
  +		if (isWhitespace) {
  +		    _whitespace.setBit(node);
  +		}
  +		// ...otherwise we check if this is a whitespace node, unless
  +		// the node is protected by an xml:space="preserve" attribute.
  +		else if (!_preserve) {
  +		    int i = _baseOffset;
  +		    while (isWhitespaceChar(_text[i++]) && i < limit) ;
  +		    if ((i == limit) && isWhitespaceChar(_text[i-1]))
  +			_whitespace.setBit(node);
  +		}
  +		_type[node] = TEXT;
  +		linkChildren(node);
  +		storeTextRef(node);
  +		return node;
  +	    }
  +	    return -1;
  +	}
  +
  +	/*
  +	 * This method will check if the current text node contains text that
  +	 * is already in the text array. If the text is found in the array
  +	 * then this method returns the offset of the previous instance of the
  +	 * string. Otherwise the text is inserted in the array, and the
  +	 * offset of the new instance is inserted.
  +	 * Updates the globals _baseOffset and _currentOffset
  +	 */
  +	private int maybeReuseText(final int length) {
  +	    final int base = _baseOffset;
  +	    if (length <= REUSABLE_TEXT_SIZE) {
  +		// Use a char array instead of string for performance benefit
  +		char[] chars = new char[length];
  +		System.arraycopy(_text, base, chars, 0, length);
  +		final Integer offsetObj = (Integer)_shortTexts.get(chars);
  +
  +		if (offsetObj != null) {
  +		    _currentOffset = base;       // step back current
  +		    return offsetObj.intValue(); // reuse previous string
  +		}
  +		else {
  +		    _shortTexts.put(chars, new Integer(base));
  +		}
  +	    }
  +	    _baseOffset = _currentOffset; // advance base to current
  +	    return base;
  +	}
  +
  +	/**
  +	 * Links a text reference (an occurance of a sequence of characters
  +	 * in the _text[] array) to a specific node index.
  +	 */
  +	private void storeTextRef(final int node) {
  +	    final int length = _currentOffset - _baseOffset;
  +	    _offsetOrChild[node] = maybeReuseText(length);
  +	    _lengthOrAttr[node]  = length;
  +	}
  +	
  +	/**
  +	 * Links an attribute value (an occurance of a sequence of characters
  +	 * in the _text[] array) to a specific attribute node index.
  +	 */
  +	private void storeAttrValRef(final int attributeNode) {
  +	    final int length = _currentOffset - _baseOffset;
  +	    _offset[attributeNode] = maybeReuseText(length);
  +	    _length[attributeNode] = length;
  +	}
  +
  +	/**
  +	 * Creates an attribute node
  +	 */
  +	private int makeAttributeNode(int parent, Attributes attList, int i)
  +	    throws SAXException {
  +	    final String name = attList.getQName(i);
  +	    boolean xmlAttr = false;
  +
  +	    // Trap namespace declarations and xml:space attributes
  +	    if (name.startsWith(XML_STRING)) {
  +		if (name.startsWith(XMLNS_STRING))
  +		    return -1;
  +		else if (name.startsWith(XMLSPACE_STRING))
  +		    xmlSpaceDefine(attList.getValue(i), parent);
  +		xmlAttr = true;
  +	    }
  +
  +	    // fall through to handle a regular attribute
  +    	    final int node = nextAttributeNode();
  +	    _type2[node] = internAttribute(name, xmlAttr);
  +	    _parent2[node] = parent;
  +	    characters(attList.getValue(i));
  +	    storeAttrValRef(node);
  +	    return node;
  +	}
  +	
  +	/****************************************************************/
  +	/*               SAX Interface Starts Here                      */
  +	/****************************************************************/
  +
  +	/**
  +	 * SAX2: Receive notification of character data.
  +	 */
  +	public void characters(char[] ch, int start, int length) {
  +	    if (_currentOffset + length > _text.length) {
  +		resizeTextArray(_text.length * 2);
  +	    }
  +	    System.arraycopy(ch, start, _text, _currentOffset, length);
  +	    _currentOffset += length;
  +	    maybeCreateTextNode(false);
  +	}
  +
  +	/**
  +	 * SAX2: Receive notification of the beginning of a document.
  +	 */
  +	public void startDocument() {
  +	    _shortTexts     = new Hashtable();
  +	    _names          = new Hashtable();
  +	    _sp             = 0;
  +	    _parentStack[0] = ROOTNODE;	// root
  +	    _currentNode    = ROOTNODE + 1;
  +	    _currentAttributeNode = 0;
  +	    //addNamespace(EMPTYSTRING,EMPTYSTRING); // default namespace
  +	    startPrefixMapping(EMPTYSTRING, EMPTYSTRING);
  +	}
  +
  +	/**
  +	 * SAX2: Receive notification of the end of a document.
  +	 */
  +	public void endDocument() {
  +
  +	    maybeCreateTextNode(false);
  +	    _shortTexts = null;
  +	    final int namesSize = _nextNameCode - NTYPES;
  +
  +	    // Fill the _namesArray[] array
  +	    _namesArray = new String[namesSize];
  +	    Enumeration keys = _names.keys();
  +	    while (keys.hasMoreElements()) {
  +		final String name = (String)keys.nextElement();
  +		final Integer idx = (Integer)_names.get(name);
  +		_namesArray[idx.intValue() - NTYPES] = name;
  +	    }
  +
  +	    _names = null;
  +	    _types = setupMapping(_namesArray);
  +
  +	    // trim arrays' sizes
  +	    resizeTextArray(_currentOffset);
  +	    
  +	    _firstAttributeNode = _currentNode;
  +	    shiftAttributes(_currentNode);
  +	    resizeArrays(_currentNode + _currentAttributeNode, _currentNode);
  +	    appendAttributes();
  +	    _treeNodeLimit = _currentNode;
  +
  +	    // Fill the _namespace[] and _nsNamesArray[] array
  +	    _namespace = new short[namesSize];
  +	    _nsNamesArray = new String[_nsCount];
  +	    for (int i = 0; i<namesSize; i++) {
  +		final String qname = _namesArray[i];
  +		final int col = _namesArray[i].lastIndexOf(':');
  +		if (col > -1) {
  +		    final String uri = _namesArray[i].substring(0, col);
  +		    final Integer idx = (Integer)_nsIndex.get(uri);
  +		    _namespace[i] = idx.shortValue();
  +		    _nsNamesArray[idx.intValue()] = uri;
  +		}
  +	    }
  +	}
  +	
  +	/**
  +	 * SAX2: Receive notification of the beginning of an element.
  +	 */
  +	public void startElement(String uri, String localName,
  +				 String qname, Attributes attributes)
  +	    throws SAXException {
  +
  +	    maybeCreateTextNode(false);
  +	    final int node = nextNode();
  +	    linkChildren(node);
  +	    _parentStack[++_sp] = node;
  +
  +	    // Process attribute list
  +	    final int length = attributes.getLength();
  +	    if (length > 0) {
  +		int i = 1, attrNode = makeAttributeNode(node, attributes, 0);
  +		while (attrNode == -1 && i < length) {
  +		    attrNode = makeAttributeNode(node, attributes, i++);
  +		}
  +		if (attrNode != -1) {
  +		    _lengthOrAttr[node] = attrNode; // first attr
  +		    while (i < length) {
  +			final int attrNode2 =
  +			    makeAttributeNode(node, attributes, i++);
  +			if (attrNode2 != -1) {
  +			    _nextSibling2[attrNode] = attrNode2;
  +			    attrNode = attrNode2;
  +			}
  +		    }
  +		}
  +	    }
  +
  +	    // Assign an internal type to this element (may exist)
  +	    if (uri != null)
  +		_type[node] = internElement(uri, localName);
  +	    else
  +		_type[node] = internElement(qname);
  +	}
  +	
  +	/**
  +	 * SAX2: Receive notification of the end of an element.
  +	 */
  +	public void endElement(String namespaceURI, String localName,
  +			       String qname) {
  +	    maybeCreateTextNode(false);
  +	    // Revert to strip/preserve-space setting from before this element
  +	    xmlSpaceRevert(_parentStack[_sp]);
  +	    // Pop all namespace declarations found in this element
  +	    //_nsDeclarations.pop(_parentStack[_sp]);
  +	    _previousSiblingStack[_sp--] = 0;
  +	}
  +
  +	/**
  +	 * SAX2: Receive notification of a processing instruction.
  +	 */
  +	public void processingInstruction(String target, String data)
  +	    throws SAXException {
  +	    maybeCreateTextNode(false);
  +	    final int node = nextNode();
  +	    _type[node] = PROCESSING_INSTRUCTION;
  +	    linkChildren(node);
  +	    characters(target + ' ' + data);
  +	    storeTextRef(node);
  +	}
  +
  +	/**
  +	 * SAX2: Receive notification of ignorable whitespace in element
  +	 * content. Similar to characters(char[], int, int).
  +	 */
  +	public void ignorableWhitespace(char[] ch, int start, int length) {
  +	    if (_currentOffset + length > _text.length) {
  +		resizeTextArray(_text.length * 2);
  +	    }
  +	    System.arraycopy(ch, start, _text, _currentOffset, length);
  +	    _currentOffset += length;
  +	    maybeCreateTextNode(true);
  +	}
  +
  +	/**
  +	 * SAX2: Receive an object for locating the origin of SAX document
  +	 * events. 
  +	 */
  +	public void setDocumentLocator(Locator locator) {
  +	    // Not handled
  +	}
  +
  +	/**
  +	 * SAX2: Receive notification of a skipped entity.
  +	 */
  +	public void skippedEntity(String name) {
  +	    // Not handled 
  +	}
  +
  +	/**
  +	 * SAX2: Begin the scope of a prefix-URI Namespace mapping.
  +	 */
  +	public void startPrefixMapping(String prefix, String uri) {
  +	    // Get the stack associated with this namespace prefix
  +	    Stack stack = (Stack)_nsPrefixes.get(prefix);
  +	    if (stack == null) {
  +		stack = new Stack();
  +		_nsPrefixes.put(prefix, stack);
  +	    }
  +
  +	    // Check if the URI already exists before pushing on stack
  +	    if (_nsIndex.get(uri) == null) {
  +		_nsIndex.put(uri, new Integer(_nsCount++));
  +	    }
  +	    stack.push(uri);
  +	}
  +
  +	/**
  +	 * SAX2: End the scope of a prefix-URI Namespace mapping.
  +	 */
  +	public void endPrefixMapping(String prefix) {
  +	    // Get the stack associated with this namespace prefix
  +	    final Stack stack = (Stack)_nsPrefixes.get(prefix);
  +	    if ((stack != null) && (!stack.empty())) stack.pop();
  +	}
  +
  +	/**
  +	 * Similar to the SAX2 method character(char[], int, int), but this
  +	 * method takes a string as its only parameter. The effect is the same.
  +	 */
  +	private void characters(final String string) {
  +	    final int length = string.length();
  +	    if (_currentOffset + length > _text.length) {
  +		resizeTextArray(_text.length * 2);
  +	    }
  +	    string.getChars(0, length, _text, _currentOffset);
  +	    _currentOffset += length;
  +	}
  +	
  +	private void resizeArrays(final int newSize, final int length) {
  +	    final short[] newType = new short[newSize];
  +	    System.arraycopy(_type, 0, newType, 0, length);
  +	    _type = newType;
  +	    final int[] newParent = new int[newSize];
  +	    System.arraycopy(_parent, 0, newParent, 0, length);
  +	    _parent = newParent;
  +	    final int[] newNextSibling = new int[newSize];
  +	    System.arraycopy(_nextSibling, 0, newNextSibling, 0, length);
  +	    _nextSibling = newNextSibling;
  +	    final int[] newOffsetOrChild = new int[newSize];
  +	    System.arraycopy(_offsetOrChild, 0, newOffsetOrChild, 0, length);
  +	    _offsetOrChild = newOffsetOrChild;
  +	    final int[] newLengthOrAttr = new int[newSize];
  +	    System.arraycopy(_lengthOrAttr, 0, newLengthOrAttr, 0, length);
  +	    _lengthOrAttr = newLengthOrAttr;
  +	    _whitespace.resize(newSize);
  +	}
  +	
  +	private void resizeArrays2(final int newSize, final int length) {
  +	    final short[] newType = new short[newSize];
  +	    System.arraycopy(_type2, 0, newType, 0, length);
  +	    _type2 = newType;
  +	    final int[] newParent = new int[newSize];
  +	    System.arraycopy(_parent2, 0, newParent, 0, length);
  +	    _parent2 = newParent;
  +	    final int[] newNextSibling = new int[newSize];
  +	    System.arraycopy(_nextSibling2, 0, newNextSibling, 0, length);
  +	    _nextSibling2 = newNextSibling;
  +	    final int[] newOffset = new int[newSize];
  +	    System.arraycopy(_offset, 0, newOffset, 0, length);
  +	    _offset = newOffset;
  +	    final int[] newLength = new int[newSize];
  +	    System.arraycopy(_length, 0, newLength, 0, length);
  +	    _length = newLength;
  +	}
  +	
  +	private void shiftAttributes(final int shift) {
  +	    final int limit = _currentAttributeNode;
  +	    int lastParent = -1;
  +	    for (int i = 0; i < limit; i++) {
  +		if (_parent2[i] != lastParent) {
  +		    lastParent = _parent2[i];
  +		    _lengthOrAttr[lastParent] = i + shift;
  +		}
  +		final int next = _nextSibling2[i];
  +		_nextSibling2[i] = next != 0 ? next + shift : 0;
  +	    }
  +	}
  +	
  +	private void appendAttributes() {
  +	    final int len = _currentAttributeNode;
  +	    if (len > 0) {
  +		final int dst = _currentNode;
  +		System.arraycopy(_type2,         0, _type,          dst, len);
  +		System.arraycopy(_parent2,       0, _parent,        dst, len);
  +		System.arraycopy(_nextSibling2,  0, _nextSibling,   dst, len);
  +		System.arraycopy(_offset,        0, _offsetOrChild, dst, len);
  +		System.arraycopy(_length,        0, _lengthOrAttr,  dst, len);
  +	    }
  +	}
   
  -             // trim arrays' sizes
  -             resizeTextArray(_currentOffset);
  -             
  -             _firstAttributeNode = _currentNode;
  -             shiftAttributes(_currentNode);
  -             resizeArrays(_currentNode + _currentAttributeNode, _currentNode);
  -             appendAttributes();
  -             _treeNodeLimit = _currentNode;
  -
  -             // Fill the _namespace[] array
  -             _namespace = new short[namesSize];
  -             for (int i=0; i<namesSize; i++) {
  -                  int col = _namesArray[i].lastIndexOf(':');
  -                  if (col == -1) { // default namespace
  -                      _namespace[i] = 0;
  -                  }
  -                  else {           // other namespaces
  -                      _namespace[i] =
  -                           (short)addNamespaceURI(_namesArray[i].substring(0,col));
  -                  }
  -             }
  -
  -             // Fill the _nsNamesArray[] array
  -             _nsNamesArray = new String[_nsCount];
  -             System.arraycopy(_nsNames,0,_nsNamesArray,0,_nsCount);
  -             _nsNames = null;
  -         }
  -         
  -         /**
  -          * Part of SAX handler interface
  -          */
  -         public void startElement(String elementName, AttributeList attList)
  -             throws SAXException {
  -
  -             maybeCreateTextNode();
  -             final int node = nextNode();
  -             linkChildren(node);
  -             _parentStack[++_sp] = node;
  -
  -             // process attribute list - including namespace declarations
  -             final int length = attList.getLength();
  -             if (length > 0) {
  -                  int i = 1, attrNode = makeAttributeNode(node, attList, 0);
  -                  while (attrNode == -1 && i < length) {
  -                      attrNode = makeAttributeNode(node, attList, i++);
  -                  }
  -                  if (attrNode != -1) {
  -                      _lengthOrAttr[node] = attrNode;         // first attr
  -                      while (i < length) {
  -                           final int attrNode2 =
  -                               makeAttributeNode(node, attList, i++);
  -                           if (attrNode2 != -1) {
  -                               _nextSibling2[attrNode] = attrNode2;
  -                               attrNode = attrNode2;
  -                           }
  -                      }
  -                  }
  -             }
  -             _type[node] = internElement(elementName);
  -         }
  -
  -         /**
  -          * Part of SAX handler interface
  -          */
  -         private int makeAttributeNode(int parent, AttributeList attList, int i)
  -             throws SAXException {
  -             final String name = attList.getName(i);
  -             boolean xmlAttr = false;
  -
  -             // process namespace declaration
  -             if (name.startsWith(XML_STRING)) {
  -                  if (name.startsWith(XMLNS_STRING)) {
  -                      // declaring the default namespace ?
  -                      if (name.length() == 5)
  -                           addNamespace(parent, EMPTYSTRING, attList.getValue(i));
  -                      // declaring some other namespace
  -                      else
  -                           addNamespace(parent, name.substring(6),
  -                                         attList.getValue(i));
  -                      return -1;
  -                  }
  -                  else if (name.startsWith(XMLSPACE_STRING)) {
  -                      xmlSpaceDefine(attList.getValue(i), parent);
  -                  }
  -                  xmlAttr = true;
  -             }
  -
  -             // fall through to handle a regular attribute
  -                 final int node = nextAttributeNode();
  -             _type2[node] = internAttribute(name,xmlAttr);
  -             _parent2[node] = parent;
  -             characters(attList.getValue(i));
  -             storeAttrValRef(node);
  -             return node;
  -         }
  -         
  -         /**
  -          * Part of SAX handler interface
  -          */
  -         public void endElement(String elementName) {
  -             maybeCreateTextNode();
  -             // Revert to strip/preserve-space setting from before this element
  -             xmlSpaceRevert(_parentStack[_sp]);
  -             // Pop all namespace declarations found in this element
  -             _nsDeclarations.pop(_parentStack[_sp]);
  -             _previousSiblingStack[_sp--] = 0;
  -         }
  -
  -         /**
  -          * Part of SAX handler interface
  -          */
  -         public void processingInstruction(String target, String data) {
  -             maybeCreateTextNode();
  -             final int node = nextNode();
  -             _type[node] = PROCESSING_INSTRUCTION;
  -             linkChildren(node);
  -             characters(target + ' ' + data);
  -             storeTextRef(node);
  -         }
  -                  
  -         /**
  -          * Part of SAX handler interface - NO, THIS IS NOT SAX, THIS IS SHITE!!
  -          */
  -         public void characters(final String string) {
  -             final int length = string.length();
  -             if (_currentOffset + length > _text.length) {
  -                  resizeTextArray(_text.length * 2);
  -             }
  -             string.getChars(0, length, _text, _currentOffset);
  -             _currentOffset += length;
  -         }
  -
  -         /**
  -          * can accumulate text from consecutive calls
  -          */
  -         public void characters(char[] ch, int start, int length) {
  -             if (_currentOffset + length > _text.length) {
  -                  resizeTextArray(_text.length * 2);
  -             }
  -             System.arraycopy(ch, start, _text, _currentOffset, length);
  -             _currentOffset += length;
  -             maybeCreateTextNode();
  -         }
  -         
  -         private void resizeArrays(final int newSize, final int length) {
  -             final short[] newType = new short[newSize];
  -             System.arraycopy(_type, 0, newType, 0, length);
  -             _type = newType;
  -             final int[] newParent = new int[newSize];
  -             System.arraycopy(_parent, 0, newParent, 0, length);
  -             _parent = newParent;
  -             final int[] newNextSibling = new int[newSize];
  -             System.arraycopy(_nextSibling, 0, newNextSibling, 0, length);
  -             _nextSibling = newNextSibling;
  -             final int[] newOffsetOrChild = new int[newSize];
  -             System.arraycopy(_offsetOrChild, 0, newOffsetOrChild, 0, length);
  -             _offsetOrChild = newOffsetOrChild;
  -             final int[] newLengthOrAttr = new int[newSize];
  -             System.arraycopy(_lengthOrAttr, 0, newLengthOrAttr, 0, length);
  -             _lengthOrAttr = newLengthOrAttr;
  -             _whitespace.resize(newSize);
  -         }
  -         
  -         private void resizeArrays2(final int newSize, final int length) {
  -             final short[] newType = new short[newSize];
  -             System.arraycopy(_type2, 0, newType, 0, length);
  -             _type2 = newType;
  -             final int[] newParent = new int[newSize];
  -             System.arraycopy(_parent2, 0, newParent, 0, length);
  -             _parent2 = newParent;
  -             final int[] newNextSibling = new int[newSize];
  -             System.arraycopy(_nextSibling2, 0, newNextSibling, 0, length);
  -             _nextSibling2 = newNextSibling;
  -             final int[] newOffset = new int[newSize];
  -             System.arraycopy(_offset, 0, newOffset, 0, length);
  -             _offset = newOffset;
  -             final int[] newLength = new int[newSize];
  -             System.arraycopy(_length, 0, newLength, 0, length);
  -             _length = newLength;
  -         }
  -         
  -         private void shiftAttributes(final int shift) {
  -             final int limit = _currentAttributeNode;
  -             int lastParent = -1;
  -             for (int i = 0; i < limit; i++) {
  -                  if (_parent2[i] != lastParent) {
  -                      lastParent = _parent2[i];
  -                      _lengthOrAttr[lastParent] = i + shift;
  -                  }
  -                  final int next = _nextSibling2[i];
  -                  _nextSibling2[i] = next != 0 ? next + shift : 0;
  -             }
  -         }
  -         
  -         private void appendAttributes() {
  -             final int len = _currentAttributeNode;
  -             if (len > 0) {
  -                  final int dst = _currentNode;
  -                  System.arraycopy(_type2,         0, _type,          dst, len);
  -                  System.arraycopy(_parent2,       0, _parent,        dst, len);
  -                  System.arraycopy(_nextSibling2,  0, _nextSibling,   dst, len);
  -                  System.arraycopy(_offset,        0, _offsetOrChild, dst, len);
  -                  System.arraycopy(_length,        0, _lengthOrAttr,  dst, len);
  -             }
  -         }
       } // end of DOMBuilder
   }
  
  
  
  1.2       +100 -51   xml-xalan/java/src/org/apache/xalan/xsltc/dom/DTDMonitor.java
  
  Index: DTDMonitor.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/DTDMonitor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DTDMonitor.java	2001/04/17 18:52:29	1.1
  +++ DTDMonitor.java	2001/05/01 13:16:20	1.2
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: DTDMonitor.java,v 1.1 2001/04/17 18:52:29 sboag Exp $
  + * @(#)$Id: DTDMonitor.java,v 1.2 2001/05/01 13:16:20 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -66,17 +66,17 @@
   import java.util.Enumeration;
   import java.util.Hashtable;
   
  -import org.xml.sax.*;
  +import org.xml.sax.XMLReader;
  +import org.xml.sax.DTDHandler;
  +import org.xml.sax.ext.DeclHandler;
  +import org.xml.sax.SAXException;
  +import org.xml.sax.SAXNotRecognizedException;
  +import org.xml.sax.SAXNotSupportedException;
   
  -import com.sun.xml.parser.Resolver;
  -import com.sun.xml.parser.DtdEventListener;
  -import com.sun.xml.parser.Parser;
  -
   import org.apache.xalan.xsltc.*;
   import org.apache.xalan.xsltc.runtime.AbstractTranslet;
  -
   
  -final public class DTDMonitor implements DtdEventListener {
  +final public class DTDMonitor implements DTDHandler, DeclHandler {
   
       // This is the name of the index used for ID attributes
       private final static String ID_INDEX_NAME = "##id";
  @@ -85,49 +85,44 @@
       // Stores names of all unparsed entities
       private Hashtable _unparsedEntities = new Hashtable();
   
  +    // Name of DTD declaration handler property of an XMLReader object
  +    private final static String DECL_HANDLER_PROP =
  +	"http://xml.org/sax/properties/declaration-handler";
  +
  +    // Error message used when the SAX parser does not generate DTD events
  +    private final static String NO_DTD_SUPPORT_STR =
  +	"Your SAX parser does not handle DTD declarations";
  +
       /**
  -     * Constructor
  +     * Constructor - does nothing
        */
       public DTDMonitor() { }
   
       /**
  -     * Retrieves the name of the ID attribute associated with an element type
  +     * Set an instance of this class as the DTD declaration handler for
  +     * an XMLReader object (using the setProperty() method).
        */
  -    private final String getIdAttrName(String elemtName) {
  -        final String idAttrName = (String)_idAttributes.get(elemtName);
  -        return ((idAttrName == null) ? "" : idAttrName);
  +    public void handleDTD(XMLReader reader) throws RuntimeException {
  +	try {
  +	    reader.setProperty(DECL_HANDLER_PROP, this);
  +	    reader.setDTDHandler(this);
  +	}
  +	catch (SAXNotRecognizedException e) {
  +	    throw(new RuntimeException(NO_DTD_SUPPORT_STR));
  +	}
  +	catch (SAXNotSupportedException e) {
  +	    throw(new RuntimeException(NO_DTD_SUPPORT_STR));
  +	}
       }
   
       /**
  -     * Leverages the Key Class to implement the XSLT id() function.
  -     * buildIdIndex creates the index (##id) that Key Class uses. 
  -     * The index contains the node index (int) and the id value (String).
  +     * SAX2: Receive notification of a notation declaration event.
        */
  -    public final void buildIdIndex(DOMImpl dom, int mask,
  -				   AbstractTranslet translet) {
  -	// Do nothing if there were no ID declarations in the DTD
  -	if ((_idAttributes == null) || (_idAttributes.isEmpty())) return;
  -	
  -	Enumeration elementNames = _idAttributes.keys();
  -	while (elementNames.hasMoreElements()) {
  -	    String elementName = (String)elementNames.nextElement();
  -	    String attrName = getIdAttrName(elementName);
  -	    int nodeType = dom.getGeneralizedType(elementName);
  -	    NodeIterator niter = dom.getTypedDescendantIterator(nodeType);
  -	    
  -	    int attributeType = dom.getGeneralizedType(attrName);
  -	    int node;
  -
  -	    while (( node = niter.next()) != NodeIterator.END) {
  -		// get id value for the node
  -		String idValue = dom.getAttributeValue(attributeType, node);
  -		// add entry into ##id index for KeyCall to handle
  -		translet.buildKeyIndex(ID_INDEX_NAME, mask|node, idValue);
  -	    }
  -	} 
  -    }
  +    public void notationDecl(String name, String publicId, String systemId)
  +	throws SAXException { }
   
       /**
  +     * SAX2: Receive notification of an unparsed entity declaration event.
        * The only method here that does not have to do with ID attributes.
        * Passes names of unparsed entities to the translet.
        */
  @@ -156,21 +151,75 @@
   	_idAttributes.put(element, "@"+attribute);
       }
   
  -    public void notationDecl(String name, String publicId, String systemId)
  -	throws SAXException { }
  -
  -    public void elementDecl(String elemtName, String contentModel) { }
  +    /**
  +     * SAX2 extension handler for DTD declaration events
  +     * Report an attribute type declaration
  +     */
  +    public void attributeDecl(String element, String attribute, 
  +			      String type, String defaultValue, String value) {
  +	// Stores the association between the name of an ID attribute and the
  +	// name of element that may contain it  Such an association would be
  +	// represented in a DTD as in:
  +	//           <!ATTLIST Person SSN ID #REQUIRED>
  +	// where 'Person' would be elemtName and 'SSN' would be the ID attribute
  +	_idAttributes.put(element, "@"+attribute);
  +    }
  +    
  +    /**
  +     * SAX2 extension handler for DTD declaration events
  +     * Report an element type declaration.
  +     */
  +    public void elementDecl(String element, String model) { }
  +                 
  +    /**
  +     * SAX2 extension handler for DTD declaration events
  +     * Report a parsed external entity declaration.
  +     */
  +    public void externalEntityDecl(String name, String pid, String sid) { }
  +                 
   
  -    public void endDtd() { }
  +    /**
  +     * SAX2 extension handler for DTD declaration events
  +     * Report an internal entity declaration.
  +     */
  +    public void internalEntityDecl(String name, String value) { }
   
  -    public void externalDtdDecl(String publicId, String systemId) { }
  +    /**
  +     * Retrieves the name of the ID attribute associated with an element type
  +     */
  +    private final String getIdAttrName(String elemtName) {
  +        final String idAttrName = (String)_idAttributes.get(elemtName);
  +        return ((idAttrName == null) ? "" : idAttrName);
  +    }
   
  -    public void externalEntityDecl(String name, String publicId,
  -				   String systemId) { }
  +    /**
  +     * Leverages the Key Class to implement the XSLT id() function.
  +     * buildIdIndex creates the index (##id) that Key Class uses. 
  +     * The index contains the node index (int) and the id value (String).
  +     */
  +    public final void buildIdIndex(DOMImpl dom, int mask,
  +				   AbstractTranslet translet) {
  +	// Do nothing if there were no ID declarations in the DTD
  +	if ((_idAttributes == null) || (_idAttributes.isEmpty())) return;
   	
  -    public void internalDtdDecl(String internalSubset) { }
  +	Enumeration elementNames = _idAttributes.keys();
  +	while (elementNames.hasMoreElements()) {
  +	    String elementName = (String)elementNames.nextElement();
  +	    String attrName = getIdAttrName(elementName);
  +	    int nodeType = dom.getGeneralizedType(elementName);
  +	    NodeIterator niter = dom.getTypedDescendantIterator(nodeType);
  +	    
  +	    int attributeType = dom.getGeneralizedType(attrName);
  +	    int node;
   
  -    public void internalEntityDecl(String name, String value) { }
  -    
  -    public void startDtd(String rootName) { }
  +	    while (( node = niter.next()) != NodeIterator.END) {
  +		// get id value for the node
  +		String idValue = dom.getAttributeValue(attributeType, node);
  +		// add entry into ##id index for KeyCall to handle
  +		translet.buildKeyIndex(ID_INDEX_NAME, mask|node, idValue);
  +	    }
  +	} 
  +    }
  +
   }
  +
  
  
  
  1.2       +28 -13    xml-xalan/java/src/org/apache/xalan/xsltc/dom/DocumentCache.java
  
  Index: DocumentCache.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/DocumentCache.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DocumentCache.java	2001/04/17 18:52:30	1.1
  +++ DocumentCache.java	2001/05/01 13:16:21	1.2
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: DocumentCache.java,v 1.1 2001/04/17 18:52:30 sboag Exp $
  + * @(#)$Id: DocumentCache.java,v 1.2 2001/05/01 13:16:21 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -71,7 +71,11 @@
   import java.util.Hashtable;
   import java.util.Date;
   
  -import com.sun.xml.parser.Parser;
  +import javax.xml.parsers.SAXParser;
  +import javax.xml.parsers.SAXParserFactory;
  +import javax.xml.parsers.ParserConfigurationException;
  +
  +import org.xml.sax.XMLReader;
   import org.xml.sax.SAXException;
   
   import org.apache.xalan.xsltc.DOM;
  @@ -83,12 +87,13 @@
   
   public final class DocumentCache implements DOMCache {
   
  -    private int            _size;
  -    private Hashtable      _references;
  -    private String[]       _URIs;
  -    private int            _count;
  -    private int            _current;
  -    private Parser         _parser;
  +    private int       _size;
  +    private Hashtable _references;
  +    private String[]  _URIs;
  +    private int       _count;
  +    private int       _current;
  +    private SAXParser _parser;
  +    private XMLReader _reader;
   
       /*
        * Inner class containing a DOMImpl object and DTD handler
  @@ -132,9 +137,9 @@
   	    try {
   		final long stamp = System.currentTimeMillis();
   
  -		_parser.setDocumentHandler(_dom.getBuilder());
  -		_parser.setDTDHandler(_dtdMonitor);
  -		_parser.parse(uri);
  +		_reader.setContentHandler(_dom.getBuilder());
  +		_dtdMonitor.handleDTD(_reader);
  +		_reader.parse(uri);
   		_dom.setDocumentURI(uri);
   
   		// The build time can be used for statistics for a better
  @@ -185,13 +190,23 @@
       /**
        * DocumentCache constructor
        */
  -    public DocumentCache(int size) {
  +    public DocumentCache(int size) throws SAXException {
   	_count = 0;
   	_current = 0;
   	_size  = size;
   	_references = new Hashtable(_size+2);
   	_URIs = new String[_size];
  -	_parser = new Parser();
  +
  +	try {
  +	    // Create a SAX parser and get the XMLReader object it uses
  +	    final SAXParserFactory factory = SAXParserFactory.newInstance();
  +	    _parser = factory.newSAXParser();
  +	    _reader = _parser.getXMLReader();
  +	}
  +	catch (ParserConfigurationException e) {
  +	    System.err.println("Your SAX parser is not configured correctly.");
  +	    System.exit(-1);
  +	}
       }
   
       /**
  
  
  
  1.2       +20 -7     xml-xalan/java/src/org/apache/xalan/xsltc/dom/LoadDocument.java
  
  Index: LoadDocument.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/LoadDocument.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LoadDocument.java	2001/04/17 18:52:32	1.1
  +++ LoadDocument.java	2001/05/01 13:16:21	1.2
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: LoadDocument.java,v 1.1 2001/04/17 18:52:32 sboag Exp $
  + * @(#)$Id: LoadDocument.java,v 1.2 2001/05/01 13:16:21 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -64,7 +64,14 @@
   
   import java.io.File;
   import java.net.URL;
  -import com.sun.xml.parser.Parser;
  +
  +import javax.xml.parsers.SAXParser;
  +import javax.xml.parsers.SAXParserFactory;
  +import javax.xml.parsers.ParserConfigurationException;
  +
  +import org.xml.sax.XMLReader;
  +import org.xml.sax.SAXException;
  +
   import org.apache.xalan.xsltc.DOM;
   import org.apache.xalan.xsltc.DOMCache;
   import org.apache.xalan.xsltc.Translet;
  @@ -116,14 +123,20 @@
   	}
   	else {
   	    // Parse the input document and construct DOM object
  -	    final Parser parser = new Parser();
  -	    dom = new DOMImpl();
  -	    parser.setDocumentHandler(dom.getBuilder());
  +	    // Create a SAX parser and get the XMLReader object it uses
  +	    final SAXParserFactory factory = SAXParserFactory.newInstance();
  +	    final SAXParser parser = factory.newSAXParser();
  +	    final XMLReader reader = parser.getXMLReader();
   
  +	    // Set the DOM's DOM builder as the XMLReader's SAX2 content handler
  +	    dom = new DOMImpl();
  +	    reader.setContentHandler(dom.getBuilder());
  +	    // Create a DTD monitor and pass it to the XMLReader object
   	    DTDMonitor dtdMonitor = new DTDMonitor();
  -	    parser.setDTDHandler(dtdMonitor);
  -	    parser.parse(uri);
  +	    dtdMonitor.handleDTD(reader);
  +
   	    dom.setDocumentURI(uri);
  +	    reader.parse(uri);
   
   	    // Set size of key/id indices
   	    translet.setIndexSize(dom.getSize());
  
  
  
  1.2       +8 -3      xml-xalan/java/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java
  
  Index: AbstractTranslet.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AbstractTranslet.java	2001/04/17 18:52:41	1.1
  +++ AbstractTranslet.java	2001/05/01 13:16:22	1.2
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: AbstractTranslet.java,v 1.1 2001/04/17 18:52:41 sboag Exp $
  + * @(#)$Id: AbstractTranslet.java,v 1.2 2001/05/01 13:16:22 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -101,6 +101,8 @@
   
       private DOMCache _domCache = null;
   
  +    private final static String EMPTYSTRING = "";
  +
       public final DOMAdapter makeDOMAdapter(DOM dom)
   	throws TransletException {
   	if (dom instanceof DOMImpl) {
  @@ -225,6 +227,7 @@
        */
       public void addDecimalFormat(String name, DecimalFormatSymbols symbols) {
   	// Remove any existing entries with the same name.
  +	if (name == null) name = EMPTYSTRING;
   	_formatSymbols.remove(name);
   	// Construct a DecimalFormat object containing the symbols we got
   	final DecimalFormat df = new DecimalFormat();
  @@ -238,10 +241,11 @@
        * Retrieves a named DecimalFormat object from _formatSymbols hashtable.
        */
       public final DecimalFormat getDecimalFormat(String name) {
  +	if (name == null) name = EMPTYSTRING;
   	final DecimalFormat df = (DecimalFormat)_formatSymbols.get(name);
   	if (df == null) {
   	    // This should really result in an error
  -	    return((DecimalFormat)_formatSymbols.get(""));
  +	    return((DecimalFormat)_formatSymbols.get(EMPTYSTRING));
   	}
   	else {
   	    return df;
  @@ -257,7 +261,7 @@
       
       public final String getUnparsedEntity(String name) {
   	final String uri = (String)_unparsedEntities.get(name);
  -	return uri == null ? "" : uri;
  +	return uri == null ? EMPTYSTRING : uri;
       }
   
       public final void setUnparsedEntityURIs(Hashtable table) {
  @@ -307,6 +311,7 @@
       public final void characters(final String string,
   				 TransletOutputHandler handler) 
   	throws TransletException {
  +	if (string == null) return;
   	final int length = string.length();
   	if (length > _characterArray.length) {
   	    _characterArray = new char[length];
  
  
  
  1.2       +106 -50   xml-xalan/java/src/org/apache/xalan/xsltc/runtime/AttributeList.java
  
  Index: AttributeList.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/runtime/AttributeList.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AttributeList.java	2001/04/17 18:52:41	1.1
  +++ AttributeList.java	2001/05/01 13:16:22	1.2
  @@ -1,5 +1,5 @@
   /*
  - * $Id: AttributeList.java,v 1.1 2001/04/17 18:52:41 sboag Exp $
  + * $Id: AttributeList.java,v 1.2 2001/05/01 13:16:22 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -63,18 +63,21 @@
   package org.apache.xalan.xsltc.runtime;
   
   import org.xml.sax.SAXException;
  +
   import java.util.Vector;
   import java.util.Enumeration;
   import java.util.Hashtable;
   
  -public class AttributeList implements org.xml.sax.AttributeList {
  +public class AttributeList implements org.xml.sax.Attributes {
   
       private final static String EMPTYSTRING = "";
       private final static String CDATASTRING = "CDATA";
   
       private Hashtable _attributes;
       private Vector    _names;
  +    private Vector    _qnames;
       private Vector    _values;
  +    private Vector    _uris;
       private int       _length;
   
       /**
  @@ -82,94 +85,147 @@
        */
       public AttributeList() {
   	_attributes = new Hashtable();
  -	_names = new Vector();
  +	_names  = new Vector();
   	_values = new Vector();
  +	_qnames = new Vector();
  +	_uris   = new Vector();
   	_length = 0;
       }
   
       /**
  -     * Adds an attribute to the list
  +     * SAX2: Return the number of attributes in the list. 
        */
  -    public void add(String name, String value) {
  -	_attributes.put(name,value);
  +    public int getLength() {
  +	return(_length);
       }
   
       /**
  -     * Clears the attribute list
  +     * SAX2: Look up an attribute's Namespace URI by index.
        */
  -    public void clear() {
  -	_length = 0;
  -	_attributes.clear();
  -	_names.removeAllElements();
  -	_values.removeAllElements();
  +    public String getURI(int index) {
  +	if (index < _length)
  +	    return((String)_uris.elementAt(index));
  +	else
  +	    return(null);
       }
   
       /**
  -     * Call this after all attributes have been added. This method prepares
  -     * the list before it can be passed to a SAX handler's startElement()
  +     * SAX2: Look up an attribute's local name by index.
        */
  -    public void prepare() {
  -	_length = 0;
  -	Enumeration names = _attributes.keys();
  -	Enumeration values = _attributes.elements();
  -	while (names.hasMoreElements()) {
  -	    _names.addElement(names.nextElement());
  -	    _values.addElement(values.nextElement());
  -	    _length++;
  -	}
  +    public String getLocalName(int index) {
  +	if (index < _length)
  +	    return((String)_names.elementAt(index));
  +	else
  +	    return(null);
       }
   
       /**
  -     * Return the number of attributes in this list.
  -     */
  -    public int getLength() {
  -	return(_length);
  -    }
  -    
  -    
  -    /**
        * Return the name of an attribute in this list (by position).
        */
  -    public String getName(int pos) {
  +    public String getQName(int pos) {
   	if (pos < _length)
  -	    return((String)_names.elementAt(pos));
  +	    return((String)_qnames.elementAt(pos));
   	else
  -	    return(EMPTYSTRING);
  +	    return(null);
       }
  -    
  +
       /**
  -     * Return the type of an attribute in the list (by position).
  +     * SAX2: Look up an attribute's type by index.
        */
  -    public String getType(int pos) {
  +    public String getType(int index) {
   	return(CDATASTRING);
  +    }
  +
  +    /**
  +     * SAX2: Look up the index of an attribute by Namespace name.
  +     */
  +    public int getIndex(String namespaceURI, String localPart) {
  +	return(0);
       }
  -    
  +
  +    /**
  +     * SAX2: Look up the index of an attribute by XML 1.0 qualified name.
  +     */
  +    public int getIndex(String qname) {
  +	return(0);
  +    }
  +
       /**
  -     * Return the value of an attribute in the list (by position).
  +     * SAX2: Look up an attribute's type by Namespace name.
        */
  +    public String getType(String uri, String localName) {
  +	return(CDATASTRING);
  +    }
  +
  +    /**
  +     * SAX2: Look up an attribute's type by qname.
  +     */
  +    public String getType(String qname) {
  +	return(CDATASTRING);
  +    }
  +
  +    /**
  +     * SAX2: Look up an attribute's value by index.
  +     */
       public String getValue(int pos) {
   	if (pos < _length)
   	    return((String)_values.elementAt(pos));
   	else
  -	    return(EMPTYSTRING);	
  +	    return(null);
       }
   
       /**
  -     * Return the value of an attribute in the list (by name).
  +     * SAX2: Look up an attribute's value by qname.
        */
  -    public String getValue(String name) {
  -	String value = (String)_attributes.get(name);
  -	if (value != null)
  -	    return(value);
  -	else
  -	    return(EMPTYSTRING);	
  +    public String getValue(String qname) {
  +	final Integer obj = (Integer)_attributes.get(qname);
  +	if (obj == null) return null;
  +	return(getValue(obj.intValue()));
  +    }
  +
  +    /**
  +     * SAX2: Look up an attribute's value by Namespace name - SLOW!
  +     */
  +    public String getValue(String uri, String localName) {
  +	return(getValue(uri+':'+localName));
  +    }
  +
  +    /**
  +     * Adds an attribute to the list
  +     */
  +    public void add(String qname, String value) {
  +	// Stuff the QName into the names vector & hashtable
  +	Integer obj = (Integer)_attributes.get(qname);
  +	if (obj == null) {
  +	    _attributes.put(qname, obj = new Integer(_length++));
  +	    _qnames.addElement(qname);
  +	    _values.addElement(value);
  +	    int col = qname.lastIndexOf(':');
  +	    if (col > -1) {
  +		_uris.addElement(qname.substring(0,col));
  +		_names.addElement(qname.substring(col+1));
  +	    }
  +	    else {
  +		_uris.addElement(EMPTYSTRING);
  +		_names.addElement(qname);
  +	    }
  +	}
  +	else {
  +	    final int index = obj.intValue();
  +	    _values.set(index, value);
  +	}
       }
   
       /**
  -     * Return the type of an attribute in the list (by name).
  +     * Clears the attribute list
        */
  -    public String getType(String name) {
  -    	return(CDATASTRING);
  +    public void clear() {
  +	_length = 0;
  +	_attributes.clear();
  +	_names.removeAllElements();
  +	_values.removeAllElements();
  +	_qnames.removeAllElements();
  +	_uris.removeAllElements();
       }
       
   }
  
  
  
  1.3       +27 -43    xml-xalan/java/src/org/apache/xalan/xsltc/runtime/DefaultRun.java
  
  Index: DefaultRun.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/runtime/DefaultRun.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DefaultRun.java	2001/04/27 20:06:15	1.2
  +++ DefaultRun.java	2001/05/01 13:16:22	1.3
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: DefaultRun.java,v 1.2 2001/04/27 20:06:15 curcuru Exp $
  + * @(#)$Id: DefaultRun.java,v 1.3 2001/05/01 13:16:22 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -71,19 +71,19 @@
   import java.net.UnknownHostException;
   import java.util.Vector;
   
  -import com.sun.xml.parser.Resolver;
  -import com.sun.xml.parser.DtdEventListener;
  -import com.sun.xml.parser.Parser;
  +import javax.xml.parsers.SAXParser;
  +import javax.xml.parsers.SAXParserFactory;
  +import javax.xml.parsers.ParserConfigurationException;
   
  -import org.xml.sax.InputSource;
  -import org.xml.sax.*;
  +import org.xml.sax.XMLReader;
  +import org.xml.sax.SAXException;
   
   import org.apache.xalan.xsltc.*;
   import org.apache.xalan.xsltc.dom.DOMImpl;
   import org.apache.xalan.xsltc.dom.Axis;
   import org.apache.xalan.xsltc.dom.DTDMonitor;
   
  -public final class DefaultRun {
  +final class DefaultRun {
   
       private TransletOutputHandler _handler;
   
  @@ -124,20 +124,24 @@
   	    final Class clazz = Class.forName(_className);
   	    final Translet translet = (Translet)clazz.newInstance();
   
  -	    final Parser parser = new Parser();
  +	    // Create a SAX parser and get the XMLReader object it uses
  +	    final SAXParserFactory factory = SAXParserFactory.newInstance();
  +	    final SAXParser parser = factory.newSAXParser();
  +	    final XMLReader reader = parser.getXMLReader();
  +
  +	    // Set the DOM's DOM builder as the XMLReader's SAX2 content handler
   	    final DOMImpl dom = new DOMImpl();
  -	    parser.setDocumentHandler(dom.getBuilder());
  +	    reader.setContentHandler(dom.getBuilder());
  +	    // Create a DTD monitor and pass it to the XMLReader object
  +	    final DTDMonitor dtdMonitor = new DTDMonitor();
  +	    dtdMonitor.handleDTD(reader);
   
   	    _translet = (AbstractTranslet)translet;
  -
  -	    DTDMonitor dtdMonitor = new DTDMonitor();
  -	    parser.setDTDHandler(dtdMonitor);
   	    dom.setDocumentURI(_fileName);
  -
   	    if (_uri)
  -		parser.parse(_fileName);
  +		reader.parse(_fileName);
   	    else
  -		parser.parse("file:"+(new File(_fileName).getAbsolutePath()));
  +		reader.parse("file:"+(new File(_fileName).getAbsolutePath()));
   	    
   	    // Set size of key/id indices
   	    _translet.setIndexSize(dom.getSize());
  @@ -182,7 +186,7 @@
   		System.err.println(e.toString());
   		e.printStackTrace();
   	    }
  -	    doSystemExit(1); return;	    
  +	    System.exit(1);	    
   	}
   	catch (RuntimeException e) {
   	    System.err.println("\nRuntime Error: " + e.getMessage());
  @@ -190,29 +194,29 @@
   		System.err.println(e.toString());
   		e.printStackTrace();
   	    }
  -	    doSystemExit(1); return;
  +	    System.exit(1);
   	}
   	catch (FileNotFoundException e) {
   	    System.err.println("Error: File or URI '"+_fileName+"' not found.");
  -	    doSystemExit(1); return;
  +	    System.exit(1);
   	}
   	catch (MalformedURLException e) {
   	    System.err.println("Error: Invalid URI '"+_fileName+"'.");
  -	    doSystemExit(1); return;
  +	    System.exit(1);
   	}
   	catch (ClassNotFoundException e) {
   	    System.err.println("Error: Cannot find class '"+_className+"'.");
  -	    doSystemExit(1); return;
  +	    System.exit(1);
   	}
           catch (UnknownHostException e) {
   	    System.err.println("Error: Can't resolve URI specification '"+ 
   			       _fileName+"'.");
  -	    doSystemExit(1); return;
  +	    System.exit(1);
           }
   	catch (Exception e) {
   	    e.printStackTrace();
   	    System.err.println("Error: internal error.");
  -	    doSystemExit(1); return;
  +	    System.exit(1);
   	}
       }
   
  @@ -228,26 +232,9 @@
   
       public static void printUsage() {
   	System.err.println(USAGE_STRING);
  -	doSystemExit(1); throw new RuntimeException("System.exit(1) would be called");
  +	System.exit(1);
       }
   
  -    /** If we should call System.exit or not */
  -    protected static boolean allowSystemExit = true;
  -
  -    /** Worker method to call System.exit or not */
  -    protected static void doSystemExit(int retVal) {
  -        if (allowSystemExit)
  -            System.exit(retVal);
  -    }
  -
  -    /** 
  -     * Command line runnability.
  -     * j jarFileName
  -     * u (isUriSpecified)
  -     * x (isDebugSpecified)
  -     * h printUsage()
  -     * s (don't allow System.exit)
  -     */
       public static void main(String[] args) {
   	try {
   	    if (args.length > 0) {
  @@ -264,9 +251,6 @@
   		    else if (args[i].equals("-x")) {
   			debug = true;
   		    }
  -		    else if (args[i].equals("-s")) {
  -			allowSystemExit = false;
  -		    }
   		    else if (args[i].equals("-j")) {
   			isJarFileSpecified = true;	
   			jarFile = args[++i];
  @@ -305,7 +289,7 @@
   		if (i == args.length) {
   		    handler.setParameters(params);
   		    handler.doTransform();
  -		    doSystemExit(0); return;
  +		    System.exit(0);
   		}
   	    }
   	    printUsage();
  
  
  
  1.2       +68 -23    xml-xalan/java/src/org/apache/xalan/xsltc/runtime/DefaultSAXOutputHandler.java
  
  Index: DefaultSAXOutputHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/runtime/DefaultSAXOutputHandler.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultSAXOutputHandler.java	2001/04/17 18:52:43	1.1
  +++ DefaultSAXOutputHandler.java	2001/05/01 13:16:22	1.2
  @@ -1,5 +1,5 @@
   /*
  - * $Id: DefaultSAXOutputHandler.java,v 1.1 2001/04/17 18:52:43 sboag Exp $
  + * @(#)$Id: DefaultSAXOutputHandler.java,v 1.2 2001/05/01 13:16:22 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -71,12 +71,12 @@
   import java.io.BufferedWriter;
   import java.util.Hashtable;
   
  -import org.xml.sax.DocumentHandler;
  +import org.xml.sax.ContentHandler;
   import org.xml.sax.Locator;
  -import org.xml.sax.AttributeList;
  +import org.xml.sax.Attributes;
   import org.xml.sax.SAXException;
   
  -public class DefaultSAXOutputHandler implements DocumentHandler{
  +public class DefaultSAXOutputHandler implements ContentHandler {
   
       // The output writer
       private Writer _writer;
  @@ -109,17 +109,22 @@
       private static final char[] GT_CR    = ">\n".toCharArray();
       private static final char[] GT_LT_SL = "></".toCharArray();
       private static final char[] SL_GT    = "/>".toCharArray();
  +    private static final char[] XMLNS    = " xmlns".toCharArray();
   
       // All of these are used to control/track output indentation
       private static final char[] INDENT = "                    ".toCharArray();
       private static final int MAX_INDENT_LEVEL = (INDENT.length >> 1);
       private static final int MAX_INDENT       = INDENT.length;
   
  +    private static final String EMPTYSTRING = "";
  +
       private boolean   _indent = false;
       private boolean   _indentNextEndTag = false;
       private boolean   _linefeedNextStartTag = false;
       private int       _indentLevel = 0;
   
  +    // This is used for aggregating namespace declarations
  +    private AttributeList _namespaceDeclarations = new AttributeList();
   
       /**
        * Constructor - simple, initially for use in servlets
  @@ -138,12 +143,10 @@
   
           OutputStreamWriter writer;
           try {
  -            writer = new OutputStreamWriter(out, encoding);
  -	    _encoding = encoding;
  +            writer = new OutputStreamWriter(out, _encoding = encoding);
           }
           catch (java.io.UnsupportedEncodingException e) {
  -            writer = new OutputStreamWriter(out, "utf-8");
  -	    _encoding = "utf-8";
  +            writer = new OutputStreamWriter(out, _encoding = "utf-8" );
           }
           _writer = new BufferedWriter(writer);
   	init();
  @@ -162,10 +165,11 @@
        */
       private void init() throws IOException {
   
  +	// These are HTML tags that can occur as empty elements with
  +	// no closing tags (such as <br> insteadof XHTML's <br/>).
           final String[] tags = { "area", "base", "basefont", "br",
   				"col", "frame", "hr", "img", "input",
   				"isindex", "link", "meta", "param" };
  -
           for (int i = 0; i < tags.length; i++)
               _emptyElements.put(tags[i],tags[i]);
   
  @@ -194,23 +198,21 @@
   	// Assume this is an HTML document if first element is <html>
   	if ((element != null) && (element.toLowerCase().equals("html"))) {
   	    _outputType = TextOutput.HTML;
  -	    System.out.println("output method determine to be HTML");
   	}
   	// Otherwise we assume this is an XML document
   	else {
  -	    System.out.println("output method determine to be XML");
   	    _outputType = TextOutput.XML;
   	    emitHeader();
   	}
       }
   
       /**
  -     * SAX: Receive notification of the beginning of a document.
  +     * SAX2: Receive notification of the beginning of a document.
        */
       public void startDocument() throws SAXException { }
   
       /**
  -     * SAX: Receive notification of the end of an element.
  +     * SAX2: Receive notification of the end of an element.
        */
       public void endDocument() throws SAXException  { 
           try {
  @@ -221,9 +223,10 @@
       }
   
       /**
  -     * SAX: Receive notification of the beginning of an element.
  +     * SAX2: Receive notification of the beginning of an element.
        */
  -    public void startElement(String elementName, AttributeList attrs) throws
  +    public void startElement(String uri, String localname,
  +			     String elementName, Attributes attrs) throws
   	SAXException {
   	try {
   	    // Determine the output document type if not already known
  @@ -245,12 +248,28 @@
   	    _writer.write('<');
   	    _writer.write(elementName);
   	    _startTagOpen = true;
  +
  +	    // Output namespace declarations first...
  +	    int declCount = _namespaceDeclarations.getLength();
  +	    for (int i=0; i<declCount; i++) {
  +		final String prefix = _namespaceDeclarations.getQName(i);
  +		_writer.write(XMLNS);
  +		if ((prefix != null) && (prefix != EMPTYSTRING)) {
  +		    _writer.write(':');
  +		    _writer.write(prefix);
  +		}
  +		_writer.write('=');
  +		_writer.write('\"');
  +		_writer.write(_namespaceDeclarations.getValue(i));
  +		_writer.write('\"');
  +            }
  +	    _namespaceDeclarations.clear();
   
  -	    // Output attributes (process in reverse order
  +	    // ...then output all attributes
   	    int attrCount = attrs.getLength();
   	    for (int i=0; i<attrCount; i++) {
   		_writer.write(' ');
  -		_writer.write(attrs.getName(i));
  +		_writer.write(attrs.getQName(i));
   		_writer.write('=');
   		_writer.write('\"');
   		_writer.write(attrs.getValue(i));
  @@ -262,10 +281,12 @@
       }
   
       /**
  -     * SAX: Receive notification of the end of an element.
  +     * SAX2: Receive notification of the end of an element.
        */
  -    public void endElement(String elementName)  throws SAXException {
  +    public void endElement(String uri, String localname,
  +			   String elementName)  throws SAXException {
   	try {
  +
               _linefeedNextStartTag = false;
   
               if (_indent) _indentLevel--;
  @@ -277,12 +298,16 @@
                   if ((_indent) && (_indentNextEndTag)) indent(false);
                   char[] endTag = (char[])_endTags.get(elementName);
                   if (endTag == null) {
  +		    // CHANGED OUTPUT LAYOUT
  +		    /*
   		    if (_outputType == TextOutput.HTML) { 
                           endTag = ("</"+elementName+">\n").toCharArray();
   		    } else {
   			// works for XML, TEXT
                           endTag = ("</"+elementName+">").toCharArray();
   		    }
  +		    */
  +		    endTag = ("</"+elementName+">\n").toCharArray();
                       _endTags.put(elementName,endTag);
                   }
                   _writer.write(endTag);
  @@ -309,7 +334,7 @@
       }
   
       /**
  -     * SAX: Receive notification of character data.
  +     * SAX2: Receive notification of character data.
        */
       public void characters(char[] ch, int off, int len) throws SAXException {
           try {
  @@ -332,7 +357,7 @@
       }
   
       /**
  -     * SAX: Receive notification of a processing instruction.
  +     * SAX2: Receive notification of a processing instruction.
        */
       public void processingInstruction(String target, String data) throws 
   	SAXException {
  @@ -353,14 +378,34 @@
       }
   
       /**
  -     * SAX: Receive notification of ignorable whitespace in element content.
  +     * SAX2: Receive notification of ignorable whitespace in element content.
        */
       public void ignorableWhitespace(char[] ch, int start, int len) { }
   
       /**
  -     * SAX: Receive an object for locating the origin of SAX document events.
  +     * SAX2: Receive an object for locating the origin of SAX document events.
        */
       public void setDocumentLocator(Locator locator) { } 
  +
  +    /**
  +     * SAX2: Receive notification of a skipped entity.
  +     */
  +    public void skippedEntity(String name) { }
  +
  +    /**
  +     * SAX2: Begin the scope of a prefix-URI Namespace mapping.
  +     *       Namespace declarations are output in startElement()
  +     */
  +    public void startPrefixMapping(String prefix, String uri) {
  +	_namespaceDeclarations.add(prefix,uri);
  +    }
  +
  +    /**
  +     * SAX2: End the scope of a prefix-URI Namespace mapping.
  +     */
  +    public void endPrefixMapping(String prefix) {
  +	// Do nothing
  +    }
   
       /**
        * Adds a newline in the output stream and indents to correct level
  
  
  
  1.2       +66 -52    xml-xalan/java/src/org/apache/xalan/xsltc/runtime/TextOutput.java
  
  Index: TextOutput.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/runtime/TextOutput.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TextOutput.java	2001/04/17 18:52:46	1.1
  +++ TextOutput.java	2001/05/01 13:16:22	1.2
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: TextOutput.java,v 1.1 2001/04/17 18:52:46 sboag Exp $
  + * @(#)$Id: TextOutput.java,v 1.2 2001/05/01 13:16:22 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -69,7 +69,7 @@
   import java.util.Stack;
   
   import org.apache.xalan.xsltc.*;
  -import org.xml.sax.DocumentHandler;
  +import org.xml.sax.ContentHandler;
   import org.xml.sax.SAXException;
   
   public final class TextOutput implements TransletOutputHandler {
  @@ -120,18 +120,17 @@
       private Stack     _nodeStack;
       private Stack     _prefixStack;
   
  -
       // Holds the current tree depth (see startElement() and endElement()).
       private int _depth = 0;
   
       private String _encoding;
   
  -    private DocumentHandler  _saxHandler;
  +    private ContentHandler _saxHandler;
   
       /**
        * Constructor
        */
  -    public TextOutput(DocumentHandler handler) throws IOException {
  +    public TextOutput(ContentHandler handler) throws IOException {
           _saxHandler = handler;
           init();
       }
  @@ -139,7 +138,7 @@
       /**
        * Constructor
        */
  -    public TextOutput(DocumentHandler handler, String encoding)
  +    public TextOutput(ContentHandler handler, String encoding)
   	throws IOException {
           _saxHandler = handler;
           init();
  @@ -180,18 +179,18 @@
       /**
        * Emit header through the SAX handler
        */
  -    private void emitHeader() throws SAXException{
  +    private void emitHeader() throws SAXException {
   	// Make sure the _encoding string contains something
  -	if ((_encoding == null) || (_encoding == "")) _encoding = "utf-8";
  +	if ((_encoding == null) || (_encoding == EMPTYSTRING))
  +	    _encoding = "utf-8";
   
   	// Output HTML header as META element
   	if (_outputType == HTML) {
   	    AttributeList attrs = new AttributeList();
   	    attrs.add("http-equiv","Content-Type");
   	    attrs.add("content","text/html; charset="+_encoding);
  -	    attrs.prepare();
  -	    _saxHandler.startElement("meta", attrs);
  -	    _saxHandler.endElement("meta");
  +	    _saxHandler.startElement(null, null, "meta", attrs);
  +	    _saxHandler.endElement(null, null, "meta");
   	}
       }
   
  @@ -212,7 +211,6 @@
       public void closeStartTag() throws TransletException {
   	try {
   	    _startTagOpen = false;
  -	    _attributes.prepare();
   	    
   	    // Output current element, either as element or CDATA section
   	    if (_cdataElements.containsKey(_elementName)) {
  @@ -226,13 +224,21 @@
   		int col = _elementName.indexOf(':');
   		if (col > 0) {
   		    final String prefix = _elementName.substring(0,col);
  -		    if (lookupNamespace(prefix) == null) {
  +		    final String localname = _elementName.substring(col+1);
  +		    final String uri = lookupNamespace(prefix);
  +		    if (uri == null) {
   			throw new TransletException("Namespace for prefix "+
   						    prefix+" has not been "+
   						    "declared.");
   		    }
  +		    _saxHandler.startElement(uri, localname,
  +					     _elementName, _attributes);
  +		}
  +		else {
  +		    final String uri = lookupNamespace(EMPTYSTRING);
  +		    _saxHandler.startElement(uri, _elementName,
  +					     _elementName, _attributes);
   		}
  -		_saxHandler.startElement(_elementName, _attributes);
   	    }
   
   	    // Insert <META> tag directly after <HEAD> element in HTML output
  @@ -289,7 +295,7 @@
        * output.
        */ 
       public void insertCdataElement(String elementName) {
  -	_cdataElements.put(elementName,"");
  +	_cdataElements.put(elementName,EMPTYSTRING);
       }
   
       /**
  @@ -558,7 +564,7 @@
                   _cdataTagOpen = false;
               }
   
  -            _saxHandler.endElement(elementName);
  +            _saxHandler.endElement(null, null, elementName);
   
               popNamespaces();
               _depth--;
  @@ -628,46 +634,61 @@
   	_nodeStack = new Stack();
   	_prefixStack = new Stack();
   
  -	_depth = -1;
  -	pushNamespace("","");
  +	// Define the default namespace (initially maps to "" uri)
  +	Stack stack =  new Stack();
  +	_namespaces.put(EMPTYSTRING, stack);
  +	stack.push(EMPTYSTRING);
  +	_prefixStack.push(EMPTYSTRING);
  +	_nodeStack.push(new Integer(-1));
   	_depth = 0;
       }
   
       /**
        * Declare a prefix to point to a namespace URI
        */
  -    private void pushNamespace(String prefix, String uri) {
  +    private void pushNamespace(String prefix, String uri) throws SAXException {
   	Stack stack;
  +	// Get the stack that contains URIs for the specified prefix
   	if ((stack = (Stack)_namespaces.get(prefix)) == null) {
   	    stack = new Stack();
   	    _namespaces.put(prefix, stack);
   	}
  +	// Quit now if the URI the prefix currently maps to is the same as this
  +	if (!stack.empty() && uri.equals(stack.peek())) return;
  +	// Put this URI on top of the stack for this prefix
   	stack.push(uri);
   	_prefixStack.push(prefix);
   	_nodeStack.push(new Integer(_depth));
  +	_saxHandler.startPrefixMapping(prefix, uri);
       }
   
       /**
        * Undeclare the namespace that is currently pointed to by a given prefix
        */
  -    private void popNamespace(String prefix) {
  +    private void popNamespace(String prefix) throws SAXException {
   	Stack stack;
   	if ((stack = (Stack)_namespaces.get(prefix)) != null) {
   	    stack.pop();
  +	    _saxHandler.endPrefixMapping(prefix);
   	}
       }
   
       /**
        * Pop all namespace definitions that were delcared by the current element
        */
  -    private void popNamespaces() {
  -	while (true) {
  -	    if (_nodeStack.isEmpty()) return;
  -	    Integer i = (Integer)(_nodeStack.peek());
  -	    if (i.intValue() != _depth) return;
  -	    _nodeStack.pop();
  -	    popNamespace((String)_prefixStack.pop());
  +    private void popNamespaces() throws TransletException {
  +	try {
  +	    while (true) {
  +		if (_nodeStack.isEmpty()) return;
  +		Integer i = (Integer)(_nodeStack.peek());
  +		if (i.intValue() != _depth) return;
  +		_nodeStack.pop();
  +		popNamespace((String)_prefixStack.pop());
  +	    }
   	}
  +	catch (SAXException e) {
  +	    throw new TransletException(e);
  +	}
       }
   
       /**
  @@ -685,31 +706,24 @@
        */
       public void declareNamespace(final String name, final String uri)
   	throws TransletException {
  -	if (_startTagOpen) {
  -	    String prefix;
  -	    int col = name.indexOf(':');
  -	    if (col == -1)
  -		prefix = EMPTYSTRING;
  -	    else
  -		prefix = name.substring(col+1);
  -
  -	    // Do not output the namespace declaration if it is already
  -	    // in scope with the same prefix
  -	    final String ns = lookupNamespace(prefix);
  -	    if ((ns != null) && (ns == uri))
  -		return;
  -	    if ((uri.equals(EMPTYSTRING)) && (prefix.equals(EMPTYSTRING)))
  -		return;
  -	    // Push the namespace definition
  -	    pushNamespace(prefix,uri);
  -	    _attributes.add(name,uri);
  -	}
  -	else if (_cdataTagOpen) {
  -	    throw new TransletException("namespace declaration within CDATA");
  +	try {
  +	    if (_startTagOpen) {
  +		if (name.indexOf(':') == -1)
  +		    pushNamespace(EMPTYSTRING,uri);
  +		else
  +		    pushNamespace(name.substring(6),uri);
  +	    }
  +	    else if (_cdataTagOpen) {
  +		throw new TransletException("namespace declaration within "+
  +					    "CDATA element");
  +	    }
  +	    else {
  +		throw new TransletException("namespace declaration '"+name+
  +					    "'='"+uri+"' outside of element");
  +	    }
   	}
  -	else {
  -	    throw new TransletException("namespace declaration '"+name+
  -					"'='"+uri+"' outside of element");
  +	catch (SAXException e) {
  +	    throw new TransletException(e);
   	}
       }
   
  @@ -727,7 +741,7 @@
   
   	if (uri == null)
   	    return(local);
  -	else if (uri.equals(""))
  +	else if (uri == EMPTYSTRING)
   	    return(local);
   	else
   	    return(uri+":"+local);
  
  
  

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