This commit was manufactured by cvs2svn to create tag
'jaxp-ri-1_2_0-fcs-03'.

git-svn-id: https://svn.apache.org/repos/asf/xalan/java/tags/jaxp-ri-1_2_0-fcs-03@336254 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/build.xml b/build.xml
index 0e09c0f..5316f9c 100644
--- a/build.xml
+++ b/build.xml
@@ -361,7 +361,7 @@
     </javac>
   </target>
 
-  <target name="xsltc.jar" depends="xsltc.compile"
+  <target name="xsltc.unbundledjar" depends="xsltc.compile"
     description="Jar just the xsltc.jar file" >
     <!-- Copy over the manifest, with filtering (for version number) -->
     <filter token="impl.version" value="${impl.version}"/>
@@ -374,7 +374,7 @@
   </target>
 
 
-  <target name="xsltc.bundledjar" depends="xsltc.compile"
+  <target name="xsltc.jar" depends="xsltc.compile"
      description="Jar xsltc, BCEL,JLex,java_cup,runtime and jakarta regexp">
     <!-- make a tmp directory to work in -->
     <delete dir="${build.dir}/xsltctmp" includeEmptyDirs="true" quiet="true"/>
@@ -449,11 +449,14 @@
         includeEmptyDirs="true" quiet="true"/>
 
     <!-- create new META-INF dir w/ transformer factory default -->
+    <!-- GTM: comment this out so that bundled xsltc.jar does not have
+	 service provider default until further notice 2/20/2002
     <mkdir dir="${build.dir}/xsltctmp/META-INF"/>
     <mkdir dir="${build.dir}/xsltctmp/META-INF/services"/>
     <copy todir="${build.dir}/xsltctmp/META-INF/services"
       file="${src.dir}/${xsltc.reldir}/javax.xml.transform.TransformerFactory"
     />
+    -->
 
     <!-- Copy over the manifest, with filtering (for version number) -->
     <filter token="impl.version" value="${impl.version}"/>
diff --git a/src/org/apache/xalan/xsltc/DOM.java b/src/org/apache/xalan/xsltc/DOM.java
index 040e74e..97e1d47 100644
--- a/src/org/apache/xalan/xsltc/DOM.java
+++ b/src/org/apache/xalan/xsltc/DOM.java
@@ -132,4 +132,6 @@
     public void setupMapping(String[] names, String[] namespaces);
     public boolean isElement(final int node);
     public boolean isAttribute(final int node);
+    public String lookupNamespace(int node, String prefix)
+	throws TransletException;
 }
diff --git a/src/org/apache/xalan/xsltc/compiler/ApplyTemplates.java b/src/org/apache/xalan/xsltc/compiler/ApplyTemplates.java
index b0143cb..985f683 100644
--- a/src/org/apache/xalan/xsltc/compiler/ApplyTemplates.java
+++ b/src/org/apache/xalan/xsltc/compiler/ApplyTemplates.java
@@ -139,6 +139,7 @@
      * some template in the stylesheet uses parameters. 
      */
     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
+	boolean setStartNodeCalled = false;
 	final Stylesheet stylesheet = classGen.getStylesheet();
 	final ConstantPoolGen cpg = classGen.getConstantPool();
 	final InstructionList il = methodGen.getInstructionList();
@@ -165,6 +166,7 @@
 	    translateContents(classGen, methodGen);
 	}
 
+
 	il.append(classGen.loadTranslet());
 
 	// The 'select' expression is a result-tree
@@ -192,6 +194,7 @@
 							     NODE_ITERATOR_SIG);
 		il.append(methodGen.loadCurrentNode());
 		il.append(new INVOKEINTERFACE(setStartNode,2));
+		setStartNodeCalled = true;	
 	    }
 	    else {
 		if (_select == null)
@@ -201,7 +204,7 @@
 	    }
 	}
 
-	if (_select != null) {
+	if (_select != null && !setStartNodeCalled) {
 	    _select.startResetIterator(classGen, methodGen);
 	}
 
diff --git a/src/org/apache/xalan/xsltc/compiler/AttributeValue.java b/src/org/apache/xalan/xsltc/compiler/AttributeValue.java
index 64c0340..8f33670 100644
--- a/src/org/apache/xalan/xsltc/compiler/AttributeValue.java
+++ b/src/org/apache/xalan/xsltc/compiler/AttributeValue.java
@@ -71,16 +71,16 @@
 
 	AttributeValue result;
 	if (text.indexOf('{') != -1) {
-	    result = new AttributeValueTemplate(text, parser);
+	    result = new AttributeValueTemplate(text, parser, parent);
 	}
 	else if (text.indexOf('}') != -1) {
-	    result = new AttributeValueTemplate(text, parser);
+	    result = new AttributeValueTemplate(text, parser, parent);
 	}
 	else {
 	    result = new SimpleAttributeValue(text);
 	    result.setParser(parser);
+	    result.setParent(parent);
 	}
-	result.setParent(parent);
 	return result;
     }
 }
diff --git a/src/org/apache/xalan/xsltc/compiler/AttributeValueTemplate.java b/src/org/apache/xalan/xsltc/compiler/AttributeValueTemplate.java
index 49f2e20..00d981d 100644
--- a/src/org/apache/xalan/xsltc/compiler/AttributeValueTemplate.java
+++ b/src/org/apache/xalan/xsltc/compiler/AttributeValueTemplate.java
@@ -72,10 +72,14 @@
 
 final class AttributeValueTemplate extends AttributeValue {
 
-    public AttributeValueTemplate(String value, Parser parser) {
+    public AttributeValueTemplate(String value, Parser parser, 
+	SyntaxTreeNode parent) 
+    {
+	setParent(parent);
 	setParser(parser);
-	if (check(value, parser))
+	if (check(value, parser)) {
 	    parseAVTemplate(0, value, parser);
+	}
     }
 
     private void parseAVTemplate(final int start, String text, Parser parser) {
diff --git a/src/org/apache/xalan/xsltc/compiler/Constants.java b/src/org/apache/xalan/xsltc/compiler/Constants.java
index 6772185..4e6acc7 100644
--- a/src/org/apache/xalan/xsltc/compiler/Constants.java
+++ b/src/org/apache/xalan/xsltc/compiler/Constants.java
@@ -486,6 +486,10 @@
     public static final int POSITION_INDEX = 2;
     public static final int LAST_INDEX     = 3;
 
+    public static final String XMLNS_PREFIX = "xmlns";
+    public static final String XMLNS_STRING = "xmlns:";
+    public static final String XMLNS_URI 
+	= "http://www.w3.org/2000/xmlns/";
     public static final String XSLT_URI
 	= "http://www.w3.org/1999/XSL/Transform";
     public static final String XHTML_URI
diff --git a/src/org/apache/xalan/xsltc/compiler/DocumentCall.java b/src/org/apache/xalan/xsltc/compiler/DocumentCall.java
index 0817a06..8ff7f49 100644
--- a/src/org/apache/xalan/xsltc/compiler/DocumentCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/DocumentCall.java
@@ -120,7 +120,15 @@
 	// Parse the second argument - the document URI base
 	if (ac == 2) {
 	    _base = argument(1);
-	    if (!_base.typeCheck(stable).identicalTo(Type.NodeSet)) {
+	    final Type baseType = _base.typeCheck(stable);
+	    
+	    if (baseType.identicalTo(Type.Node)) {
+		_base = new CastExpr(_base, Type.NodeSet);
+	    }
+	    else if (baseType.identicalTo(Type.NodeSet)) {
+		// falls through
+	    }
+	    else {
 		ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
 		throw new TypeCheckError(msg);
 	    }
diff --git a/src/org/apache/xalan/xsltc/compiler/Expression.java b/src/org/apache/xalan/xsltc/compiler/Expression.java
index 3da80c6..727dc3b 100644
--- a/src/org/apache/xalan/xsltc/compiler/Expression.java
+++ b/src/org/apache/xalan/xsltc/compiler/Expression.java
@@ -103,7 +103,7 @@
     public abstract String toString();
 
     public boolean hasPositionCall() {
-	return true;
+	return false;		// default should be 'false' for StepPattern
     }
 
     public boolean hasLastCall() {
diff --git a/src/org/apache/xalan/xsltc/compiler/FormatNumberCall.java b/src/org/apache/xalan/xsltc/compiler/FormatNumberCall.java
index 9558f1a..124576d 100644
--- a/src/org/apache/xalan/xsltc/compiler/FormatNumberCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/FormatNumberCall.java
@@ -97,7 +97,7 @@
 	    _format = new CastExpr(_format, Type.String);
 	}
 	if (argumentCount() == 3) {
-	    final Type tname = _format.typeCheck(stable);
+	    final Type tname = _name.typeCheck(stable);
 	    if (tname instanceof StringType == false) {
 		_name = new CastExpr(_name, Type.String);
 	    }
diff --git a/src/org/apache/xalan/xsltc/compiler/FunctionAvailableCall.java b/src/org/apache/xalan/xsltc/compiler/FunctionAvailableCall.java
index 1e6aafc..af45184 100644
--- a/src/org/apache/xalan/xsltc/compiler/FunctionAvailableCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/FunctionAvailableCall.java
@@ -56,7 +56,7 @@
  * information on the Apache Software Foundation, please see
  * <http://www.apache.org/>.
  *
- * @author Jacek Ambroziak
+ * @author G. Todd Miller 
  * @author Santiago Pericas-Geertsen
  *
  */
@@ -64,38 +64,188 @@
 package org.apache.xalan.xsltc.compiler;
 
 import java.util.Vector;
-import java.util.HashSet;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Method;
 import org.apache.xalan.xsltc.compiler.util.Type;
 import org.apache.bcel.generic.*;
 import org.apache.xalan.xsltc.compiler.util.*;
+import org.apache.xalan.xsltc.runtime.TransletLoader;
 
 final class FunctionAvailableCall extends FunctionCall {
 
+    private boolean    _isFunctionAvailable = false; 
+    private Expression _arg; 
+    private String     _namespaceOfFunct =null; 	
+    private String     _nameOfFunct =null; 
+
+
+    /**
+     * Constructs a FunctionAvailableCall FunctionCall. Takes the
+     * function name qname, for example, 'function-available', and a list
+     * of arguments where the arguments must be instances of 
+     * LiteralExpression. The test for availability considers
+     * internal xsl functions such as 'floor' as well as external
+     * Java functions, such as 'java.lang.Math.sin'.  The case of
+     * external functions is handled here, the case of internal
+     * functions is handled in getResult. 
+     */
     public FunctionAvailableCall(QName fname, Vector arguments) {
 	super(fname, arguments);
+	_arg = (Expression)arguments.elementAt(0);
+	_type = null; 
+        if (_arg instanceof LiteralExpr) {
+	    LiteralExpr arg = (LiteralExpr)_arg;
+            _namespaceOfFunct = arg.getNamespace();
+            _nameOfFunct = arg.getValue();
+            if ((_namespaceOfFunct != null) && 
+                (!_namespaceOfFunct.equals(Constants.EMPTYSTRING)))
+	    {
+		// the function is external, such as a java function
+                _isFunctionAvailable = hasMethods();
+            }
+	    // the case of internal function is handled in getResult.
+        }
+	// case where _arg is not instanceof LiteralExpr can not be handled.
     }
 
     /**
-     * Force the argument to this function to be a literal string.
+     * Argument of function-available call must be literal, typecheck
+     * returns the type of function-available to be boolean.  
      */
     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
-	if (argument() instanceof LiteralExpr) {
-	    return _type = Type.Boolean;
+	// may be already set
+	if ( _type != null ) {
+	   return _type;
+	}
+	if (_arg instanceof LiteralExpr) {
+	    _type = Type.Boolean;
+	    return Type.Boolean;	
 	}
 	ErrorMsg err = new ErrorMsg(ErrorMsg.NEED_LITERAL_ERR,
-				    "function-available", this);
+			"function-available", this);
 	throw new TypeCheckError(err);
     }
 
     /**
-     * Returns the result that this function will return
+     * (For ext. java functions only)
+     * Parses the argument to function-available to extract the package 
+     * qualified class name, for example, given the argument 
+     * 'java:java.lang.Math.sin', getClassName would return
+     * 'java.lang.Math'. See also 'getMethodName'.
+     */
+    private String getClassName(String argValue){
+	int colonSep = argValue.indexOf(":");
+	if (colonSep != -1) {
+	    argValue = argValue.substring(colonSep+1);  
+	}		
+	int lastDot  = argValue.lastIndexOf(".");
+	if (lastDot != -1) {
+	    argValue = argValue.substring(0, lastDot);
+	}
+	return argValue;
+    }
+
+    /**
+     * (For ext. java functions only) 
+     * Parses the argument to function-available
+     * to extract the method name, for example, given the argument
+     * 'java.lang.Math.sin', getMethodName would return 'sin'. 
+     */
+    private String getMethodName(String argValue){
+	int lastDot  = argValue.lastIndexOf(".");
+	if (lastDot != -1) {
+	    argValue = argValue.substring(lastDot+1);
+	}
+	return argValue;
+    }
+
+    /**
+     * (For java external functions only) 
+     * Creates a full package qualified 
+     * function name taking into account the namespace and the
+     * function name derived from the argument passed to function-available.
+     * For example, given a name of 'java:java.lang.Math.sin' and a
+     * namespace of 'http://xml.apache.org/xalan/xsltc/java' this routine
+     * constructs a uri and then derives the class name 
+     * 'java.lang.Math.sin' from the uri. The uri in this example would
+     * be 'http://xml.apache.org/xalan/xsltc/java.java.lang.Math.sin'
+     */
+    private String getExternalFunctionName() {
+	int colonIndex = _nameOfFunct.indexOf(":");
+	String uri = _namespaceOfFunct + 
+                    "." + _nameOfFunct.substring(colonIndex+1);
+	try{
+	    return getClassNameFromUri(uri); 
+        } catch (TypeCheckError e) {
+	    return null; 
+        }
+    }
+
+    /**
+     * for external java functions only: reports on whether or not
+     * the specified method is found in the specifed class. 
+     */
+    private boolean hasMethods() {
+        
+	LiteralExpr arg = (LiteralExpr)_arg;
+	final String externalFunctName = getExternalFunctionName();
+	if (externalFunctName == null) {
+	    return false;
+	}
+	final String className = getClassName(externalFunctName);
+
+        if (_namespaceOfFunct.startsWith(JAVA_EXT_PREFIX) ||
+            _namespaceOfFunct.startsWith(JAVA_EXT_XALAN)) {
+            try {
+                TransletLoader loader = new TransletLoader();
+                final Class clazz = loader.loadClass(className);
+
+                if (clazz == null) {
+                    final ErrorMsg msg =
+                        new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, className);
+                    getParser().reportError(Constants.ERROR, msg);
+                }
+                else {
+                    final String methodName = getMethodName(externalFunctName);
+                    final Method[] methods = clazz.getDeclaredMethods();
+
+                    for (int i = 0; i < methods.length; i++) {
+                        final int mods = methods[i].getModifiers();
+
+                        if (Modifier.isPublic(mods)
+                            && Modifier.isStatic(mods)
+                            && methods[i].getName().equals(methodName))
+                        {
+			    return true;
+                        }
+                    }
+                }
+            }
+            catch (ClassNotFoundException e) {
+                final ErrorMsg msg =
+                    new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, className);
+                getParser().reportError(Constants.ERROR, msg);
+            }
+        }
+        return false;   
+    }
+
+    /**
+     * reports on whether the function specified in the argument to
+     * xslt function 'function-available' was found.
      */
     public boolean getResult() {
-	final Parser parser = getParser();
-	final LiteralExpr arg = (LiteralExpr)argument();
-	return(parser.functionSupported(arg.getValue()));
+        if ((_namespaceOfFunct == null) ||
+           (_namespaceOfFunct.equals(Constants.EMPTYSTRING)))
+        {
+            // no namespace, so the function is an internal xslt function.
+            final Parser parser = getParser();
+            _isFunctionAvailable = parser.functionSupported(_nameOfFunct);
+        }
+ 	return _isFunctionAvailable;
     }
 
+
     /**
      * Calls to 'function-available' are resolved at compile time since 
      * the namespaces declared in the stylsheet are not available at run
@@ -103,7 +253,7 @@
      */
     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
 	final ConstantPoolGen cpg = classGen.getConstantPool();
-	final boolean result = getResult();
-	methodGen.getInstructionList().append(new PUSH(cpg, result));
+	methodGen.getInstructionList().append(new PUSH(cpg, getResult()));
     }
+
 }
diff --git a/src/org/apache/xalan/xsltc/compiler/FunctionCall.java b/src/org/apache/xalan/xsltc/compiler/FunctionCall.java
index 4bf5be5..e3dfc05 100644
--- a/src/org/apache/xalan/xsltc/compiler/FunctionCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/FunctionCall.java
@@ -86,8 +86,8 @@
     private final static Vector EMPTY_ARG_LIST = new Vector(0);
 
     // Valid namespaces for Java function-call extension
-    private final static String JAVA_EXT_PREFIX = TRANSLET_URI + "/java";
-    private final static String JAVA_EXT_XALAN =
+    protected final static String JAVA_EXT_PREFIX = TRANSLET_URI + "/java";
+    protected final static String JAVA_EXT_XALAN =
 	"http://xml.apache.org/xslt/java";
 
     // External Java function's class/method/signature
@@ -170,6 +170,7 @@
     public FunctionCall(QName fname, Vector arguments) {
 	_fname = fname;
 	_arguments = arguments;
+	_type = null;
     }
 
     public FunctionCall(QName fname) {
@@ -192,11 +193,27 @@
 	}
     }
 
+    public String getClassNameFromUri(String uri) 
+	throws TypeCheckError
+    {
+	final int length = 
+	    uri.startsWith(JAVA_EXT_PREFIX) ? JAVA_EXT_PREFIX.length() + 1 :
+	    uri.startsWith(JAVA_EXT_XALAN) ? JAVA_EXT_XALAN.length() + 1 : 0;
+
+	if (length == 0) {
+	    throw new TypeCheckError(this);
+	}
+	return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING;
+    }
+
     /**
      * Type check a function call. Since different type conversions apply,
      * type checking is different for standard and external (Java) functions.
      */
-    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
+    public Type typeCheck(SymbolTable stable) 
+	throws TypeCheckError 
+    {
+	if (_type != null) return _type;
 
 	final String namespace = _fname.getNamespace();
 	final String local = _fname.getLocalPart();
@@ -207,33 +224,37 @@
 	}
 	// Handle extension functions (they all have a namespace)
 	else {
-	    final int len = JAVA_EXT_PREFIX.length();
-	    if (namespace.equals(JAVA_EXT_PREFIX) ||
-		namespace.equals(JAVA_EXT_XALAN)) {
-		final int pos = local.indexOf('.');
-		_className = local.substring(0, pos);
-		_fname = new QName(namespace, null, local.substring(pos+1));
-	    }
-	    else if (namespace.length() >= len &&
-		namespace.substring(0, len).equals(JAVA_EXT_PREFIX)) {
-		_className = namespace.substring(len + 1);
-	    }
-	    else {
-		/*
-		 * Warn user if external function could not be resolved.
-		 * Warning will _NOT_ be issued is the call is properly
-		 * wrapped in an <xsl:if> or <xsl:when> element. For details
-		 * see If.parserContents() and When.parserContents()
-		 */
-		final Parser parser = getParser();
-		if (parser != null) {
-		    reportWarning(this, parser, ErrorMsg.FUNCTION_RESOLVE_ERR,
-				  _fname.toString());
+	    try {
+		_className = getClassNameFromUri(namespace);
+
+		final int pos = local.lastIndexOf('.');
+		if (pos > 0) {
+		    _className = _className + local.substring(0, pos);
+		    _fname = new QName(namespace, null, local.substring(pos + 1));
 		}
-		unresolvedExternal = true;
-		return _type = Type.Void;
+		else {
+		    _fname = new QName(namespace, null, local);
+		}
+		if (_className.length() > 0) {
+		    return typeCheckExternal(stable);
+		}
+	    } catch (TypeCheckError e) {
+		// Falls through
 	    }
-	    return typeCheckExternal(stable);
+
+	    /*
+	     * Warn user if external function could not be resolved.
+	     * Warning will _NOT_ be issued is the call is properly
+	     * wrapped in an <xsl:if> or <xsl:when> element. For details
+	     * see If.parserContents() and When.parserContents()
+	     */
+	    final Parser parser = getParser();
+	    if (parser != null) {
+		reportWarning(this, parser, ErrorMsg.FUNCTION_RESOLVE_ERR,
+			      _fname.toString());
+	    }
+	    unresolvedExternal = true;
+	    return _type = Type.Void;
 	}
     }
 
diff --git a/src/org/apache/xalan/xsltc/compiler/Include.java b/src/org/apache/xalan/xsltc/compiler/Include.java
index 9f50727..4500b45 100644
--- a/src/org/apache/xalan/xsltc/compiler/Include.java
+++ b/src/org/apache/xalan/xsltc/compiler/Include.java
@@ -65,6 +65,7 @@
 package org.apache.xalan.xsltc.compiler;
 
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.net.URL;
 import java.net.MalformedURLException;
 import java.util.Enumeration;
@@ -106,11 +107,28 @@
 		input = loader.loadSource(docToLoad, currLoadedDoc, xsltc);
 	    }
 	    else {
-		File file = new File(currLoadedDoc);
-		if (file.exists()) currLoadedDoc = "file:"+currLoadedDoc;
-		final URL url = new URL(new URL(currLoadedDoc), docToLoad);
-		docToLoad = url.toString();
-		input = new InputSource(docToLoad);
+		// bug 7835, patch by Stefan Kost (s.kost@webmacher.de)
+		if ((currLoadedDoc != null) && (currLoadedDoc.length() > 0)) {
+		    File file = new File(currLoadedDoc);
+		    if (file.exists()) {
+		        currLoadedDoc = "file:" + file.getCanonicalPath();
+		    }
+		    final URL url = new URL(new URL(currLoadedDoc), docToLoad);
+		    docToLoad = url.toString();
+		    input = new InputSource(docToLoad);
+		}
+		else {
+		    File file = new File(System.getProperty("user.dir"),
+			docToLoad);
+		    if (file.exists()) {
+			docToLoad = "file:" + file.getCanonicalPath();
+		    }
+		    else {
+			throw new FileNotFoundException(
+			  "Could not load file " + docToLoad);
+		    }
+		    input = new InputSource(docToLoad);
+		}
 	    }
 
 	    final SyntaxTreeNode root = parser.parse(input);
diff --git a/src/org/apache/xalan/xsltc/compiler/LiteralElement.java b/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
index fffa79b..a041344 100644
--- a/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
+++ b/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
@@ -77,10 +77,11 @@
 import org.apache.xalan.xsltc.compiler.util.*;
 
 final class LiteralElement extends Instruction {
+
     private String _name;
-    private Hashtable _accessedPrefixes = null;
-    private LiteralElement _parent;
+    private LiteralElement _literalElemParent;
     private Vector _attributeElements = null;
+    private Hashtable _accessedPrefixes = null;
 
     private final static String XMLNS_STRING = "xmlns";
 
@@ -119,10 +120,10 @@
 				  SymbolTable stable, boolean declared) {
 
 	// Check if the parent has a declaration for this namespace
-	if (_parent != null) {
-	    final String parentUri = _parent.accessedNamespace(prefix);
+	if (_literalElemParent != null) {
+	    final String parentUri = _literalElemParent.accessedNamespace(prefix);
 	    if (parentUri == null) {
-		_parent.registerNamespace(prefix, uri, stable, declared);
+		_literalElemParent.registerNamespace(prefix, uri, stable, declared);
 		return;
 	    }
 	    if (parentUri.equals(uri)) return;
@@ -139,7 +140,7 @@
 		if (old != null) {
 		    if (old.equals(uri))
 			return;
-		    else
+		    else 
 			prefix = stable.generateNamespacePrefix();
 		}
 	    }
@@ -207,7 +208,6 @@
 	_attributeElements.insertElementAt(attribute,0);
     }
 
-
     /**
      * Type-check the contents of this element. The element itself does not
      * need any type checking as it leaves nothign on the JVM's stack.
@@ -255,23 +255,24 @@
      * Registers all namespaces that are used by the element/attributes
      */
     public void parseContents(Parser parser) {
-
 	final SymbolTable stable = parser.getSymbolTable();
 	stable.setCurrentNode(this);
 
 	// Find the closest literal element ancestor (if there is one)
-	SyntaxTreeNode _parent = getParent();
-	while ((_parent != null) && !(_parent instanceof LiteralElement))
-	    _parent = _parent.getParent();
-	if (!(_parent instanceof LiteralElement))
-	    _parent = null;
+	SyntaxTreeNode _literalElemParent = getParent();
+	while (_literalElemParent != null && !(_literalElemParent instanceof LiteralElement)) {
+	    _literalElemParent = _literalElemParent.getParent();
+	}
+
+	if (!(_literalElemParent instanceof LiteralElement)) {
+	    _literalElemParent = null;
+	}
 
 	_name = translateQName(_qname, stable);
 
 	// Process all attributes and register all namespaces they use
 	final int count = _attributes.getLength();
 	for (int i = 0; i < count; i++) {
-
 	    final QName qname = parser.getQName(_attributes.getQName(i));
 	    final String uri = qname.getNamespace();
 	    final String val = _attributes.getValue(i);
@@ -290,12 +291,15 @@
 	    else if (qname == parser.getExcludeResultPrefixes()) {
 		stable.excludeNamespaces(val);
 	    }
-	    // Ignore all other attributes in XSL namespace
-	    else if ((uri != null) && (uri.equals(XSLT_URI))) {
-		
-	    }
-	    // Handle literal attributes (attributes not in XSL namespace)
 	    else {
+		// Ignore special attributes
+		final String prefix = qname.getPrefix();
+		if (uri != null && uri.equals(XSLT_URI) ||
+		    prefix != null && prefix.equals(XMLNS_STRING)) {
+		    continue;	
+		}
+
+		// Handle all other literal attributes
 		final String name = translateQName(qname, stable);
 		LiteralAttribute attr = new LiteralAttribute(name, val, parser);
 		addAttribute(attr);
@@ -311,9 +315,8 @@
 	    final String prefix = (String)include.nextElement();
 	    if (!prefix.equals("xml")) {
 		final String uri = lookupNamespace(prefix);
-		if ((uri != null) && (!uri.equals(XSLT_URI))) {
-		    if (!stable.isExcludedNamespace(uri))
-			registerNamespace(prefix,uri,stable,true);
+		if (uri != null && !stable.isExcludedNamespace(uri)) {
+		    registerNamespace(prefix, uri, stable, true);
 		}
 	    }
 	}
@@ -322,7 +325,6 @@
 
 	// Process all attributes and register all namespaces they use
 	for (int i = 0; i < count; i++) {
-
 	    final QName qname = parser.getQName(_attributes.getQName(i));
 	    final String val = _attributes.getValue(i);
 
@@ -344,7 +346,9 @@
     /**
      * Compiles code that emits the literal element to the output handler,
      * first the start tag, then namespace declaration, then attributes,
-     * then the element contents, and then the element end tag.
+     * then the element contents, and then the element end tag. Since the
+     * value of an attribute may depend on a variable, variables must be
+     * compiled first.
      */
     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
 
@@ -354,23 +358,52 @@
 	// Compile code to emit element start tag
 	il.append(methodGen.loadHandler());
 	il.append(new PUSH(cpg, _name));
-	il.append(DUP2); // duplicate these 2 args for endElement
+	il.append(DUP2); 		// duplicate these 2 args for endElement
 	il.append(methodGen.startElement());
 
+	// The value of an attribute may depend on a (sibling) variable
+	for (int i = 0; i < elementCount(); i++) {
+	    final SyntaxTreeNode item = (SyntaxTreeNode) elementAt(i);
+	    if (item instanceof Variable) {
+		item.translate(classGen, methodGen);
+		removeElement(item);	// avoid translating it twice
+	    }
+	}
+
 	// Compile code to emit namespace attributes
 	if (_accessedPrefixes != null) {
+	    boolean declaresDefaultNS = false;
 	    Enumeration e = _accessedPrefixes.keys();
+
 	    while (e.hasMoreElements()) {
 		final String prefix = (String)e.nextElement();
 		final String uri = (String)_accessedPrefixes.get(prefix);
-		if ((uri != Constants.EMPTYSTRING) ||
-		    (prefix != Constants.EMPTYSTRING)) {
+
+		if (uri != Constants.EMPTYSTRING || 
+			prefix != Constants.EMPTYSTRING) 
+		{
+		    if (prefix == Constants.EMPTYSTRING) {
+			declaresDefaultNS = true;
+		    }
 		    il.append(methodGen.loadHandler());
 		    il.append(new PUSH(cpg,prefix));
 		    il.append(new PUSH(cpg,uri));
 		    il.append(methodGen.namespace());
 		}
 	    }
+
+	    /* 
+	     * If our XslElement parent redeclares the default NS, and this
+	     * element doesn't, it must be redeclared one more time.
+	     */
+	    if (!declaresDefaultNS && (_parent instanceof XslElement)
+		    && ((XslElement) _parent).declaresDefaultNS()) 
+	    {
+		il.append(methodGen.loadHandler());
+		il.append(new PUSH(cpg, Constants.EMPTYSTRING));
+		il.append(new PUSH(cpg, Constants.EMPTYSTRING));
+		il.append(methodGen.namespace());
+	    }
 	}
 
 	// Output all attributes
diff --git a/src/org/apache/xalan/xsltc/compiler/Number.java b/src/org/apache/xalan/xsltc/compiler/Number.java
index af99fe4..5435f27 100644
--- a/src/org/apache/xalan/xsltc/compiler/Number.java
+++ b/src/org/apache/xalan/xsltc/compiler/Number.java
@@ -129,23 +129,23 @@
 		}
 	    }
 	    else if (name.equals("format")) {
-		_format = new AttributeValueTemplate(value, parser);
+		_format = new AttributeValueTemplate(value, parser, this);
 		_formatNeeded = true;
 	    }
 	    else if (name.equals("lang")) {
-		_lang = new AttributeValueTemplate(value, parser);
+		_lang = new AttributeValueTemplate(value, parser, this);
 		_formatNeeded = true;
 	    }
 	    else if (name.equals("letter-value")) {
-		_letterValue = new AttributeValueTemplate(value, parser);
+		_letterValue = new AttributeValueTemplate(value, parser, this);
 		_formatNeeded = true;
 	    }
 	    else if (name.equals("grouping-separator")) {
-		_groupingSeparator = new AttributeValueTemplate(value, parser);
+		_groupingSeparator = new AttributeValueTemplate(value, parser, this);
 		_formatNeeded = true;
 	    }
 	    else if (name.equals("grouping-size")) {
-		_groupingSize = new AttributeValueTemplate(value, parser);
+		_groupingSize = new AttributeValueTemplate(value, parser, this);
 		_formatNeeded = true;
 	    }
 	}
diff --git a/src/org/apache/xalan/xsltc/compiler/ParentLocationPath.java b/src/org/apache/xalan/xsltc/compiler/ParentLocationPath.java
index adca196..8ffd159 100644
--- a/src/org/apache/xalan/xsltc/compiler/ParentLocationPath.java
+++ b/src/org/apache/xalan/xsltc/compiler/ParentLocationPath.java
@@ -216,10 +216,12 @@
 	Expression stp = _step;
 	if (stp instanceof ParentLocationPath)
 	    stp = ((ParentLocationPath)stp).getStep();
+
 	if ((_path instanceof Step) && (stp instanceof Step)) {
 	    final int path = ((Step)_path).getAxis();
 	    final int step = ((Step)stp).getAxis();
 	    if ((path == Axis.DESCENDANTORSELF && step == Axis.CHILD) ||
+		(path == Axis.DESCENDANTORSELF && step == Axis.ATTRIBUTE) ||
 		(path == Axis.PRECEDING        && step == Axis.PARENT)) {
 		final int incl = cpg.addMethodref(STEP_ITERATOR_CLASS,
 						  "includeSelf",
diff --git a/src/org/apache/xalan/xsltc/compiler/Parser.java b/src/org/apache/xalan/xsltc/compiler/Parser.java
index c4b2fd6..486a35d 100644
--- a/src/org/apache/xalan/xsltc/compiler/Parser.java
+++ b/src/org/apache/xalan/xsltc/compiler/Parser.java
@@ -265,6 +265,10 @@
     }
     
     public QName getQName(final String stringRep) {
+	return getQName(stringRep, true);    
+    }
+
+    public QName getQName(final String stringRep, boolean reportError) {
 	// parse and retrieve namespace
 	final int colon = stringRep.lastIndexOf(':');
 	if (colon != -1) {
@@ -275,7 +279,7 @@
 	    // Get the namespace uri from the symbol table
 	    if (prefix.equals("xmlns") == false) {
 		namespace = _symbolTable.lookupNamespace(prefix);
-		if (namespace == null) {
+		if (namespace == null && reportError) {
 		    final int line = _locator.getLineNumber();
 		    ErrorMsg err = new ErrorMsg(ErrorMsg.NAMESPACE_UNDEF_ERR,
 						line, prefix);
@@ -1072,7 +1076,9 @@
      *       This has to be passed on to the symbol table!
      */
     public void startPrefixMapping(String prefix, String uri) {
-	if (_prefixMapping == null) _prefixMapping = new Hashtable();
+	if (_prefixMapping == null) {
+	    _prefixMapping = new Hashtable();
+	}
 	_prefixMapping.put(prefix, uri);
     }
 
diff --git a/src/org/apache/xalan/xsltc/compiler/ProcessingInstruction.java b/src/org/apache/xalan/xsltc/compiler/ProcessingInstruction.java
index 91e40a4..fa2a188 100644
--- a/src/org/apache/xalan/xsltc/compiler/ProcessingInstruction.java
+++ b/src/org/apache/xalan/xsltc/compiler/ProcessingInstruction.java
@@ -109,13 +109,13 @@
 
 	// get String out of the handler
 	il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_VALUE_HANDLER,
-						     "getValue",
-						     "()"+STRING_SIG)));
+						     "getValueOfPI",
+						     "()" + STRING_SIG)));
 	// call "processingInstruction"
 	final int processingInstruction =
 	    cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
 				      "processingInstruction", 
-				      "("+STRING_SIG+STRING_SIG+")V");
+				      "(" + STRING_SIG + STRING_SIG + ")V");
 	il.append(new INVOKEINTERFACE(processingInstruction, 3));
 	// Restore old handler base from stack
 	il.append(methodGen.storeHandler());
diff --git a/src/org/apache/xalan/xsltc/compiler/Step.java b/src/org/apache/xalan/xsltc/compiler/Step.java
index 4d54224..9146616 100644
--- a/src/org/apache/xalan/xsltc/compiler/Step.java
+++ b/src/org/apache/xalan/xsltc/compiler/Step.java
@@ -508,22 +508,6 @@
 		    il.append(new CHECKCAST(cpg.addClass(className)));
 		}
 		il.append(new INVOKESPECIAL(idx));
-
-		// Determine if the node set should be generated using the
-		// natural order of the node set or document order.
-		// See CurrentNodeListIterator's constructor(s) for details.
-		SyntaxTreeNode parent = getParent();
-		while (!(parent instanceof Template)) {
-		    if (parent == null) break;
-		    if (parent instanceof ApplyTemplates) {
-			idx = cpg.addMethodref(CURRENT_NODE_LIST_ITERATOR,
-					       "forceNaturalOrder",
-					       "()"+NODE_ITERATOR_SIG);
-			il.append(new INVOKEVIRTUAL(idx));
-			break;
-		    }
-		    parent = parent.getParent();
-		}
 	    }
 	}
     }
diff --git a/src/org/apache/xalan/xsltc/compiler/StepPattern.java b/src/org/apache/xalan/xsltc/compiler/StepPattern.java
index 78243a3..c14b743 100644
--- a/src/org/apache/xalan/xsltc/compiler/StepPattern.java
+++ b/src/org/apache/xalan/xsltc/compiler/StepPattern.java
@@ -162,10 +162,12 @@
     private int analyzeCases() {
 	boolean noContext = true;
 	final int n = _predicates.size();
+
 	for (int i = 0; i < n && noContext; i++) {
 	    final Predicate pred = (Predicate)_predicates.elementAt(i);
-	    final Expression exp = pred.getExpr();
-	    if (exp.hasPositionCall()) noContext = false;
+	    if (pred.getExpr().hasPositionCall()) {
+		noContext = false;
+	    }
 	}
 
 	if (noContext) {
diff --git a/src/org/apache/xalan/xsltc/compiler/Stylesheet.java b/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
index 15b0522..fa2d816 100644
--- a/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
+++ b/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
@@ -284,7 +284,6 @@
 	super.addPrefixMapping(prefix, uri);
     }
 
-
     /**
      * Store extension URIs
      */
@@ -308,8 +307,10 @@
     public void excludeExtensionPrefixes(Parser parser) {
 	final SymbolTable stable = parser.getSymbolTable();
     	final String excludePrefixes = getAttribute("exclude-result-prefixes");
-	final String extensionPrefixes = 
-	    getAttribute("extension-element-prefixes");
+	final String extensionPrefixes = getAttribute("extension-element-prefixes");
+	
+	// Exclude XSLT uri 
+	stable.excludeURI(Constants.XSLT_URI);
 	stable.excludeNamespaces(excludePrefixes);
 	stable.excludeNamespaces(extensionPrefixes);
 	extensionURI(extensionPrefixes, stable);
@@ -878,6 +879,18 @@
 					   "("+OUTPUT_HANDLER_SIG+")V");
 	il.append(new INVOKEVIRTUAL(index));
 
+	// Compile buildKeys -- TODO: omit if not needed
+	final String keySig = compileBuildKeys(classGen);
+	final int    keyIdx = cpg.addMethodref(getClassName(),
+					       "buildKeys", keySig);
+	il.append(classGen.loadTranslet());     // The 'this' pointer
+	il.append(classGen.loadTranslet());
+	il.append(new GETFIELD(domField));      // The DOM reference
+	il.append(transf.loadIterator());       // Not really used, but...
+	il.append(transf.loadHandler());        // The output handler
+	il.append(new PUSH(cpg, DOM.ROOTNODE)); // Start with the root node
+	il.append(new INVOKEVIRTUAL(keyIdx));
+
 	// Look for top-level elements that need handling
 	final Enumeration toplevel = elements();
 	if ((_globals.size() > 0) || (toplevel.hasMoreElements())) {
@@ -896,17 +909,6 @@
 	    il.append(new INVOKEVIRTUAL(topLevelIdx));
 	}
 	
-	final String keySig = compileBuildKeys(classGen);
-	final int    keyIdx = cpg.addMethodref(getClassName(),
-					       "buildKeys", keySig);
-	il.append(classGen.loadTranslet());     // The 'this' pointer
-	il.append(classGen.loadTranslet());
-	il.append(new GETFIELD(domField));      // The DOM reference
-	il.append(transf.loadIterator());       // Not really used, but...
-	il.append(transf.loadHandler());        // The output handler
-	il.append(new PUSH(cpg, DOM.ROOTNODE)); // Start with the root node
-	il.append(new INVOKEVIRTUAL(keyIdx));
-
 	// start document
 	il.append(transf.loadHandler());
 	il.append(transf.startDocument());
diff --git a/src/org/apache/xalan/xsltc/compiler/SymbolTable.java b/src/org/apache/xalan/xsltc/compiler/SymbolTable.java
index cf5c576..4b190d1 100644
--- a/src/org/apache/xalan/xsltc/compiler/SymbolTable.java
+++ b/src/org/apache/xalan/xsltc/compiler/SymbolTable.java
@@ -262,11 +262,10 @@
      * Check if a namespace should not be declared in the output (unless used)
      */
     public boolean isExcludedNamespace(String uri) {
-	if (uri == null) return false;
-	if (_excludedURI == null) return false;
-	final Integer refcnt = (Integer)_excludedURI.get(uri);
-	if (refcnt == null) return false;
-	if (refcnt.intValue() > 0) return true;
+	if (uri != null && _excludedURI != null) {
+	    final Integer refcnt = (Integer)_excludedURI.get(uri);
+	    return (refcnt != null && refcnt.intValue() > 0);
+	}
 	return false;
     }
 
diff --git a/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java b/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java
index 26f6c13..cd6f4d1 100644
--- a/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java
+++ b/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java
@@ -193,18 +193,16 @@
      * @return The value of the attribute of name 'qname'.
      */
     protected String getAttribute(String qname) {
-	if (_attributes == null)
-	    return(Constants.EMPTYSTRING);
+	if (_attributes == null) {
+	    return EMPTYSTRING;
+	}
 	final String value = _attributes.getValue(qname);
-	if (value == null)
-	    return(Constants.EMPTYSTRING);
-	else
-	    return(value);
+	return (value == null || value.equals(EMPTYSTRING)) ? 
+	    EMPTYSTRING : value;
     }
 
     protected boolean hasAttribute(String qname) {
-	if (_attributes == null) return false;
-	return (_attributes.getValue(qname) != null);
+	return (_attributes != null && _attributes.getValue(qname) != null);
     }
 
     /**
diff --git a/src/org/apache/xalan/xsltc/compiler/XslAttribute.java b/src/org/apache/xalan/xsltc/compiler/XslAttribute.java
index f6e8b6e..96f64f9 100644
--- a/src/org/apache/xalan/xsltc/compiler/XslAttribute.java
+++ b/src/org/apache/xalan/xsltc/compiler/XslAttribute.java
@@ -73,10 +73,9 @@
 
 final class XslAttribute extends Instruction {
 
-    // Attribute contents
-    private AttributeValue _name; // name treated as AVT (7.1.3)
-    private AttributeValueTemplate _namespace = null;
     private String _prefix;
+    private AttributeValue _name; 	// name treated as AVT (7.1.3)
+    private AttributeValueTemplate _namespace = null;
     private boolean _ignore = false;
 
     /**
@@ -99,15 +98,15 @@
      * Parses the attribute's contents. Special care taken for namespaces.
      */
     public void parseContents(Parser parser) {
-
-	final SymbolTable stable = parser.getSymbolTable();
-	String namespace = getAttribute("namespace");
-	String name = getAttribute("name");
-	QName qname = parser.getQName(name);
-	final String prefix = qname.getPrefix();
 	boolean generated = false;
+	final SymbolTable stable = parser.getSymbolTable();
 
-	if ((prefix != null) && (prefix.equals("xmlns"))) {
+	String name = getAttribute("name");
+	String namespace = getAttribute("namespace");
+	QName qname = parser.getQName(name, false);
+	final String prefix = qname.getPrefix();
+
+	if ((prefix != null) && (prefix.equals(XMLNS_PREFIX))) {
 	    reportError(this, parser, ErrorMsg.ILLEGAL_ATTR_NAME_ERR, name);
 	    return;
 	}
@@ -118,11 +117,13 @@
 	for (int i = 0; i < parent.elementCount(); i++) {
 	    SyntaxTreeNode item = (SyntaxTreeNode)siblings.elementAt(i);
 	    if (item == this) break;
+
 	    // These three objects result in one or more attribute output
 	    if (item instanceof XslAttribute) continue;
 	    if (item instanceof UseAttributeSets) continue;
 	    if (item instanceof LiteralAttribute) continue;
 	    if (item instanceof Text) continue;
+
 	    // These objects _can_ result in one or more attribute
 	    // The output handler will generate an error if not (at runtime)
 	    if (item instanceof If) continue;
@@ -134,24 +135,23 @@
 	}
 
 	// Get namespace from namespace attribute?
-	if ((namespace != null) && (namespace != Constants.EMPTYSTRING)) {
-	    // Prefix could be in symbol table
+	if (namespace != null && namespace != Constants.EMPTYSTRING) {
 	    _prefix = lookupPrefix(namespace);
-	    _namespace = new AttributeValueTemplate(namespace, parser);
+	    _namespace = new AttributeValueTemplate(namespace, parser, this);
 	}
 	// Get namespace from prefix in name attribute?
-	else if ((prefix != null) && (prefix != Constants.EMPTYSTRING)) {
+	else if (prefix != null && prefix != Constants.EMPTYSTRING) {
 	    _prefix = prefix;
 	    namespace = lookupNamespace(prefix);
-	    if (namespace != null)
-		_namespace = new AttributeValueTemplate(namespace, parser);
+	    if (namespace != null) {
+		_namespace = new AttributeValueTemplate(namespace, parser, this);
+	    }
 	}
 	
 	// Common handling for namespaces:
 	if (_namespace != null) {
-
 	    // Generate prefix if we have none
-	    if (_prefix == null) {
+	    if (_prefix == null || _prefix == Constants.EMPTYSTRING) {
 		if (prefix != null) {
 		    _prefix = prefix;
 		}
@@ -160,25 +160,25 @@
 		    generated = true;
 		}
 	    }
-
-	    if (_prefix == Constants.EMPTYSTRING) {
-		name = qname.getLocalPart();
+	    else if (prefix != null && !prefix.equals(_prefix)) {
+		_prefix = prefix;
 	    }
-	    else {
-		name = _prefix+":"+qname.getLocalPart();
-		// PROBLEM:
-		// The namespace URI must be passed to the parent element,
-		// but we don't yet know what the actual URI is (as we only
-		// know it as an attribute value template). New design needed.
-		if ((parent instanceof LiteralElement) && (!generated)) {
-		    ((LiteralElement)parent).registerNamespace(_prefix,
-							       namespace,
-							       stable,false);
-		}
+
+	    name = _prefix + ":" + qname.getLocalPart();
+
+	    /*
+	     * TODO: The namespace URI must be passed to the parent 
+	     * element but we don't yet know what the actual URI is 
+	     * (as we only know it as an attribute value template). 
+	     */
+	    if ((parent instanceof LiteralElement) && (!generated)) {
+		((LiteralElement)parent).registerNamespace(_prefix,
+							   namespace,
+							   stable, false);
 	    }
 	}
 
-	if (name.equals("xmlns")) {
+	if (name.equals(XMLNS_PREFIX)) {
 	    reportError(this, parser, ErrorMsg.ILLEGAL_ATTR_NAME_ERR, name);
 	    return;
 	}
@@ -191,15 +191,14 @@
 	parseChildren(parser);
     }
 	
-    /**
-     *
-     */
     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
-	if (_ignore) return(Type.Void);
-	_name.typeCheck(stable);
-	if (_namespace != null)
-	    _namespace.typeCheck(stable);
-	typeCheckContents(stable);
+	if (!_ignore) {
+	    _name.typeCheck(stable);
+	    if (_namespace != null) {
+		_namespace.typeCheck(stable);
+	    }
+	    typeCheckContents(stable);
+	}
 	return Type.Void;
     }
 
diff --git a/src/org/apache/xalan/xsltc/compiler/XslElement.java b/src/org/apache/xalan/xsltc/compiler/XslElement.java
index 84d7d38..6f3df54 100644
--- a/src/org/apache/xalan/xsltc/compiler/XslElement.java
+++ b/src/org/apache/xalan/xsltc/compiler/XslElement.java
@@ -74,10 +74,11 @@
 
 final class XslElement extends Instruction {
 
-    private AttributeValue _name; // name treated as AVT (7.1.3)
-    private AttributeValueTemplate _namespace = null;
     private String  _prefix;
     private boolean _ignore = false;
+    private boolean _isLiteralName = true;
+    private AttributeValueTemplate _name; 
+    private AttributeValueTemplate _namespace;
 
     /**
      * Displays the contents of the element
@@ -89,87 +90,124 @@
     }
 
     /**
-     * Parses the element's contents. Special care taken for namespaces.
-     * TODO: The namespace attribute that specifies the namespace to use
-     * for the element is an attribute value template and not a string
-     * constant. This means that we do not know what namespace is used
-     * before runtime. This causes a problem with the way output namespaces
-     * are handled at compile-time. We use a shortcut in this method to get
-     * around the problem by treating the namaspace attribute as a constant.
-     *          (Yes, I know this is a hack, bad, bad, bad.)
+     * This method is now deprecated. The new implemation of this class
+     * never declares the default NS.
      */
-    public void parseContents(Parser parser) {
+    public boolean declaresDefaultNS() {
+	return false;
+    }
 
+    /**
+     * Checks if <param>str</param> is a literal (i.e. not an AVT) or not.
+     */
+    private boolean isLiteral(String str) {
+	final int length = str.length();
+	for (int i = 0; i < length; i++) {
+	    if (str.charAt(i) == '{' && str.charAt(i + 1) != '{') {
+		return false;
+	    }
+	}
+	return true;
+    }
+
+    /**
+     * Simple check to determine if qname is legal. If it returns false
+     * then <param>str</param> is illegal; if it returns true then 
+     * <param>str</param> may or may not be legal.
+     */
+    private boolean isLegalName(String str) {
+	if (str.indexOf(' ') > -1) {
+	    return false;
+	}
+	final int colon = str.indexOf(':');
+	if (colon == 0 || colon == str.length() - 1) {
+	    return false;
+	}
+	final char first = str.charAt(0);
+	if (!Character.isLetter(first) && first != '_') {
+	    return false;
+	}
+	return true;
+    }
+
+    public void parseContents(Parser parser) {
 	final SymbolTable stable = parser.getSymbolTable();
 
-	// Get the "name" attribute of the <xsl:element> element
+	// Handle the 'name' attribute
 	String name = getAttribute("name");
-	if ((name == null) || (name.equals(EMPTYSTRING))) {
+	if (name == EMPTYSTRING) {
 	    ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ELEM_NAME_ERR,
 					name, this);
 	    parser.reportError(WARNING, msg);
-	    _ignore = true; // Ignore the element if the QName is invalid
+	    parseChildren(parser);
+	    _ignore = true; 	// Ignore the element if the QName is invalid
 	    return;
 	}
 
-	// Try to construct a QName and then get the prefix and local part
-	QName  qname  = parser.getQNameSafe(name);
-	String prefix = qname.getPrefix();
-	String local  = qname.getLocalPart();
-
-	// First try to get the namespace URI from the "namespace" attribute
+	// Get namespace attribute
 	String namespace = getAttribute("namespace");
-	// Then try to get it from the "name" attribute QName prefix
-	if (!hasAttribute("namespace")) {
-	    // We are supposed to use the default namespace URI if the QName
-	    // from the "name" attribute is not prefixed, so check that first
-	    if (prefix == null) prefix = EMPTYSTRING;
-	    // Then look up the URI that is in scope for the prefix
-	    namespace = lookupNamespace(prefix); 
 
-	    // Signal error if the prefix does not map to any namespace URI 
-	    if (namespace == null) {
-		ErrorMsg err = new ErrorMsg(ErrorMsg.NAMESPACE_UNDEF_ERR,
-					    prefix, this);
-		parser.reportError(WARNING, err);
+	// Optimize compilation when name is known at compile time
+	_isLiteralName = isLiteral(name);
+	if (_isLiteralName) {
+	    if (!isLegalName(name)) {
+		ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ELEM_NAME_ERR,
+					    name, this);
+		parser.reportError(WARNING, msg);
 		parseChildren(parser);
-		_ignore = true; // Ignore the element if prefix is undeclared
+		_ignore = true; 	// Ignore the element if the QName is invalid
 		return;
 	    }
-	    _namespace = new AttributeValueTemplate(namespace, parser);
-	    _prefix = prefix;
+
+	    final QName qname = parser.getQNameSafe(name);
+	    String prefix = qname.getPrefix();
+	    String local = qname.getLocalPart();
+	    
+	    if (prefix == null) {
+		prefix = EMPTYSTRING;
+	    }
+
+	    if (!hasAttribute("namespace")) {
+		namespace = lookupNamespace(prefix); 
+		if (namespace == null) {
+		    ErrorMsg err = new ErrorMsg(ErrorMsg.NAMESPACE_UNDEF_ERR,
+						prefix, this);
+		    parser.reportError(WARNING, err);
+		    parseChildren(parser);
+		    _ignore = true; 	// Ignore the element if prefix is undeclared
+		    return;
+		}
+		_prefix = prefix;
+		_namespace = (namespace == EMPTYSTRING) ? null :
+			     new AttributeValueTemplate(namespace, parser, this);
+	    }
+	    else {
+		if (prefix == EMPTYSTRING) {
+		    if (isLiteral(namespace)) {
+			prefix = lookupPrefix(namespace);
+			if (prefix == null) {
+			    prefix = stable.generateNamespacePrefix();
+			}
+		    }
+
+		    // Prepend prefix to local name
+		    final StringBuffer newName = new StringBuffer(prefix);
+		    if (prefix != EMPTYSTRING) {
+			newName.append(':');
+		    }
+		    name = newName.append(local).toString();
+		}
+		_prefix = prefix;
+		_namespace = new AttributeValueTemplate(namespace, parser, this);
+	    }
 	}
-	// Check if this element belongs in a specific namespace
 	else {
-	    // Get the namespace requested by the xsl:element
-	    _namespace = new AttributeValueTemplate(namespace, parser);
-	    // Get the current prefix for that namespace (if any)
-	    _prefix = lookupPrefix(namespace);
-	    // Is it the default namespace?
-	    if ((_prefix = prefix) == null) _prefix = EMPTYSTRING;
-
-	    // Construct final element QName
-	    if (_prefix == EMPTYSTRING)
-		name = qname.getLocalPart();
-	    else
-		name = _prefix+":"+qname.getLocalPart();
+	    _namespace = (namespace == EMPTYSTRING) ? null :
+			 new AttributeValueTemplate(namespace, parser, this);
 	}
 
-	_name = AttributeValue.create(this, name, parser);
+	_name = new AttributeValueTemplate(name, parser, this);
 
-	// Next check that the local part of the QName is legal (no whitespace)
-	if (_name instanceof SimpleAttributeValue) {
-	    if (local.equals(EMPTYSTRING) || (local.indexOf(' ') > -1)) {
-		ErrorMsg err = new ErrorMsg(ErrorMsg.ILLEGAL_ELEM_NAME_ERR,
-					    local, this);
-		parser.reportError(WARNING, err);
-		parseChildren(parser);
-		_ignore = true; // Ignore the element if local part is invalid
-		return;
-	    }
-	}
-
-	// Handle the 'use-attribute-sets' attribute
 	final String useSets = getAttribute("use-attribute-sets");
 	if (useSets.length() > 0) {
 	    setFirstElement(new UseAttributeSets(useSets, parser));
@@ -184,34 +222,30 @@
     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
 	if (!_ignore) {
 	    _name.typeCheck(stable);
-	    if (_namespace != null)
+	    if (_namespace != null) {
 		_namespace.typeCheck(stable);
+	    }
 	}
 	typeCheckContents(stable);
 	return Type.Void;
     }
 
     /**
-     * Compiles code that emits the element with the necessary namespace
-     * 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.
+     * This method is called when the name of the element is known at compile time.
+     * In this case, there is no need to inspect the element name at runtime to
+     * determine if a prefix exists, needs to be generated, etc.
      */
-    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
+    public void translateLiteral(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());
 	    _name.translate(classGen, methodGen);
-	    il.append(DUP2);	// duplicate these 2 args for endElement
+	    il.append(DUP2);
 	    il.append(methodGen.startElement());
 
-	    // Compile code that emits any needed namespace declaration
 	    if (_namespace != null) {
-		// public void attribute(final String name, final String value)
 		il.append(methodGen.loadHandler());
 		il.append(new PUSH(cpg, _prefix));
 		_namespace.translate(classGen,methodGen);
@@ -219,12 +253,94 @@
 	    }
 	}
 
-	// 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());
+	}
+    }
+
+    /**
+     * At runtime the compilation of xsl:element results in code that: (i)
+     * evaluates the avt for the name, (ii) checks for a prefix in the name
+     * (iii) generates a new prefix and create a new qname when necessary
+     * (iv) calls startElement() on the handler (v) looks up a uri in the XML
+     * when the prefix is not known at compile time (vi) calls namespace() 
+     * on the handler (vii) evaluates the contents (viii) calls endElement().
+     */
+    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
+	LocalVariableGen local = null;
+	final ConstantPoolGen cpg = classGen.getConstantPool();
+	final InstructionList il = methodGen.getInstructionList();
+
+	// Optimize translation if element name is a literal
+	if (_isLiteralName) {
+	    translateLiteral(classGen, methodGen);
+	    return;
+	}
+
+	if (!_ignore) {
+	    il.append(methodGen.loadHandler());
+	    _name.translate(classGen, methodGen);
+
+	    // Call BasisLibrary.getPrefix() and store result in local variable
+	    il.append(DUP);
+	    final int getPrefix = cpg.addMethodref(BASIS_LIBRARY_CLASS, "getPrefix",
+					      "(" + STRING_SIG + ")" + STRING_SIG);
+	    il.append(new INVOKESTATIC(getPrefix));
+	    il.append(DUP);
+	    local = methodGen.addLocalVariable("prefix", 
+					       org.apache.bcel.generic.Type.STRING,
+					       il.getEnd(), null);
+	    il.append(new ASTORE(local.getIndex()));
+
+	    // If prefix is null then generate a prefix at runtime
+	    final BranchHandle ifNotNull = il.append(new IFNONNULL(null));
+	    if (_namespace != null) {
+		final int generatePrefix = cpg.addMethodref(BASIS_LIBRARY_CLASS, 
+							    "generatePrefix", 
+							    "()" + STRING_SIG);
+		il.append(new INVOKESTATIC(generatePrefix));
+		il.append(DUP);
+		il.append(new ASTORE(local.getIndex()));
+
+		// Prepend newly generated prefix to the name
+		final int makeQName = cpg.addMethodref(BASIS_LIBRARY_CLASS, "makeQName", 
+				       "(" + STRING_SIG + STRING_SIG + ")" + STRING_SIG);
+		il.append(new INVOKESTATIC(makeQName));
+	    }
+	    ifNotNull.setTarget(il.append(DUP2));
+	    il.append(methodGen.startElement());
+
+	    if (_namespace != null) {
+		il.append(methodGen.loadHandler());
+		il.append(new ALOAD(local.getIndex()));
+		_namespace.translate(classGen, methodGen);
+		il.append(methodGen.namespace());
+	    }
+	    else {
+		// If prefix not known at compile time, call DOM.lookupNamespace()
+		il.append(new ALOAD(local.getIndex()));
+		final BranchHandle ifNull = il.append(new IFNULL(null));
+		il.append(methodGen.loadHandler());
+		il.append(new ALOAD(local.getIndex()));
+
+		il.append(methodGen.loadDOM());
+		il.append(methodGen.loadCurrentNode());
+		il.append(new ALOAD(local.getIndex()));
+
+		final int lookupNamespace = cpg.addInterfaceMethodref(DOM_INTF, 
+					"lookupNamespace", 
+				        "(I" + STRING_SIG + ")" + STRING_SIG);
+		il.append(new INVOKEINTERFACE(lookupNamespace, 3));
+		il.append(methodGen.namespace());
+		ifNull.setTarget(il.append(NOP));
+	    }
+	}
+
+	translateContents(classGen, methodGen);
+
+	if (!_ignore) {
 	    il.append(methodGen.endElement());
 	}
     }
@@ -239,7 +355,7 @@
 	for (int i = 0; i < n; i++) {
 	    final SyntaxTreeNode item =
 		(SyntaxTreeNode)getContents().elementAt(i);
-	    if ((_ignore) && (item instanceof XslAttribute)) continue;
+	    if (_ignore && item instanceof XslAttribute) continue;
 	    item.translate(classGen, methodGen);
 	}
     }
diff --git a/src/org/apache/xalan/xsltc/compiler/util/Util.java b/src/org/apache/xalan/xsltc/compiler/util/Util.java
index 2082fe1..0fc872b 100644
--- a/src/org/apache/xalan/xsltc/compiler/util/Util.java
+++ b/src/org/apache/xalan/xsltc/compiler/util/Util.java
@@ -108,17 +108,20 @@
      * Replace all illegal Java chars by '_'.
      */
     public static String toJavaName(String name) {
-	final StringBuffer result = new StringBuffer();
+	if (name.length() > 0) {
+	    final StringBuffer result = new StringBuffer();
 
-	char ch = name.charAt(0);
-	result.append(Character.isJavaIdentifierStart(ch) ? ch : '_');
+	    char ch = name.charAt(0);
+	    result.append(Character.isJavaIdentifierStart(ch) ? ch : '_');
 
-	final int n = name.length();
-	for (int i = 1; i < n; i++) {
-	    ch = name.charAt(i);
-	    result.append(Character.isJavaIdentifierPart(ch)  ? ch : '_');
+	    final int n = name.length();
+	    for (int i = 1; i < n; i++) {
+		ch = name.charAt(i);
+		result.append(Character.isJavaIdentifierPart(ch)  ? ch : '_');
+	    }
+	    return result.toString();
 	}
-	return result.toString();
+	return name;
     }
 
     public static Type getJCRefType(String signature) {
@@ -130,15 +133,11 @@
     }
 
     public static void println(String s) {
-	if (false) {
-	    System.out.println(s);
-	}
+	System.out.println(s);
     }
 
     public static void println(char ch) {
-	if (false) {
-	    System.out.println(ch);
-	}
+	System.out.println(ch);
     }
 
     public static void TRACE1() {
diff --git a/src/org/apache/xalan/xsltc/dom/CurrentNodeListIterator.java b/src/org/apache/xalan/xsltc/dom/CurrentNodeListIterator.java
index dfb9f3d..79df194 100644
--- a/src/org/apache/xalan/xsltc/dom/CurrentNodeListIterator.java
+++ b/src/org/apache/xalan/xsltc/dom/CurrentNodeListIterator.java
@@ -99,11 +99,6 @@
 	_currentNode = currentNode;
     }
 
-    public NodeIterator forceNaturalOrder() {
-	_docOrder = true;
-	return this;
-    }
-
     public void setRestartable(boolean isRestartable) {
 	_isRestartable = isRestartable;
 	_source.setRestartable(isRestartable);
@@ -139,9 +134,8 @@
 	final int currentNode = _currentNode;
 
 	for (int index = _current; index < last; ) {
-	    final int node = _nodes.at(index++); // note increment
-	    final int position = docOrder ? index : last - index + 1;
-	    if (_filter.test(node, position, last, currentNode, _translet, this)) {
+	    final int node = _nodes.at(index++); 	// note increment
+	    if (_filter.test(node, index, last, currentNode, _translet, this)) {
 		_current = index;
 		return returnNode(node);
 	    }
@@ -156,9 +150,8 @@
         final int currNode = _currentNode;
 
 	for (int index = _current; index < last; ) {
-            int nodeIndex = _nodes.at(index++); // note increment
-            final int pos = docOrder ? index : last - index + 1;
-            if (_filter.test(nodeIndex, pos, last, currNode, _translet, this)) {
+            int nodeIndex = _nodes.at(index++); 	// note increment
+            if (_filter.test(nodeIndex, index, last, currNode, _translet, this)) {
                 lastPosition++;
             }
         }
@@ -185,7 +178,7 @@
     }
 	
     public int getLast() {
-	return ( _last == -1 ) ? computePositionOfLast() : _last;
+	return (_last == -1) ? computePositionOfLast() : _last;
     }
 
     public void setMark() {
diff --git a/src/org/apache/xalan/xsltc/dom/DOMAdapter.java b/src/org/apache/xalan/xsltc/dom/DOMAdapter.java
index 4d75669..1bc9c7c 100644
--- a/src/org/apache/xalan/xsltc/dom/DOMAdapter.java
+++ b/src/org/apache/xalan/xsltc/dom/DOMAdapter.java
@@ -278,4 +278,9 @@
 	return(_domImpl.isAttribute(node));
     }
 
+    public String lookupNamespace(int node, String prefix) 
+	throws TransletException 
+    {
+	return _domImpl.lookupNamespace(node, prefix);
+    }
 }
diff --git a/src/org/apache/xalan/xsltc/dom/DOMBuilder.java b/src/org/apache/xalan/xsltc/dom/DOMBuilder.java
index cc67a53..dabd49e 100644
--- a/src/org/apache/xalan/xsltc/dom/DOMBuilder.java
+++ b/src/org/apache/xalan/xsltc/dom/DOMBuilder.java
@@ -64,4 +64,4 @@
 import org.xml.sax.ContentHandler;
 import org.xml.sax.ext.LexicalHandler;
 
-public interface DOMBuilder extends ContentHandler, LexicalHandler { }
+public interface DOMBuilder extends  ExtendedSAX { }
diff --git a/src/org/apache/xalan/xsltc/dom/DOMImpl.java b/src/org/apache/xalan/xsltc/dom/DOMImpl.java
index df1a7ea..3d6164b 100644
--- a/src/org/apache/xalan/xsltc/dom/DOMImpl.java
+++ b/src/org/apache/xalan/xsltc/dom/DOMImpl.java
@@ -81,6 +81,7 @@
 
 import org.xml.sax.*;
 import org.xml.sax.ext.*;
+import org.xml.sax.helpers.AttributesImpl;
 import org.apache.xalan.xsltc.*;
 import org.apache.xalan.xsltc.util.IntegerArray;
 import org.apache.xalan.xsltc.runtime.BasisLibrary;
@@ -136,6 +137,9 @@
     // Tracks which textnodes are whitespaces and which are not
     private BitArray  _whitespace; // takes xml:space into acc.
 
+    // Tracks which textnodes are not escaped
+    private BitArray  _dontEscape = null; 
+
     // The URI to this document
     private String    _documentURI;
 
@@ -171,6 +175,37 @@
     }
 
     /**
+     * Lookup a namespace URI from a prefix starting at node. This method 
+     * is used in the execution of xsl:element when the prefix is not known 
+     * at compile time.
+     */
+    public String lookupNamespace(int node, String prefix) 
+	throws TransletException 
+    {
+	int anode, nsnode;
+	final AncestorIterator ancestors = new AncestorIterator();
+	
+	if (isElement(node)) {
+	    ancestors.includeSelf();
+	}
+
+	ancestors.setStartNode(node);
+	while ((anode = ancestors.next()) != NULL) {
+	    final NodeIterator namespaces = 
+		new NamespaceIterator().setStartNode(anode);
+
+	    while ((nsnode = namespaces.next()) != NULL) {
+		if (_prefixArray[_prefix[nsnode]].equals(prefix)) {
+		    return getNodeValue(nsnode);
+		}
+	    }
+	}
+
+	// TODO: Internationalization?
+	throw new TransletException("Namespace prefix '" + prefix + "' is undeclared.");
+    }
+
+    /**
      * Returns 'true' if a specific node is an element (of any type)
      */
     public boolean isElement(final int node) {
@@ -1053,6 +1088,7 @@
 		while ((_ns == DOM.NULL) && (_node != DOM.NULL)) {
 		    _node = _parent[_node];
 		    _ns = _lengthOrAttr[_node];
+
 		    while ((_ns != DOM.NULL) && (_type[_ns] != NAMESPACE)) {
 			_ns = _nextSibling[_ns];
 		    }
@@ -1980,6 +2016,7 @@
 	case ROOT:
 	    return getNodeValue(_offsetOrChild[node]);
 	case TEXT:
+	    // GTM - add escapign code here too.
 	case COMMENT:
 	    return makeStringValue(node);
 	case PROCESSING_INSTRUCTION:
@@ -2162,6 +2199,13 @@
 
 	out.writeObject(_whitespace);
 
+	if (_dontEscape != null) {
+	    out.writeObject(_dontEscape);
+	}
+	else {
+	    out.writeObject(new BitArray(0));
+	}
+
 	out.flush();
     }
 
@@ -2190,6 +2234,11 @@
 
 	_whitespace    = (BitArray)in.readObject();
 
+	_dontEscape    = (BitArray)in.readObject();
+	if (_dontEscape.size() == 0) {
+	    _dontEscape = null;
+        }
+
 	_types         = setupMapping(_namesArray);
     }
 
@@ -2614,9 +2663,23 @@
 				       _lengthOrAttr[node]));
 	    break;
 	case TEXT:
+	    boolean last = false;
+	    boolean escapeBit = false;
+
+	    if (_dontEscape != null) {	
+		escapeBit = _dontEscape.getBit(node);
+		if (escapeBit) {
+		    last = handler.setEscaping(false);
+		}	
+	    }
+
 	    handler.characters(_text,
 			       _offsetOrChild[node],
 			       _lengthOrAttr[node]);
+
+            if (_dontEscape != null && escapeBit) {
+		handler.setEscaping(last);
+	    }	
 	    break;
 	case ATTRIBUTE:
 	    shallowCopy(node, handler);
@@ -2628,6 +2691,7 @@
 	    if (isElement(node)) {
 		// Start element definition
 		final String name = copyElement(node, type, handler);
+
 		// Copy element attribute
 		for (int a=_lengthOrAttr[node]; a!=NULL; a=_nextSibling[a]) {
 		    if (_type[a] != NAMESPACE) {
@@ -2694,9 +2758,11 @@
 	case ROOT: // do nothing
 	    return EMPTYSTRING;
 	case TEXT:
+
 	    handler.characters(_text,
 			       _offsetOrChild[node],
 			       _lengthOrAttr[node]);
+
 	    return null;
 	case PROCESSING_INSTRUCTION:
 	    copyPI(node, handler);
@@ -2899,8 +2965,7 @@
      * DOM builder's interface is pure SAX2 (must investigate)
      */
     public TransletOutputHandler getOutputDomBuilder() {
-	DOMBuilder builder = getBuilder();
-	return new SAXAdapter(builder, builder);
+	return new SAXAdapter(new DOMBuilderImpl());
     }
 
     /**
@@ -2959,6 +3024,11 @@
 	private static final String XML_STRING = "xml:";
 	private static final String XMLSPACE_STRING = "xml:space";
 	private static final String PRESERVE_STRING = "preserve";
+	private static final String XML_PREFIX   = "xml";
+	private static final String XMLNS_PREFIX = "xmlns";
+
+	private boolean _escaping = true;
+	private boolean _disableEscaping = false;
 
 	/**
 	 * Default constructor for the DOMBuiler class
@@ -3076,7 +3146,6 @@
 	 */
 	private short makeElementNode(String uri, String localname)
 	    throws SAXException {
-	    
 	    final String name;
 	    if (uri != EMPTYSTRING)
 		name = uri + ':' + localname;
@@ -3170,6 +3239,7 @@
 	 */
 	private int makeTextNode(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...
@@ -3188,6 +3258,14 @@
 		_type[node] = TEXT;
 		linkChildren(node);
 		storeTextRef(node);
+
+		if (_disableEscaping) {
+		    if (_dontEscape == null) {
+			_dontEscape = new BitArray(_whitespace.size());
+		    }
+		    _dontEscape.setBit(node);
+		    _disableEscaping = false;
+		}
 		return node;
 	    }
 	    return -1;
@@ -3217,33 +3295,34 @@
 	 * Creates an attribute node
 	 */
 	private int makeAttributeNode(int parent, Attributes attList, int i)
-	    throws SAXException {
-
+	    throws SAXException 
+	{
     	    final int node = nextAttributeNode();
-
 	    final String qname = attList.getQName(i);
-	    final String localname = attList.getLocalName(i);
+	    String localName = attList.getLocalName(i);
 	    final String value = attList.getValue(i);
 	    StringBuffer namebuf = new StringBuffer(EMPTYSTRING);
 	    
-	    // Create the internal attribute node name (uri+@+localname)
-	    if (qname.startsWith(XML_STRING)) {
-		if (qname.startsWith(XMLSPACE_STRING))
-		    xmlSpaceDefine(attList.getValue(i), parent);
+	    if (qname.startsWith(XMLSPACE_STRING)) {
+		xmlSpaceDefine(attList.getValue(i), parent);
 	    }
+
+	    // If local name is null set it to the empty string
+	    if (localName == null) {
+		localName = EMPTYSTRING;
+	    }
+
+	    // Create the internal attribute node name (uri+@+localname)
 	    final String uri = attList.getURI(i);
-	    if ((uri != null) && (!uri.equals(EMPTYSTRING))) {
+	    if (uri != null && !uri.equals(EMPTYSTRING)) {
 		namebuf.append(uri);
 		namebuf.append(':');
 	    }
 	    namebuf.append('@');
-	    if (localname != null )
-                namebuf.append(localname);
-            else
-                namebuf.append(qname);
+	    namebuf.append(localName.length() > 0 ? localName : qname);
 
 	    String name = namebuf.toString();
-	    
+
 	    // Get the index of the attribute node name (create new if non-ex).
 	    Integer obj = (Integer)_names.get(name);
 	    if (obj == null) {
@@ -3280,6 +3359,9 @@
 	    }
 	    System.arraycopy(ch, start, _text, _currentOffset, length);
 	    _currentOffset += length;
+
+	    _disableEscaping = !_escaping;	
+
 	}
 
 	/**
@@ -3295,7 +3377,7 @@
 	    _type2[0] = NAMESPACE;
 
 	    startPrefixMapping(EMPTYSTRING, EMPTYSTRING);
-	    startPrefixMapping("xml", "http://www.w3.org/XML/1998/namespace");
+	    startPrefixMapping(XML_PREFIX, "http://www.w3.org/XML/1998/namespace");
 	    _lengthOrAttr[ROOTNODE] = _nextNamespace;
 	    _parent2[_nextNamespace] = ROOTNODE;
 	    _nextNamespace = DOM.NULL;
@@ -3374,41 +3456,61 @@
 
 	    _lengthOrAttr[node] = DOM.NULL;
 
+	    int last = -1;
 	    final int count = attributes.getLength();
 
 	    // Append any namespace nodes
 	    if (_nextNamespace != DOM.NULL) {
 		_lengthOrAttr[node] = _nextNamespace;
+
 		while (_nextNamespace != DOM.NULL) {
 		    _parent2[_nextNamespace] = node;
-		    int tail = _nextNamespace;
-		    _nextNamespace = _nextSibling2[_nextNamespace];
+		    _nextNamespace = _nextSibling2[last = _nextNamespace];
 		    // Chain last namespace node to following attribute node(s)
-		    if ((_nextNamespace == DOM.NULL) && (count > 0))
-			_nextSibling2[tail] = _currentAttributeNode;
+		    if (_nextNamespace == DOM.NULL && count > 0) {
+			_nextSibling2[last] = _currentAttributeNode;
+		    }
 		}
 	    }
 
+	    // If local name is null set it to the empty string
+	    if (localName == null) {
+		localName = EMPTYSTRING;
+	    }
+
 	    // Append any attribute nodes
+	    boolean attrsAdded = false;
 	    if (count > 0) {
 		int attr = _currentAttributeNode;
-		if (_lengthOrAttr[node] == DOM.NULL)
+		if (_lengthOrAttr[node] == DOM.NULL) {
 		    _lengthOrAttr[node] = attr;
-		for (int i = 0; i<count; i++) {
-		    attr = makeAttributeNode(node, attributes, i);
-		    _parent2[attr] = node;
-		    _nextSibling2[attr] = attr + 1;
 		}
-		_nextSibling2[attr] = DOM.NULL;
+		for (int i = 0; i < count; i++) {
+		    if (!attributes.getQName(i).startsWith(XMLNS_PREFIX)) {
+			attr = makeAttributeNode(node, attributes, i);
+			_parent2[attr] = node;
+			_nextSibling2[attr] = attr + 1;
+			attrsAdded = true;
+		    }
+		}
+		// Did we append namespace nodes only?
+		if (!attrsAdded && last != -1) {
+		    _nextSibling2[last] = DOM.NULL;
+		}
+		else {
+		    _nextSibling2[attr] = DOM.NULL;
+		}
 	    }
 
 	    final int col = qname.lastIndexOf(':');
 
 	    // Assign an internal type to this element (may exist)
-	    if ((uri != null) && (localName.length() > 0))
+	    if (uri != null && localName.length() > 0) {
 		_type[node] = makeElementNode(uri, localName);
-	    else
+	    }
+	    else {
 		_type[node] = makeElementNode(qname, col);
+	    }
 
 	    // Assign an internal type to the element's prefix (may exist)
 	    if (col > -1) {
@@ -3502,7 +3604,8 @@
 		else
 		    _nextSibling2[attr-1] = attr;
 		_nextSibling2[attr] = DOM.NULL;
-		_prefix2[attr] = idx.shortValue();
+		// _prefix2[attr] = idx.shortValue();
+		_prefix2[attr] = ((Integer) stack.elementAt(0)).shortValue();
 	    }
 	}
 
@@ -3587,6 +3690,11 @@
 	    // Resize the '_whitespace' array (a BitArray instance)
 	    _whitespace.resize(newSize);
 
+	    // Resize the '_dontEscape' array (a BitArray instance)
+	    if (_dontEscape != null) {
+		_dontEscape.resize(newSize);
+	    }
+
 	    // Resize the '_prefix' array
 	    final short[] newPrefix = new short[newSize];
 	    System.arraycopy(_prefix, 0, newPrefix, 0, length);
@@ -3656,5 +3764,11 @@
 	    }
 	}
 
+ 	public boolean setEscaping(boolean value) {
+	    final boolean temp = _escaping;
+	    _escaping = value; 
+	    return temp;
+    	}
+
     } // end of DOMBuilder
 }
diff --git a/src/org/apache/xalan/xsltc/dom/ExtendedSAX.java b/src/org/apache/xalan/xsltc/dom/ExtendedSAX.java
new file mode 100644
index 0000000..8e87428
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/dom/ExtendedSAX.java
@@ -0,0 +1,69 @@
+/*
+ * @(#)$Id$
+ *
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 2001, Sun
+ * Microsystems., http://www.sun.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * @author Morten Jorgensen
+ *
+ */
+package org.apache.xalan.xsltc.dom;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ext.LexicalHandler;
+
+public interface ExtendedSAX extends ContentHandler, LexicalHandler { 
+    public boolean setEscaping(boolean escape);
+}
diff --git a/src/org/apache/xalan/xsltc/dom/MultiDOM.java b/src/org/apache/xalan/xsltc/dom/MultiDOM.java
index 95b7b87..ebaab3b 100644
--- a/src/org/apache/xalan/xsltc/dom/MultiDOM.java
+++ b/src/org/apache/xalan/xsltc/dom/MultiDOM.java
@@ -453,4 +453,9 @@
 	return(_adapters[node>>>24].isAttribute(node & CLR));
     }
 
+    public String lookupNamespace(int node, String prefix) 
+	throws TransletException
+    {
+	return _adapters[node>>>24].lookupNamespace(node, prefix);
+    }
 }
diff --git a/src/org/apache/xalan/xsltc/dom/SortingIterator.java b/src/org/apache/xalan/xsltc/dom/SortingIterator.java
index 9d16c2b..e2ffd9e 100644
--- a/src/org/apache/xalan/xsltc/dom/SortingIterator.java
+++ b/src/org/apache/xalan/xsltc/dom/SortingIterator.java
@@ -66,11 +66,12 @@
 
 import org.apache.xalan.xsltc.NodeIterator;
 import org.apache.xalan.xsltc.TransletException;
+import org.apache.xalan.xsltc.runtime.BasisLibrary;
 
 public final class SortingIterator extends NodeIteratorBase {
     private final static int INIT_DATA_SIZE = 16;
-    private final NodeIterator _source;
-    private final NodeSortRecordFactory _factory;
+    private NodeIterator _source;
+    private NodeSortRecordFactory _factory;
     private NodeSortRecord[] _data;
     private int _free = 0;
     private int _current;	// index in _nodes of the next node to try
@@ -124,6 +125,29 @@
 	_current = _markedNode;
     }
     
+    /**
+     * Clone a <code>SortingIterator</code> by cloning its source
+     * iterator and then sharing the factory and the array of
+     * <code>NodeSortRecords</code>.
+     */
+    public NodeIterator cloneIterator() {
+	try {
+	    final SortingIterator clone = (SortingIterator) super.clone();
+	    clone._source = _source.cloneIterator();  
+	    clone._factory = _factory;		// shared between clones
+	    clone._data = _data;		// shared between clones
+	    clone._free = _free;
+	    clone._current = _current;
+	    clone.setRestartable(false);
+	    return clone.reset();
+	}
+	catch (CloneNotSupportedException e) {
+	    BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR,
+				      e.toString());
+	    return null;
+	}
+    }
+
     private void addRecord(NodeSortRecord record) {
 	if (_free == _data.length) {
 	    NodeSortRecord[] newArray = new NodeSortRecord[_data.length * 2];
diff --git a/src/org/apache/xalan/xsltc/dom/UnionIterator.java b/src/org/apache/xalan/xsltc/dom/UnionIterator.java
index bfd1452..be22cd1 100644
--- a/src/org/apache/xalan/xsltc/dom/UnionIterator.java
+++ b/src/org/apache/xalan/xsltc/dom/UnionIterator.java
@@ -152,8 +152,10 @@
 	    final int smallest = _heap[0].node;
 	    if (smallest == END) { // iterator _heap[0] is done
 		if (_heapSize > 1) {
-		    // replace it with last
+		    // Swap first and last (iterator must be restartable)
+		    final LookAheadIterator temp = _heap[0];
 		    _heap[0] = _heap[--_heapSize];
+		    _heap[_heapSize] = temp;
 		}
 		else {
 		    return END;
diff --git a/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java b/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java
index e363410..9b4c431 100644
--- a/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java
+++ b/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java
@@ -143,44 +143,15 @@
      */
     public final void popParamFrame() {
 	if (pbase > 0) {
-	    int bot = pbase - 1;
-	    int top = pframe - 1;
-	    pframe = pbase - 1;
-	    pbase = ((Integer) paramsStack.elementAt(pframe)).intValue();
-	    // bug fix #3424, John Howard.
-	    // remove objects that are in the stack since objects are	
-	    // added with insertElementAt(int) and will cause memory retention
-	    for (int i=top; i>=bot; i--) {
-		paramsStack.removeElementAt(i);
+	    final int oldpbase = ((Integer)paramsStack.elementAt(--pbase)).intValue();
+	    for (int i = pbase; i < pframe; i++) {
+		paramsStack.setElementAt(null, i);	// for the GC
 	    }
+	    pframe = pbase; pbase = oldpbase;
 	}
     }
 
     /**
-     * Replace a certain character in a string with a new substring.
-     */
-    private static String replace(String base, char c, String str) {
-	final int len = base.length() - 1;
-	int pos;
-	while ((pos = base.indexOf(c)) > -1) {
-	    if (pos == 0) {
-		final String after = base.substring(1);
-		base = str + after;
-	    }
-	    else if (pos == len) {
-		final String before = base.substring(0, pos);
-		base = before + str;
-	    }
-	    else {
-		final String before = base.substring(0, pos);
-		final String after = base.substring(pos+1);
-		base = before + str + after;
-	    }
-	}
-	return base;
-    }
-
-    /**
      * Add a new global parameter if not already in the current frame.
      */
     public final Object addParameter(String name, Object value) {
@@ -224,6 +195,7 @@
      * Clears the parameter stack.
      */
     public void clearParameters() {  
+	pbase = pframe = 0;
 	paramsStack.clear();
     }
 
@@ -246,6 +218,7 @@
 	varsStack.insertElementAt(new Integer(vbase), vframe);
 	vbase = ++vframe;
 	vframe += frameSize;
+	varsStack.setSize(vframe + 1);	// clear stack frame
     }
 
     /**
@@ -253,16 +226,11 @@
      */
     public final void popVarFrame() {
 	if (vbase > 0) {
-	    int bot = vbase - 1;
-	    int top = vframe - 1;
-	    vframe = vbase - 1;
-	    vbase = ((Integer)varsStack.elementAt(vframe)).intValue();
-	    // bug fix 3424, John Howard
-	    // remove objects that are in the stack since objects are	
-	    // added with insertElementAt(int) and will cause memory retention
-	    for (int i=top; i>=bot; i--) {
-		varsStack.removeElementAt(i);
+	    final int oldvbase = ((Integer)varsStack.elementAt(--vbase)).intValue();
+	    for (int i = vbase; i < vframe; i++) {
+		varsStack.setElementAt(null, i);	// for the GC
 	    }
+	    vframe = vbase; vbase = oldvbase;
 	}
     }
 
@@ -270,18 +238,38 @@
      * Get the value of a variable given its index.
      */
     public final Object getVariable(int vindex) {
-	// bug fix 3424, John Howard
 	return varsStack.elementAt(vbase + vindex);
     }
 	
-
     /**
      * Set the value of a variable in the current frame.
      */
     public final void addVariable(int vindex, Object value) {
-	final int index = vbase + vindex;
-	if (index > varsStack.size()) varsStack.setSize(index);
-	varsStack.insertElementAt(value, index);
+	varsStack.setElementAt(value, vbase + vindex);
+    }
+
+    /**
+     * Replace a certain character in a string with a new substring.
+     */
+    private static String replace(String base, char c, String str) {
+	final int len = base.length() - 1;
+	int pos;
+	while ((pos = base.indexOf(c)) > -1) {
+	    if (pos == 0) {
+		final String after = base.substring(1);
+		base = str + after;
+	    }
+	    else if (pos == len) {
+		final String before = base.substring(0, pos);
+		base = before + str;
+	    }
+	    else {
+		final String before = base.substring(0, pos);
+		final String after = base.substring(pos+1);
+		base = before + str + after;
+	    }
+	}
+	return base;
     }
 
     /************************************************************************
@@ -582,10 +570,10 @@
 	    // Transfer all settings relevant to XML output
 	    if (_method.equals("xml")) {
 	        if (_standalone != null) handler.setStandalone(_standalone);
+		if (_omitHeader) handler.omitHeader(true);
 		handler.setType(TextOutput.XML);
 		handler.setCdataElements(_cdata);
 		if (_version != null) handler.setVersion(_version);
-		if (_omitHeader) handler.omitHeader(true);
 		handler.setIndent(_indent);
 		if (_doctypeSystem != null)
 		    handler.setDoctype(_doctypeSystem, _doctypePublic);
diff --git a/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java b/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java
index 18f223b..8e37169 100644
--- a/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java
+++ b/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java
@@ -427,7 +427,7 @@
 	if (name.equals("xsl:version"))
 	    return("1.0");
 	if (name.equals("xsl:vendor"))
-	    return("Apache Xalan XSLTC");
+	    return("Apache Software Foundation");
 	if (name.equals("xsl:vendor-url"))
 	    return("http://xml.apache.org/xalan-j");
 	
@@ -960,6 +960,29 @@
 	}
     }
     
+    /**
+     * This function is used in the execution of xsl:element
+     */
+    public static String getPrefix(String qname) {
+	final int index = qname.indexOf(':');
+	return (index > 0) ? qname.substring(0, index) : null;
+    }
+
+    /**
+     * This function is used in the execution of xsl:element
+     */
+    private static int prefixIndex = 0;
+    public static String generatePrefix() {
+	return ("ns" + prefixIndex++);
+    }
+
+    /**
+     * This function is used in the execution of xsl:element
+     */
+    public static String makeQName(String localName, String prefix) {
+	return (new StringBuffer(prefix).append(':').append(localName).toString());
+    }
+
     public static final int RUN_TIME_INTERNAL_ERR   = 0;
     public static final int RUN_TIME_COPY_ERR       = 1;
     public static final int DATA_CONVERSION_ERR     = 2;
diff --git a/src/org/apache/xalan/xsltc/runtime/Constants.java b/src/org/apache/xalan/xsltc/runtime/Constants.java
index 4f72e23..da2bdb3 100644
--- a/src/org/apache/xalan/xsltc/runtime/Constants.java
+++ b/src/org/apache/xalan/xsltc/runtime/Constants.java
@@ -83,4 +83,9 @@
     public static final String NAMESPACE_FEATURE =
 	"http://xml.org/sax/features/namespaces";
 
+    public static final String EMPTYSTRING = "";
+    public static final String XML_PREFIX = "xml";
+    public static final String XMLNS_PREFIX = "xmlns";
+    public static final String XMLNS_STRING = "xmlns:";
+    public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
 }
diff --git a/src/org/apache/xalan/xsltc/runtime/DefaultSAXOutputHandler.java b/src/org/apache/xalan/xsltc/runtime/DefaultSAXOutputHandler.java
index 37e3c3e..b3d356f 100644
--- a/src/org/apache/xalan/xsltc/runtime/DefaultSAXOutputHandler.java
+++ b/src/org/apache/xalan/xsltc/runtime/DefaultSAXOutputHandler.java
@@ -63,6 +63,8 @@
 
 package org.apache.xalan.xsltc.runtime;
 
+import java.util.Vector;
+
 import java.io.IOException;
 import java.io.Writer;
 import java.io.FileOutputStream;
@@ -122,7 +124,7 @@
     private int     _indentLevel = 0;
 
     // This is used for aggregating namespace declarations
-    private AttributeList _namespaceDeclarations = new AttributeList();
+    private Vector _namespaceDecls = null;
 
     /**
      * Constructor - set Writer to send output to and output encoding
@@ -239,7 +241,8 @@
     /**
      * SAX2: Receive notification of the beginning of a document.
      */
-    public void startDocument() throws SAXException { }
+    public void startDocument() throws SAXException { 
+    }
 
     /**
      * SAX2: Receive notification of the end of an element.
@@ -266,7 +269,7 @@
             if (_startTagOpen) closeStartTag(true); // Close any open element.
             _element = elementName; // Save element name
 
-	    // Handle indentation (not a requirement)
+	    // Handle inden3dcb50483dcb504tation (not a requirement)
             if (_indent) {
 		if (!_emptyElements.containsKey(elementName.toLowerCase())) {
 		    indent(_lineFeedNextStartTag);
@@ -283,24 +286,26 @@
 	    _indentNextEndTag = false;
 
 	    // 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);
+	    if (_namespaceDecls != null) {
+		int nDecls = _namespaceDecls.size();
+		for (int i = 0; i < nDecls; i++) {
+		    final String prefix = (String) _namespaceDecls.elementAt(i++);
+		    _writer.write(XMLNS);
+		    if ((prefix != null) && (prefix != EMPTYSTRING)) {
+			_writer.write(':');
+			_writer.write(prefix);
+		    }
+		    _writer.write('=');
+		    _writer.write('\"');
+		    _writer.write((String) _namespaceDecls.elementAt(i));
+		    _writer.write('\"');
 		}
-		_writer.write('=');
-		_writer.write('\"');
-		_writer.write(_namespaceDeclarations.getValue(i));
-		_writer.write('\"');
-            }
-	    _namespaceDeclarations.clear();
+		_namespaceDecls.clear();
+	    }
 
 	    // ...then output all attributes
 	    int attrCount = attrs.getLength();
-	    for (int i=0; i<attrCount; i++) {
+	    for (int i = 0; i < attrCount; i++) {
 		_writer.write(' ');
 		_writer.write(attrs.getQName(i));
 		_writer.write('=');
@@ -440,7 +445,11 @@
      *       Namespace declarations are output in startElement()
      */
     public void startPrefixMapping(String prefix, String uri) {
-	_namespaceDeclarations.add(prefix,uri);
+	if (_namespaceDecls == null) {
+	    _namespaceDecls = new Vector(2);
+	}
+	_namespaceDecls.addElement(prefix);
+	_namespaceDecls.addElement(uri);
     }
 
     /**
diff --git a/src/org/apache/xalan/xsltc/runtime/SAXAdapter.java b/src/org/apache/xalan/xsltc/runtime/SAXAdapter.java
index ae0e891..8642def 100644
--- a/src/org/apache/xalan/xsltc/runtime/SAXAdapter.java
+++ b/src/org/apache/xalan/xsltc/runtime/SAXAdapter.java
@@ -65,37 +65,32 @@
 package org.apache.xalan.xsltc.runtime;
 
 import org.xml.sax.*;
-import org.xml.sax.ext.LexicalHandler;
-import org.apache.xalan.xsltc.*;
+import org.xml.sax.ext.*;
+import org.apache.xalan.xsltc.TransletException;
+import org.apache.xalan.xsltc.TransletOutputHandler;
+import org.apache.xalan.xsltc.dom.DOMBuilder;
 
 public final class SAXAdapter implements TransletOutputHandler {
 
-    private final ContentHandler _saxHandler;
-    private final LexicalHandler _lexHandler;
+    private final DOMBuilder _domBuilder;
     private final AttributeList  _attributes = new AttributeList();
 
     private String _openElementName;
     
-    public SAXAdapter(ContentHandler saxHandler) {
-	_saxHandler = saxHandler;
-	_lexHandler = null;
-    }
-
-    public SAXAdapter(ContentHandler saxHandler, LexicalHandler lexHandler) {
-	_saxHandler = saxHandler;
-	_lexHandler = lexHandler;
+    public SAXAdapter(DOMBuilder domBuilder) {
+	_domBuilder = domBuilder;
     }
 
     private void maybeEmitStartElement() throws SAXException {
 	if (_openElementName != null) {
-	    _saxHandler.startElement(null, null, _openElementName, _attributes);
+	    _domBuilder.startElement(null, null, _openElementName, _attributes);
 	    _openElementName = null;
 	}
     }
 
     public void startDocument() throws TransletException {
 	try {
-	    _saxHandler.startDocument();
+	    _domBuilder.startDocument();
 	}
 	catch (SAXException e) {
 	    throw new TransletException(e);
@@ -104,7 +99,7 @@
     
     public void endDocument() throws TransletException {
 	try {
-	    _saxHandler.endDocument();
+	    _domBuilder.endDocument();
 	}
 	catch (SAXException e) {
 	    throw new TransletException(e);
@@ -115,7 +110,7 @@
 	throws TransletException {
 	try {
 	    maybeEmitStartElement();
-	    _saxHandler.characters(characters, offset, length);
+	    _domBuilder.characters(characters, offset, length);
 	}
 	catch (SAXException e) {
 	    throw new TransletException(e);
@@ -136,7 +131,7 @@
     public void endElement(String elementName) throws TransletException {
 	try {
 	    maybeEmitStartElement();
-	    _saxHandler.endElement(null, null, elementName);
+	    _domBuilder.endElement(null, null, elementName);
 	}
 	catch (SAXException e) {
 	    throw new TransletException(e);
@@ -161,9 +156,9 @@
     public void comment(String comment) throws TransletException {
 	try {
 	    maybeEmitStartElement();
-	    if (_lexHandler != null) {
+	    if (_domBuilder != null) {
 		char[] chars = comment.toCharArray();
-		_lexHandler.comment(chars, 0, chars.length);
+		_domBuilder.comment(chars, 0, chars.length);
 	    }
 	}
 	catch (SAXException e) {
@@ -175,13 +170,17 @@
 	throws TransletException {
 	try {
 	    maybeEmitStartElement();
-	    _saxHandler.processingInstruction(target, data);
+	    _domBuilder.processingInstruction(target, data);
 	}
 	catch (SAXException e) {
 	    throw new TransletException(e);
 	}
     }
 
+    public boolean setEscaping(boolean escape) throws TransletException {
+	return _domBuilder.setEscaping(escape);
+    }
+
     // The SAX handler does not handle these:
     public void setType(int type) {}
     public void setHeader(String header) {}
@@ -189,8 +188,5 @@
     public void omitHeader(boolean value) {}
     public void setCdataElements(Hashtable elements) { }
     public void close() {}
-    public boolean setEscaping(boolean escape) throws TransletException {
-        return(true);
-    }
     public String getPrefix(String uri) { return(""); }
 }
diff --git a/src/org/apache/xalan/xsltc/runtime/StringValueHandler.java b/src/org/apache/xalan/xsltc/runtime/StringValueHandler.java
index 2e47eb4..cd0f76e 100644
--- a/src/org/apache/xalan/xsltc/runtime/StringValueHandler.java
+++ b/src/org/apache/xalan/xsltc/runtime/StringValueHandler.java
@@ -86,4 +86,29 @@
 	_free = 0;		// getValue resets
 	return new String(_buffer, 0, length);
     }
+
+    /**
+     * The value of a PI must not contain the substring "?>". Should
+     * that substring be present, replace it by "? >". 
+     */
+    public String getValueOfPI() {
+	final String value = getValue();
+
+	if (value.indexOf("?>") > 0) {
+	    final int n = value.length(); 
+	    final StringBuffer valueOfPI = new StringBuffer();
+
+	    for (int i = 0; i < n;) {
+		final char ch = value.charAt(i++);
+		if (ch == '?' && value.charAt(i) == '>') {
+		    valueOfPI.append("? >"); i++;
+		}
+		else {
+		    valueOfPI.append(ch);
+		}
+	    } 
+	    return valueOfPI.toString();
+	}
+	return value;
+    }
 }
diff --git a/src/org/apache/xalan/xsltc/runtime/TextOutput.java b/src/org/apache/xalan/xsltc/runtime/TextOutput.java
index fd29db7..4e7a27e 100644
--- a/src/org/apache/xalan/xsltc/runtime/TextOutput.java
+++ b/src/org/apache/xalan/xsltc/runtime/TextOutput.java
@@ -72,10 +72,11 @@
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
 
 import org.apache.xalan.xsltc.*;
 
-public final class TextOutput implements TransletOutputHandler {
+public final class TextOutput implements TransletOutputHandler, Constants {
 
     // These are the various output types we handle
     public static final int UNKNOWN = 0; // determine type from output contents
@@ -100,8 +101,6 @@
     // Contains all elements that should be output as CDATA sections
     private Hashtable _cdata = null;
 
-    private static final String XML_PREFIX = "xml";
-
     private static final char[] AMP      = "&amp;".toCharArray();
     private static final char[] LT       = "&lt;".toCharArray();
     private static final char[] GT       = "&gt;".toCharArray();
@@ -124,15 +123,15 @@
     private static final int BEGCOMM_length = BEGCOMM.length;
     private static final int ENDCOMM_length = ENDCOMM.length;
 
-    private static final String EMPTYSTRING     = "";
     private static final String HREF_STR        = "href";
-    private static final String SRC_STR         = "str";
+    private static final String CITE_STR        = "cite";
+    private static final String SRC_STR         = "src";
     private static final String CHAR_ESC_START  = "&#";
     private static final String CDATA_ESC_START = "]]>&#";
     private static final String CDATA_ESC_END   = ";<![CDATA[";
 
-    private AttributeList _attributes = new AttributeList();
-    private String        _elementName = null;
+    private AttributesImpl _attributes = new AttributesImpl();
+    private String         _elementName = null;
 
     // Each entry (prefix) in this hashtable points to a Stack of URIs
     private Hashtable _namespaces;
@@ -252,8 +251,8 @@
 	    AttributeList attrs = new AttributeList();
 	    attrs.add("http-equiv", "Content-Type");
 	    attrs.add("content", _mediaType+"; charset="+_encoding);
-	    _saxHandler.startElement(null, null, "meta", attrs);
-	    _saxHandler.endElement(null, null, "meta");
+	    _saxHandler.startElement(EMPTYSTRING, EMPTYSTRING, "meta", attrs);
+	    _saxHandler.endElement(EMPTYSTRING, EMPTYSTRING, "meta");
 	}
     }
 
@@ -264,27 +263,10 @@
     public void closeStartTag() throws TransletException {
 	try {
 	    _startTagOpen = false;
-	    
-	    // Final check to assure that the element is within a namespace
-	    // that has been declared (all declarations for this element
-	    // should have been processed at this point).
-	    int col = _elementName.lastIndexOf(':');
-	    if (col > 0) {
-		final String prefix = _elementName.substring(0,col);
-		final String localname = _elementName.substring(col+1);
-		final String uri = lookupNamespace(prefix);
-		if (uri == null)
-		    BasisLibrary.runTimeError(BasisLibrary.NAMESPACE_PREFIX_ERR,
-					      prefix);
-		if (uri.equals(EMPTYSTRING)) _elementName = localname;
-		_saxHandler.startElement(uri, localname,
-					 _elementName, _attributes);
-	    }
-	    else {
-		final String uri = lookupNamespace(EMPTYSTRING);
-		_saxHandler.startElement(uri, _elementName,
-					 _elementName, _attributes);
-	    }
+
+	    // Now is time to send the startElement event
+	    _saxHandler.startElement(getNamespaceURI(_elementName, true),
+		getLocalName(_elementName), _elementName, _attributes);
 
 	    // Insert <META> tag directly after <HEAD> element in HTML output
 	    if (_headTagOpen) {
@@ -467,9 +449,7 @@
      * Start an element in the output document. This might be an XML
      * element (<elem>data</elem> type) or a CDATA section.
      */
-    public void startElement(String elementName)
-	throws TransletException {
-
+    public void startElement(String elementName) throws TransletException {
 	try {
 	    switch(_outputType) {
 
@@ -670,6 +650,14 @@
 	return(buf.toString());
     }
 
+    private String makeHHString(int i) {
+	String s = Integer.toHexString(i).toUpperCase();
+	if (s.length() == 1) {
+	    s = "0"+s;
+	}
+	return s;
+    }
+
     /**
      * This method escapes special characters used in HTML attribute values
      */
@@ -681,9 +669,17 @@
 	char[] ch = base.toCharArray();
 	StringBuffer buf = new StringBuffer();
         for(int i=0; i<base.length(); i++){
-	    if (ch[i] > '\u007F') {
-	        buf.append('%');
-		buf.append(Integer.toHexString((int)ch[i]));
+	    if (ch[i] <= 0x20) {
+		buf.append('%');
+		buf.append(makeHHString(ch[i]));
+	    } 
+	    else if (ch[i] > '\u007F') {
+		int high = (ch[i] >> 6) | 0xC0;
+		int low  = (ch[i] & 0x3F) | 0x80;  // First 6 bits + high bit
+		buf.append('%');
+		buf.append(makeHHString(high));
+		buf.append('%');
+		buf.append(makeHHString(low));
 	    }
 	    else {
 		// These chars are reserved or unsafe in URLs
@@ -705,7 +701,8 @@
 		        buf.append(Integer.toHexString((int)ch[i]));
 		        break;
 		    case '\u0026' :
-			buf.append("&amp;");
+			//bug fix for customer/murphy3: buf.append("&amp;");
+			buf.append("&");
 			break;
 		    default:	
 		        buf.append(ch[i]); break;
@@ -758,27 +755,51 @@
 	return base;
     }
 
-    private String expandAttribute(String qname) throws TransletException {
-	// If this attribute was created using an <xsl:attribute>
-	// element with a 'namespace' attribute and a 'name' attribute
-	// containing an AVT, then we might get an attribute name on
-	// a strange format like 'prefix1:prefix2:localpart', where
-	// prefix1 is from the AVT and prefix2 from the namespace.
-	final int endcol = qname.lastIndexOf(':');
-	if (endcol > 0) {
-	    final int startcol = qname.indexOf(':');
-	    final String localname = qname.substring(endcol+1);
-	    final String prefix = qname.substring(0,startcol);
-	    final String uri = lookupNamespace(prefix);
-	    if (uri == null)
+    /**
+     * Returns the URI of an element or attribute. Note that default namespaces 
+     * do not apply directly to attributes.
+     */
+    private String getNamespaceURI(String qname, boolean isElement) 
+	throws TransletException 
+    {
+	String uri = EMPTYSTRING;
+	int col = qname.lastIndexOf(':');
+	final String prefix = (col > 0) ? qname.substring(0, col) : EMPTYSTRING;
+
+	if (prefix != EMPTYSTRING || isElement) { 
+	    uri = lookupNamespace(prefix);
+	    if (uri == null && !prefix.equals(XMLNS_PREFIX)) {
 		BasisLibrary.runTimeError(BasisLibrary.NAMESPACE_PREFIX_ERR,
-					  prefix);
-	    // Omit prefix (use default) if the namespace URI is null
-	    if (uri.equals(EMPTYSTRING))
-		return(localname);
-	    // Construct new QName if we've got two alt. prefixes
-	    else if (endcol != startcol)
-		return(prefix+':'+localname);
+					  qname.substring(0, col));
+	    }
+	}
+	return uri;
+    }
+
+    /**
+     * Returns the local name of a qualified name. If the name has no prefix
+     * then return null. 
+     */
+    private static String getLocalName(String qname) throws TransletException {
+	final int col = qname.lastIndexOf(':');
+	return (col > 0) ? qname.substring(col + 1) : null;
+    }
+
+    /**
+     * TODO: This method is a HACK! Since XSLTC does not have access to the
+     * XML file, it sometimes generates a NS prefix of the form "ns?" for
+     * an attribute. If at runtime, when the qname of the attribute is
+     * known, another prefix is specified for the attribute, then we can get 
+     * a qname of the form "ns?:otherprefix:name". This function patches the 
+     * qname by simply ignoring "otherprefix".
+     */
+    private static String patchQName(String qname) throws TransletException {
+	final int lastColon = qname.lastIndexOf(':');
+	if (lastColon > 0) {
+	    final int firstColon = qname.indexOf(':');
+	    if (firstColon != lastColon) {
+		return qname.substring(0, firstColon) + qname.substring(lastColon);
+	    }
 	}
 	return qname;
     }
@@ -790,59 +811,110 @@
     public void attribute(String name, final String value)
 	throws TransletException {
 
-	switch(_outputType) {
-	case TEXT:
-	    // Do not output attributes if output mode is 'text'
-	    return;
-	case XML:
-	    if (!_startTagOpen)
-		BasisLibrary.runTimeError(BasisLibrary.STRAY_ATTRIBUTE_ERR,name);
-	    // Attributes whose names start with XML need special handling
-	    if (name.startsWith("xml")) {
-		// Output as namespace declaration
-		if (name.startsWith("xmlns")) {
-		    if (name.length() == 5)
-			namespace(EMPTYSTRING, value);
-		    else
-			namespace(name.substring(6),value);
-		    return;
-		}
-		// Output as xml:<blah> attribute
-		_attributes.add(name, value);
-	    }
-	    else {
-		// Output as regular attribute
-		_attributes.add(expandAttribute(name), escapeString(value));
-	    }
-	    return;
-	case HTML:
-	    if (!_startTagOpen)
-		BasisLibrary.runTimeError(BasisLibrary.STRAY_ATTRIBUTE_ERR,name);
-	    // The following is an attempt to escape an URL stored in a href
-	    // attribute of HTML output. Normally URLs should be encoded at
-	    // the time they are created, since escaping or unescaping a
-	    // completed URI might change its semantics. We limit or escaping
-	    // to include space characters only - and nothing else. This is for
-	    // two reasons: (1) performance and (2) we want to make sure that
-	    // we do not change the meaning of the URL.
+	if (_outputType == TEXT) return;
 
-	    // URL-encode href attributes in HTML output
-	    final String tmp = name.toLowerCase();
-	    if  (tmp.equals(HREF_STR) || tmp.equals(SRC_STR)) {
-		_attributes.add(name,quickAndDirtyUrlEncode(escapeAttr(value)));
+	final String patchedName = patchQName(name);
+	final String localName = getLocalName(patchedName);
+	final String uri = getNamespaceURI(patchedName, false);
+	final int index = (localName == null) ?
+				_attributes.getIndex(name) :	/* don't use patchedName */
+				_attributes.getIndex(uri, localName);
+
+	switch(_outputType) {
+	case XML:
+	    if (!_startTagOpen) {
+		BasisLibrary.runTimeError(BasisLibrary.STRAY_ATTRIBUTE_ERR, patchedName);
+	    }
+
+/*
+System.err.println("TextOutput.attribute() uri = " + uri
+    + " localname = " + localName
+    + " qname = " + name 
+    + "\n value = " + value
+    + " escapeString(value) = " + escapeString(value));
+*/
+
+	    // Output as namespace declaration
+	    if (name.startsWith(XMLNS_PREFIX)) {
+		namespace(name.length() > 6 ? name.substring(6) : EMPTYSTRING, value);
 	    }
 	    else {
-		_attributes.add(expandAttribute(name), escapeAttr(value));
+		if (index >= 0) {	// Duplicate attribute?
+		    _attributes.setAttribute(index, uri, localName, patchedName, "CDATA", 
+			escapeString(value));	
+		}
+		else {
+		    _attributes.addAttribute(uri, localName, patchedName, "CDATA", 
+			escapeString(value));
+		}
 	    }
-	    return;
+	    break;
+	case HTML:
+	    if (!_startTagOpen) {
+		BasisLibrary.runTimeError(BasisLibrary.STRAY_ATTRIBUTE_ERR,name);
+	    }
+
+	    /* 
+	     * The following is an attempt to escape an URL stored in a href
+	     * attribute of HTML output. Normally URLs should be encoded at
+	     * the time they are created, since escaping or unescaping a
+	     * completed URI might change its semantics. We limit or escaping
+	     * to include space characters only - and nothing else. This is for
+	     * two reasons: (1) performance and (2) we want to make sure that
+	     * we do not change the meaning of the URL.
+	     */
+	    final String tmp = name.toLowerCase();
+	    if (tmp.equals(HREF_STR) || tmp.equals(SRC_STR) || tmp.equals(CITE_STR)) {
+		if (index >= 0) {
+		    _attributes.setAttribute(index, EMPTYSTRING, EMPTYSTRING, name, 
+			"CDATA", quickAndDirtyUrlEncode(escapeAttr(value)));
+		}
+		else {
+		    _attributes.addAttribute(EMPTYSTRING, EMPTYSTRING, name, "CDATA",
+			quickAndDirtyUrlEncode(escapeAttr(value)));
+		}
+	    }
+	    else {
+		if (index >= 0) {
+		    _attributes.setAttribute(index, EMPTYSTRING, EMPTYSTRING, 
+			name, "CDATA", escapeNonURLAttr(value));
+		}
+		else {
+		    _attributes.addAttribute(EMPTYSTRING, EMPTYSTRING, 
+			name, "CDATA", escapeNonURLAttr(value));
+		}
+	    }
+	    break;
 	}
     }
 
     /**
+     * Escape non ASCII characters (> u007F) as &#XXX; entities.
+     */
+    private String escapeNonURLAttr(String base) {
+	final int len = base.length() - 1;
+
+	char[] ch = base.toCharArray();
+	StringBuffer buf = new StringBuffer();
+        for(int i=0; i<base.length(); i++){
+	    if (ch[i] > '\u007F') {
+	        buf.append(CHAR_ESC_START);
+		buf.append(Integer.toString((int)ch[i]));
+	        buf.append(';');
+	    }
+	    else {
+	        buf.append(ch[i]); 
+	    } 
+  	}
+	base = buf.toString();
+	return base;
+    }
+
+
+    /**
      * End an element or CDATA section in the output document
      */
     public void endElement(String elementName) throws TransletException {
-	
 	try {
 	    switch(_outputType) {
 	    case TEXT:
@@ -853,7 +925,10 @@
 		if (_startTagOpen) closeStartTag();
 		if (_cdataTagOpen) closeCDATA();
 
-		_saxHandler.endElement(null, null, (String)(_qnameStack.pop()));
+		final String qname = (String) _qnameStack.pop();
+		_saxHandler.endElement(getNamespaceURI(qname, true), 
+		    getLocalName(qname), qname);
+
 		popNamespaces();
 		if (((Integer)_cdataStack.peek()).intValue() == _depth)
 		    _cdataStack.pop();
@@ -862,7 +937,8 @@
 	    case HTML:
 		// Close any open element
 		if (_startTagOpen) closeStartTag();
-		_saxHandler.endElement(null, null, (String)(_qnameStack.pop()));
+		_saxHandler.endElement(EMPTYSTRING, EMPTYSTRING, 
+		    (String)(_qnameStack.pop()));
 		popNamespaces();
 		_depth--;		
 		return;
@@ -929,10 +1005,15 @@
 	_prefixStack = new Stack();
 
 	// Define the default namespace (initially maps to "" uri)
-	Stack stack =  new Stack();
-	_namespaces.put(EMPTYSTRING, stack);
+	Stack stack;
+	_namespaces.put(EMPTYSTRING, stack = new Stack());
 	stack.push(EMPTYSTRING);
 	_prefixStack.push(EMPTYSTRING);
+
+	_namespaces.put(XML_PREFIX, stack = new Stack());
+	stack.push("http://www.w3.org/XML/1998/namespace");
+	_prefixStack.push(XML_PREFIX);
+
 	_nodeStack.push(new Integer(-1));
 	_depth = 0;
     }
@@ -941,9 +1022,9 @@
      * Declare a prefix to point to a namespace URI
      */
     private void pushNamespace(String prefix, String uri) throws SAXException {
-
+	// Prefixes "xml" and "xmlns" cannot be redefined
 	if (prefix.equals(XML_PREFIX)) return;
-
+	
 	Stack stack;
 	// Get the stack that contains URIs for the specified prefix
 	if ((stack = (Stack)_namespaces.get(prefix)) == null) {
@@ -958,15 +1039,15 @@
 	_prefixStack.push(prefix);
 	_nodeStack.push(new Integer(_depth));
 
-	if ((!prefix.equals(EMPTYSTRING)) && (uri.equals(EMPTYSTRING))) return;
-	_saxHandler.startPrefixMapping(prefix, uri);
+	// Inform the SAX handler
+	_saxHandler.startPrefixMapping(prefix, escapeString(uri));
     }
 
     /**
      * Undeclare the namespace that is currently pointed to by a given prefix
      */
     private void popNamespace(String prefix) throws SAXException {
-
+	// Prefixes "xml" and "xmlns" cannot be redefined
 	if (prefix.equals(XML_PREFIX)) return;
 
 	Stack stack;
diff --git a/src/org/apache/xalan/xsltc/runtime/TransletLoader.java b/src/org/apache/xalan/xsltc/runtime/TransletLoader.java
index 1974afa..faa8861 100644
--- a/src/org/apache/xalan/xsltc/runtime/TransletLoader.java
+++ b/src/org/apache/xalan/xsltc/runtime/TransletLoader.java
@@ -57,6 +57,7 @@
  * <http://www.apache.org/>.
  *
  * @author Morten Jorgensen
+ * @author Santiago Pericas-Geertsen
  *
  */
 
@@ -64,6 +65,9 @@
 
 import java.lang.Class;
 import java.lang.ClassLoader;
+import java.lang.Thread;
+
+import java.net.*;	// temporary
 
 /**
  * This class is intended used when the default Class.forName() method fails.
@@ -91,14 +95,14 @@
      * Get a handle to the system class loader
      */
     public TransletLoader() {
-	// Get the default class loader
-	ClassLoader loader = this.getClass().getClassLoader();
-	// If this is the extensions class loader we need to get the
-	// default system class loader instead. This is permitted if
-	// this class was loaded by the extensions class loader.
-	String loaderName = loader.getClass().getName();
-	if (loaderName.equals("sun.misc.Launcher$ExtClassLoader"))
+	// Get the loader for the current thread (not the current class)
+	ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+	// Avoid using the extensions class loader (see comment above)
+	final String loaderName = loader.getClass().getName();
+	if (loaderName.equals("sun.misc.Launcher$ExtClassLoader")) {
 	    loader = ClassLoader.getSystemClassLoader();
+	}
 	_loader = loader;
     }
 
@@ -108,6 +112,7 @@
     public Class loadClass(String name) throws ClassNotFoundException {
 	return(Class.forName(name, false, _loader));
     }
+
     /**
      * Loads a Class definition and runs static initializers.
      */
diff --git a/src/org/apache/xalan/xsltc/trax/DOM2SAX.java b/src/org/apache/xalan/xsltc/trax/DOM2SAX.java
index af2ddb7..4f3af59 100644
--- a/src/org/apache/xalan/xsltc/trax/DOM2SAX.java
+++ b/src/org/apache/xalan/xsltc/trax/DOM2SAX.java
@@ -63,6 +63,10 @@
 
 package org.apache.xalan.xsltc.trax;
 
+import java.util.Stack;
+import java.util.Vector;
+import java.util.Hashtable;
+
 import org.xml.sax.XMLReader;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.DTDHandler;
@@ -74,6 +78,9 @@
 import org.xml.sax.SAXNotSupportedException;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.AttributeList;
+import org.xml.sax.helpers.AttributeListImpl;
+
 import org.w3c.dom.Node;
 import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
@@ -81,49 +88,110 @@
 import org.w3c.dom.Entity;
 import org.w3c.dom.Notation;
 
-import org.apache.xalan.xsltc.runtime.AttributeList;
+// import org.apache.xalan.xsltc.runtime.AttributeList;
 
-class DOM2SAX implements XMLReader , Locator {
+class DOM2SAX implements XMLReader, Locator {
 
-    private Document _dom = null;
+    private final static String EMPTYSTRING = "";
+    private static final String XMLNS_PREFIX = "xmlns";
+
+    private Node _dom = null;
     private ContentHandler _sax = null;
- 
+    private Hashtable _nsPrefixes = new Hashtable();
+
     public DOM2SAX(Node root) {
-	_dom = (Document)root;
+	_dom = root;
     }
 
     public ContentHandler getContentHandler() { 
 	return _sax;
     }
 
-    public DTDHandler getDTDHandler() { 
-	return null;
-    }
-
-    public ErrorHandler getErrorHandler() {
-	return null;
-    }
-
-    public boolean getFeature(String name) throws SAXNotRecognizedException,
-	SAXNotSupportedException
+    public void setContentHandler(ContentHandler handler) throws 
+	NullPointerException 
     {
-	return false;
+	if (handler == null) throw new NullPointerException();
+	_sax = handler;
     }
 
-    public void setFeature(String name, boolean value) throws 
-	SAXNotRecognizedException, SAXNotSupportedException 
+    /**
+     * Begin the scope of namespace prefix. Forward the event to the 
+     * SAX handler only if the prefix is unknown or it is mapped to a 
+     * different URI.
+     */
+    private boolean startPrefixMapping(String prefix, String uri) 
+	throws SAXException 
     {
-	
+	boolean pushed = true;
+	Stack uriStack = (Stack) _nsPrefixes.get(prefix);
+
+	if (uriStack != null) {
+	    if (uriStack.isEmpty()) {
+		_sax.startPrefixMapping(prefix, uri);
+		uriStack.push(uri);
+	    }
+	    else {
+		final String lastUri = (String) uriStack.peek();
+		if (!lastUri.equals(uri)) {
+		    _sax.startPrefixMapping(prefix, uri);
+		    uriStack.push(uri);
+		}
+		else {
+		    pushed = false;
+		}
+	    }	
+	}
+	else {
+	    _sax.startPrefixMapping(prefix, uri);
+	    _nsPrefixes.put(prefix, uriStack = new Stack());
+	    uriStack.push(uri);
+	}
+	return pushed;
+    }
+
+    /*
+     * End the scope of a name prefix by popping it from the stack and 
+     * passing the event to the SAX Handler.
+     */
+    private void endPrefixMapping(String prefix) 
+	throws SAXException
+    {
+	final Stack uriStack = (Stack) _nsPrefixes.get(prefix);
+
+	if (uriStack != null) {
+	    _sax.endPrefixMapping(prefix);
+	    uriStack.pop();
+	}
+    }
+
+    /**
+     * If the DOM was created using a DOM 1.0 API, the local name may be 
+     * null. If so, get the local name from the qualified name before 
+     * generating the SAX event. 
+     */
+    private static String getLocalName(Node node) {
+	final String localName = node.getLocalName();
+
+	if (localName == null) {
+	    final String qname = node.getNodeName();
+	    final int col = qname.lastIndexOf(':');
+	    return (col > 0) ? qname.substring(col + 1) : qname;
+	}
+	return localName;
     }
 
     public void parse(InputSource unused) throws IOException, SAXException {
-        Node currNode = _dom;
-        parse(currNode);
+        parse(_dom);
     }
 
+    /**
+     * Traverse the DOM and generate SAX events for a handler. A 
+     * startElement() event passes all attributes, including namespace 
+     * declarations. 
+     */
     private void parse(Node node) throws IOException, SAXException {
         Node first = null;
- 	if (node == null ) return;
+ 	if (node == null) return;
 
         switch (node.getNodeType()) {
 	case Node.ATTRIBUTE_NODE:         // handled by ELEMENT_NODE
@@ -139,6 +207,7 @@
 
 	case Node.DOCUMENT_NODE:
 	    _sax.setDocumentLocator(this);
+
 	    _sax.startDocument();
 	    Node next = node.getFirstChild();
 	    while (next != null) {
@@ -149,29 +218,85 @@
 	    break;
 
 	case Node.ELEMENT_NODE:
-	    // Gather all attribute node of the element
-	    AttributeList attrs = new AttributeList();
-	    NamedNodeMap map = node.getAttributes();
-	    int length = map.getLength();
-	    for (int i=0; i<length; i++ ) {
-		Node attr = map.item(i);
-		attrs.add(attr.getNodeName(), attr.getNodeValue());
+	    String prefix;
+	    Vector pushedPrefixes = new Vector();
+	    final AttributesImpl attrs = new AttributesImpl();
+	    final NamedNodeMap map = node.getAttributes();
+	    final int length = map.getLength();
+
+	    // Process all namespace declarations
+	    for (int i = 0; i < length; i++) {
+		final Node attr = map.item(i);
+		final String qnameAttr = attr.getNodeName();
+
+		// Ignore everything but NS declarations here
+		if (qnameAttr.startsWith(XMLNS_PREFIX)) {
+		    final String uriAttr = attr.getNodeValue();
+		    final int colon = qnameAttr.lastIndexOf(':');
+		    prefix = (colon > 0) ? qnameAttr.substring(colon + 1) : EMPTYSTRING;
+		    if (startPrefixMapping(prefix, uriAttr)) {
+			pushedPrefixes.addElement(prefix);
+		    }
+		}
+	    }
+
+	    // Process all other attributes
+	    for (int i = 0; i < length; i++) {
+		final Node attr = map.item(i);
+		final String qnameAttr = attr.getNodeName();
+
+		// Ignore NS declarations here
+		if (!qnameAttr.startsWith(XMLNS_PREFIX)) {
+		    final String uriAttr = attr.getNamespaceURI();
+		    final String localNameAttr = getLocalName(attr);
+
+		    // Uri may be implicitly declared
+		    if (uriAttr != null) {	
+			final int colon = qnameAttr.lastIndexOf(':');
+			prefix = (colon > 0) ? qnameAttr.substring(0, colon) : EMPTYSTRING;
+			if (startPrefixMapping(prefix, uriAttr)) {
+			    pushedPrefixes.addElement(prefix);
+			}
+		    }
+
+		    // Add attribute to list
+		    attrs.addAttribute(attr.getNamespaceURI(), getLocalName(attr), 
+			qnameAttr, "CDATA", attr.getNodeValue());
+		}
+	    }
+
+	    // Now process the element itself
+	    final String qname = node.getNodeName();
+	    final String uri = node.getNamespaceURI();
+	    final String localName = getLocalName(node);
+
+	    // Uri may be implicitly declared
+	    if (uri != null) {	
+		final int colon = qname.lastIndexOf(':');
+		prefix = (colon > 0) ? qname.substring(0, colon) : EMPTYSTRING;
+		if (startPrefixMapping(prefix, uri)) {
+		    pushedPrefixes.addElement(prefix);
+		}
 	    }
 
 	    // Generate SAX event to start element
-	    _sax.startElement(node.getNamespaceURI(), node.getLocalName(),
-			      node.getNodeName(), attrs);
+	    _sax.startElement(uri, localName, qname, attrs);
 
 	    // Traverse all child nodes of the element (if any)
 	    next = node.getFirstChild();
-	    while ( next != null ) {
+	    while (next != null) {
 		parse(next);
 		next = next.getNextSibling();
 	    }
 
 	    // Generate SAX event to close element
-	    _sax.endElement(node.getNamespaceURI(),
-				    node.getLocalName(), node.getNodeName());
+	    _sax.endElement(uri, localName, qname);
+
+	    // Generate endPrefixMapping() for all pushed prefixes
+	    final int nPushedPrefixes = pushedPrefixes.size();
+	    for (int i = 0; i < nPushedPrefixes; i++) {
+		endPrefixMapping((String) pushedPrefixes.elementAt(i));
+	    }
 	    break;
 
 	case Node.PROCESSING_INSTRUCTION_NODE:
@@ -186,48 +311,133 @@
 	}
     }
 
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public DTDHandler getDTDHandler() { 
+	return null;
+    }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public ErrorHandler getErrorHandler() {
+	return null;
+    }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public boolean getFeature(String name) throws SAXNotRecognizedException,
+	SAXNotSupportedException
+    {
+	return false;
+    }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public void setFeature(String name, boolean value) throws 
+	SAXNotRecognizedException, SAXNotSupportedException 
+    {
+    }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void parse(String sysId) throws IOException, SAXException {
 	throw new IOException("This method is not yet implemented.");
     }
-    public void setContentHandler(ContentHandler handler) throws 
-	NullPointerException 
-    {
-	if (handler == null ) throw new NullPointerException();
-	_sax = handler;
-    }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void setDTDHandler(DTDHandler handler) throws NullPointerException {
-	if (handler == null )  throw new NullPointerException();
     }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void setEntityResolver(EntityResolver resolver) throws 
 	NullPointerException 
     {
-	if (resolver == null )  throw new NullPointerException();
     }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public EntityResolver getEntityResolver() {
 	return null;
     }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void setErrorHandler(ErrorHandler handler) throws 
 	NullPointerException
     {
-	if (handler == null )  throw new NullPointerException();
     }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void setProperty(String name, Object value) throws
 	SAXNotRecognizedException, SAXNotSupportedException {
     }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public Object getProperty(String name) throws SAXNotRecognizedException,
 	SAXNotSupportedException
     {
 	return null;
     }
 
-    // Locator methods
-    public int getColumnNumber() { return 0; }
-    public int getLineNumber() { return 0; }
-    public String getPublicId() { return null; }
-    public String getSystemId() { return null; }
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public int getColumnNumber() { 
+	return 0; 
+    }
+    
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public int getLineNumber() { 
+	return 0; 
+    }
 
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public String getPublicId() { 
+	return null; 
+    }
 
-    // private 
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public String getSystemId() { 
+	return null; 
+    }
+
+    // Debugging 
     private String getNodeTypeFromCode(short code) {
 	String retval = null;
 	switch (code) {
diff --git a/src/org/apache/xalan/xsltc/trax/SAX2DOM.java b/src/org/apache/xalan/xsltc/trax/SAX2DOM.java
index 82177b7..de6da38 100644
--- a/src/org/apache/xalan/xsltc/trax/SAX2DOM.java
+++ b/src/org/apache/xalan/xsltc/trax/SAX2DOM.java
@@ -57,12 +57,14 @@
  * <http://www.apache.org/>.
  *
  * @author G. Todd Miller 
- *
  */
 
 
 package org.apache.xalan.xsltc.trax;
 
+import java.util.Stack;
+import java.util.Vector;
+
 import org.xml.sax.ContentHandler;
 import org.xml.sax.Locator;
 import org.xml.sax.Attributes;
@@ -75,164 +77,135 @@
 import org.w3c.dom.Element;
 import org.w3c.dom.Text;
 import org.w3c.dom.Attr;
-import java.util.Stack;
 
+import org.apache.xalan.xsltc.runtime.Constants;
 
-class SAX2DOM implements ContentHandler {
+class SAX2DOM implements ContentHandler, Constants {
 
-    private Document _document = null;
-    private DocumentBuilder _builder = null;
-    private Stack _nodeStk = null;
- 
+    private Document _root = null;
+    private Stack _nodeStk = new Stack();
+    private Vector _namespaceDecls = null;
+
     public SAX2DOM() throws ParserConfigurationException {
-	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-	_builder = factory.newDocumentBuilder();
-	_nodeStk = new Stack();
+	final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+	_root = factory.newDocumentBuilder().newDocument();
+    }
+
+    public SAX2DOM(Node root) throws ParserConfigurationException {
+	if (root != null) {
+	    _root = (Document) root;   // TODO: add support for frags and elems
+	}
+	else {
+	    final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+	    _root = factory.newDocumentBuilder().newDocument();
+	}
     }
 
     public Node getDOM() {
-	return _document;
+	return _root;
     }
 
     public void characters(char[] ch, int start, int length) {
-	Text text = _document.createTextNode(new String(ch, start, length));
-	Node last = (Node)_nodeStk.peek();
-	last.appendChild(text);
+	final Node last = (Node)_nodeStk.peek();
+
+	// No text nodes can be children of root (DOM006 exception)
+	if (last != _root) {
+	    final String text = new String(ch, start, length);
+	    last.appendChild(_root.createTextNode(text));
+	}
     }
 
     public void startDocument() {
-	_document = _builder.newDocument();
-	Element root = (Element)_document.createElement("root");
-	_document.appendChild(root);
-	_nodeStk.push(root);
+	_nodeStk.push(_root);
     }
 
     public void endDocument() {
-	//printDOM();
     }
 
     public void startElement(String namespace, String localName, String qName,
-	Attributes attrs ) 
+	Attributes attrs) 
     {
-	// create new element
-	Element tmp = (Element)_document.createElementNS(namespace, qName);
-	int nattrs = attrs.getLength();
-	for (int i=0; i<nattrs; i++ ) {
-	    String namespaceuri = attrs.getURI(i);
-	    String value = attrs.getValue(i);
-	    String qname = attrs.getQName(i);
-	    if ((namespaceuri == null) || (namespaceuri.equals("")))
-		tmp.setAttribute(qname, value);
-	    else
-		tmp.setAttributeNS(namespaceuri, qname, value);
+	final Element tmp = (Element)_root.createElementNS(namespace, qName);
+
+	// Add namespace declarations first
+	if (_namespaceDecls != null) {
+	    final int nDecls = _namespaceDecls.size();
+	    for (int i = 0; i < nDecls; i++) {
+		final String prefix = (String) _namespaceDecls.elementAt(i++);
+
+		if (prefix == null || prefix.equals(EMPTYSTRING)) {
+		    tmp.setAttributeNS(XMLNS_URI, XMLNS_PREFIX,
+			(String) _namespaceDecls.elementAt(i));
+		}
+		else {
+		    tmp.setAttributeNS(XMLNS_URI, XMLNS_STRING + prefix, 
+			(String) _namespaceDecls.elementAt(i));
+		}
+	    }
+	    _namespaceDecls.clear();
 	}
-	// append this new node onto current stack node
+
+	// Add attributes to element
+	final int nattrs = attrs.getLength();
+	for (int i = 0; i < nattrs; i++) {
+	    if (attrs.getLocalName(i) == null) {
+		tmp.setAttribute(attrs.getQName(i), attrs.getValue(i));
+	    }
+	    else {
+		tmp.setAttributeNS(attrs.getURI(i), attrs.getQName(i), 
+		    attrs.getValue(i));
+	    }
+	}
+
+	// Append this new node onto current stack node
 	Node last = (Node)_nodeStk.peek();
 	last.appendChild(tmp);
-	// push this node onto stack
+
+	// Push this node onto stack
 	_nodeStk.push(tmp);
     }
 
     public void endElement(String namespace, String localName, String qName) {
-	Node lastActive = (Node)_nodeStk.pop();  
-    }
-
-
-    public void ignorableWhitespace(char[] ch, int start, int length) {
-    }
-
-    public void processingInstruction(String target, String data) {
-    }
-
-    public void setDocumentLocator(Locator locator) {
-    }
-
-    public void skippedEntity(String name) {
+	_nodeStk.pop();  
     }
 
     public void startPrefixMapping(String prefix, String uri) {
+	if (_namespaceDecls == null) {
+	    _namespaceDecls = new Vector(2);
+	}
+	_namespaceDecls.addElement(prefix);
+	_namespaceDecls.addElement(uri);
     }
 
     public void endPrefixMapping(String prefix) {
+	// do nothing
     }
 
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public void ignorableWhitespace(char[] ch, int start, int length) {
+    }
 
-    // for debugging - will be removed
-    private void printDOM() {
-        System.out.println("SAX2DOM.java:Printing DOM...");
-        Node currNode = _document;
-        while (currNode != null) {
-            // start of node processing
-            switch (currNode.getNodeType()) {
-                case Node.ATTRIBUTE_NODE :
-                    break;
-                case Node.CDATA_SECTION_NODE :
-                    break;
-                case Node.COMMENT_NODE :
-                    break;
-                case Node.DOCUMENT_FRAGMENT_NODE :
-                    break;
-                case Node.DOCUMENT_NODE :
-                    break;
-                case Node.DOCUMENT_TYPE_NODE :
-                    break;
-                case Node.ELEMENT_NODE :
-                    System.out.println("ELEMT NODE " + currNode.getLocalName() +":");
-		     org.w3c.dom.NamedNodeMap map = currNode.getAttributes();
-                    int length = map.getLength();
-                    for (int i=0; i<length; i++ ){
-                        Node attrNode = map.item(i);
-                        short code = attrNode.getNodeType();
-                        System.out.println("\tattr:"+attrNode.getNamespaceURI()+
-                            "," + attrNode.getLocalName() +
-                            "," + attrNode.getNodeName() +
-                            "=" + attrNode.getNodeValue());
-                    }
-                    break;
-                case Node.ENTITY_NODE :
-                    org.w3c.dom.Entity edecl = (org.w3c.dom.Entity)currNode;
-                    String name = edecl.getNotationName();
-                    if ( name != null ) {
-                        System.out.println("ENT NODE: "+currNode.getNodeName()+
-                           ", "+ edecl.getSystemId()+ "," + name);
-                    }
-                    break;
-                case Node.ENTITY_REFERENCE_NODE :
-                    break;
-                case Node.NOTATION_NODE :
-                    break;
-                case Node.PROCESSING_INSTRUCTION_NODE :
-                    break;
-                case Node.TEXT_NODE :
-                    String data = currNode.getNodeValue();
-                    System.out.println("TEXT NODE:" + data);
-                    break;
-            }
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public void processingInstruction(String target, String data) {
+    }
 
-            // move to first child
-            Node next = currNode.getFirstChild();
-            if (next != null) {
-                currNode = next;
-                continue;
-            }
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public void setDocumentLocator(Locator locator) {
+    }
 
-            // no child nodes, walk the tree
-            while (currNode != null) {
-                switch (currNode.getNodeType()) {
-                    case Node.DOCUMENT_NODE:
-                        break;
-                    case Node.ELEMENT_NODE:
-                        break;
-                }
-                next = currNode.getNextSibling();
-                if (next != null ) {
-                    currNode = next;
-                    break;
-                }
-                // move up a level
-                currNode = currNode.getParentNode();
-            }
-        }
-   }
-
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public void skippedEntity(String name) {
+    }
 }
diff --git a/src/org/apache/xalan/xsltc/trax/TemplatesHandlerImpl.java b/src/org/apache/xalan/xsltc/trax/TemplatesHandlerImpl.java
index 3c8f8f0..f998609 100644
--- a/src/org/apache/xalan/xsltc/trax/TemplatesHandlerImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TemplatesHandlerImpl.java
@@ -91,8 +91,9 @@
 	// Create and initialize a stylesheet compiler
 	final XSLTC xsltc = new XSLTC();
 	super.setXSLTC(xsltc);
-	xsltc.setParser(this);
 	xsltc.init();
+	super.init();
+	xsltc.setParser(this);
 	xsltc.setOutputType(XSLTC.BYTEARRAY_OUTPUT);
     }
 
@@ -126,10 +127,7 @@
      *         process, or null if no Templates object has been created.
      */
     public Templates getTemplates() {
-
 	try {
-	    // Create a placeholder for the translet bytecodes
-	    byte[][] bytecodes = null;
 
 	    final XSLTC xsltc = getXSLTC();
 
@@ -137,6 +135,8 @@
 	    String transletName = TransformerFactoryImpl._defaultTransletName;
 	    if (_systemId != null) transletName = Util.baseName(_systemId);
 	    xsltc.setClassName(transletName);
+	    // get java-legal class name from XSLTC module
+	    transletName = xsltc.getClassName();
 
 	    Stylesheet stylesheet = null;
 	    SyntaxTreeNode root = getDocumentRoot();
@@ -161,6 +161,7 @@
 	    xsltc.printWarnings();
 
 	    // Check that the transformation went well before returning
+	    final byte[][] bytecodes = xsltc.getBytecodes();
 	    if (bytecodes == null) {
 		xsltc.printErrors();
 		return null;
diff --git a/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java b/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java
index e1c099c..26cde36 100644
--- a/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java
@@ -59,6 +59,7 @@
  * @author Morten Jorgensen
  * @author G. Todd Millerj
  * @author Jochen Cordes <Jochen.Cordes@t-online.de>
+ * @author Santiago Pericas-Geertsen 
  *
  */
 
@@ -176,8 +177,13 @@
 	    (TransletClassLoader) AccessController.doPrivileged(
 		new PrivilegedAction() {
 			public Object run() {
-			    ClassLoader current = getClass().getClassLoader();
-			    return new TransletClassLoader(current);
+			    /* 
+			     * Get the loader from the current thread instead of
+			     * the class. This is important for translets that load
+			     * external Java classes and run in multi-threaded envs.
+			     */
+			    return new TransletClassLoader(
+				Thread.currentThread().getContextClassLoader());
 			}
 		    }
 		);
diff --git a/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java b/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
index 2f2cc9b..a652020 100644
--- a/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
@@ -527,7 +527,9 @@
      */
     public TemplatesHandler newTemplatesHandler() 
 	throws TransformerConfigurationException { 
-	return(new TemplatesHandlerImpl());
+	final TemplatesHandlerImpl handler = new TemplatesHandlerImpl();
+	handler.init();
+	return handler;
     }
 
     /**
diff --git a/src/org/apache/xalan/xsltc/trax/TransformerImpl.java b/src/org/apache/xalan/xsltc/trax/TransformerImpl.java
index 24e66cf..e6eb0ce 100644
--- a/src/org/apache/xalan/xsltc/trax/TransformerImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TransformerImpl.java
@@ -211,7 +211,7 @@
                 if (handler != null) return handler;
             }
 	    else if (result instanceof DOMResult) {
-                return (new SAX2DOM());
+                return new SAX2DOM(((DOMResult) result).getNode());
             }
 	    else if (result instanceof StreamResult) {
 		// Get StreamResult
@@ -409,8 +409,14 @@
 	    // Handle DOMSource input
 	    else if (source instanceof DOMSource) {
 		final DOMSource   domsrc = (DOMSource)source;
-		final Document    tree = (Document)domsrc.getNode();
-		final DOM2SAX     dom2sax = new DOM2SAX(tree);
+		final org.w3c.dom.Node node = domsrc.getNode();
+
+		boolean isComplete = true;
+		if (node.getNodeType() != org.w3c.dom.Node.DOCUMENT_NODE) {
+		    isComplete = false;
+		}
+
+		final DOM2SAX     dom2sax = new DOM2SAX(node);
 		final InputSource input = null; 
 		final String      systemId = domsrc.getSystemId(); 
 
@@ -425,7 +431,13 @@
 		dom2sax.setContentHandler(builder);
 
 		// Parse the input and build the internal DOM
+		if (!isComplete) {
+		    builder.startDocument();
+		}
 		dom2sax.parse(input); // need this parameter?
+		if (!isComplete) {
+		    builder.endDocument();
+		}
 		dom.setDocumentURI(systemId);
 	    }
 	    // Handle StreamSource input
@@ -708,7 +720,8 @@
 	while (names.hasMoreElements()) {
 	    // Get the next property name and value
 	    String name  = (String)names.nextElement();
-	    String value = (String)properties.get(name);
+	    // bug fix # 6636- contributed by Tim Elcott
+	    String value = (String)properties.getProperty(name);
 
 	    // Pass property value to translet - override previous setting
 	    if (name.equals(OutputKeys.ENCODING))
@@ -756,13 +769,14 @@
     private Properties createOutputProperties() {
 	
 	// Level3: Return the default property value
+ 	// bug # 6751 fixed by removing setProperty lines for 
+  	//  OutputKeys.(DOCTYPE_PUBLIC|DOCTYPE_SYSTEM|CDATA_SECTION_ELEMENTS)
+  	//  instead of setting them to "" (EMPTY_STRING). Fix contributed
+  	//  by Derek Sayeau.   
 	Properties third = new Properties();
 	third.setProperty(OutputKeys.ENCODING, "UTF-8");
 	third.setProperty(OutputKeys.METHOD, XML_STRING);
 	third.setProperty(OutputKeys.INDENT, NO_STRING);
-	third.setProperty(OutputKeys.DOCTYPE_PUBLIC, EMPTY_STRING);
-	third.setProperty(OutputKeys.DOCTYPE_SYSTEM, EMPTY_STRING);
-	third.setProperty(OutputKeys.CDATA_SECTION_ELEMENTS, EMPTY_STRING);
 	third.setProperty(OutputKeys.MEDIA_TYPE, "text/xml");
 	third.setProperty(OutputKeys.OMIT_XML_DECLARATION, NO_STRING);
 	third.setProperty(OutputKeys.STANDALONE, NO_STRING);
diff --git a/src/trax/trax.properties b/src/trax/trax.properties
deleted file mode 100644
index e593c39..0000000
--- a/src/trax/trax.properties
+++ /dev/null
@@ -1,11 +0,0 @@
-# $Revision$ $Date$
-#
-# Note: This properties file is provided for illustrative purposes
-#       only and is not part of the interface definition.
-#       This properties file is located in the implementation JAR
-#       and different implementations will specify different
-#       implementation classes and output methods.
-#
-
-# The TRaX Stylesheet processor
-trax.processor.xslt=org.apache.xalan.processor.StylesheetProcessor