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

git-svn-id: https://svn.apache.org/repos/asf/xalan/java/tags/jaxp-ri-1_2_0-fcs-06@336540 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/build.xml b/build.xml
index 0e09c0f..0378c20 100644
--- a/build.xml
+++ b/build.xml
@@ -361,7 +361,19 @@
     </javac>
   </target>
 
-  <target name="xsltc.jar" depends="xsltc.compile"
+  <target name="xsltc.fcompile" 
+    description="Compile just the XSLTC classes w/o JLex, JCUP" >
+    <echo message="Compiling remaining XSLTC classes"/>
+    <javac srcdir="${src.dir}" 
+           destdir="${build.classes}"
+           includes="${xsltc.reldir}/**/*.java"
+           debug="${build.debug}">
+      <classpath refid="xsltc.class.path" />
+      <bootclasspath refid="xslt.boot.class.path" />
+    </javac>
+  </target>
+
+  <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 +386,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 +461,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/serialize/SerializerToXML.java b/src/org/apache/xalan/serialize/SerializerToXML.java
index f9705d8..5d38068 100644
--- a/src/org/apache/xalan/serialize/SerializerToXML.java
+++ b/src/org/apache/xalan/serialize/SerializerToXML.java
@@ -323,6 +323,9 @@
   /** Indicate whether running in Debug mode */
   private static final boolean DEBUG = false;
 
+  /** This flag is set while receiving events from the external DTD */
+  private boolean m_inExternalDTD = false;
+
   /**
    * Default constructor.
    */
@@ -1864,6 +1867,8 @@
    */
   public void startEntity(String name) throws org.xml.sax.SAXException
   {
+    if (name.equals("[dtd]"))
+      m_inExternalDTD = true;	
     m_inEntityRef = true;
   }
 
@@ -1876,7 +1881,9 @@
    */
   public void endEntity(String name) throws org.xml.sax.SAXException
   {
-    m_inEntityRef = false;
+    if (name.equals("[dtd]")) 
+      m_inExternalDTD = false;
+     m_inEntityRef = false;
   }
 
   /**
@@ -1925,7 +1932,10 @@
    */
   public void elementDecl(String name, String model) throws SAXException
   {
-    try
+    // Do not inline external DTD
+    if (m_inExternalDTD) return; 
+
+     try
     {
       final Writer writer = m_writer;
       if (m_inDoctype)
@@ -1975,6 +1985,8 @@
           String eName, String aName, String type, String valueDefault, String value)
             throws SAXException
   {
+    // Do not inline external DTD
+    if (m_inExternalDTD) return; 
 
     try
     {
@@ -1987,26 +1999,19 @@
         m_inDoctype = false;
       }
   
-      if (!eName.equals(m_elemName))
-      {
-        writer.write("<!ATTLIST ");
-        writer.write(eName);
-        writer.write(" ");
+      writer.write("<!ATTLIST ");
+      writer.write(eName);
+      writer.write(" ");
   
-        m_elemName = eName;
-      }
-      else
-      {
-        m_pos -= 3;
-  
-        writer.write(m_lineSep, 0, m_lineSepLen);
-      }
   
       writer.write(aName);
       writer.write(" ");
       writer.write(type);
-      writer.write(" ");
-      writer.write(valueDefault);
+      if (valueDefault != null)
+      {
+         writer.write(" ");
+         writer.write(valueDefault);
+      }
   
       //m_writer.write(" ");
       //m_writer.write(value);
@@ -2035,6 +2040,8 @@
   public void internalEntityDecl(String name, String value)
           throws SAXException
   {
+    // Do not inline external DTD
+    if (m_inExternalDTD) return; 
 
     try
     {
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/CastExpr.java b/src/org/apache/xalan/xsltc/compiler/CastExpr.java
index cec15f5..e028905 100644
--- a/src/org/apache/xalan/xsltc/compiler/CastExpr.java
+++ b/src/org/apache/xalan/xsltc/compiler/CastExpr.java
@@ -140,6 +140,7 @@
 	InternalTypeMap.put(Type.Reference, Type.String);
 	InternalTypeMap.put(Type.Reference, Type.Node);
 	InternalTypeMap.put(Type.Reference, Type.NodeSet);
+	InternalTypeMap.put(Type.Reference, Type.ResultTree);
 
 	InternalTypeMap.put(Type.Void, Type.String);
     }
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/ElementAvailableCall.java b/src/org/apache/xalan/xsltc/compiler/ElementAvailableCall.java
index 97e3f3c..cc14b58 100644
--- a/src/org/apache/xalan/xsltc/compiler/ElementAvailableCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/ElementAvailableCall.java
@@ -91,10 +91,11 @@
      * Returns the result that this function will return
      */
     public boolean getResult() {
-	final Parser parser = getParser();
-	final LiteralExpr arg = (LiteralExpr)argument();
-	final QName qname = parser.getQName(arg.getValue());
-	return(parser.elementSupported(qname));
+	final LiteralExpr arg = (LiteralExpr) argument();
+	final String qname = arg.getValue();
+	final int index = qname.indexOf(':');
+	final String localName = (index > 0) ? qname.substring(index + 1) : qname;
+	return getParser().elementSupported(arg.getNamespace(), localName);
     }
 
     /**
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..1987549 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_XSLTC) ||
+            _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..d609cd8 100644
--- a/src/org/apache/xalan/xsltc/compiler/FunctionCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/FunctionCall.java
@@ -86,10 +86,19 @@
     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 EXT_XSLTC = 
+	TRANSLET_URI;
+
+    protected final static String JAVA_EXT_XSLTC = 
+	EXT_XSLTC + "/java";
+
+    protected final static String EXT_XALAN =
+	"http://xml.apache.org/xalan";
+
+    protected final static String JAVA_EXT_XALAN =
 	"http://xml.apache.org/xslt/java";
 
+
     // External Java function's class/method/signature
     private String     _className;
     private Method     _chosenMethod;
@@ -170,6 +179,7 @@
     public FunctionCall(QName fname, Vector arguments) {
 	_fname = fname;
 	_arguments = arguments;
+	_type = null;
     }
 
     public FunctionCall(QName fname) {
@@ -192,48 +202,71 @@
 	}
     }
 
+    public String getClassNameFromUri(String uri) 
+	throws TypeCheckError
+    {
+	final int length = 
+	    uri.startsWith(JAVA_EXT_XSLTC) ? JAVA_EXT_XSLTC.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();
 
-	// XPath functions have no namespace
-	if (isStandard()) {
+	if (isExtension()) {
+	    _fname = new QName(null, null, local);
+	    return typeCheckStandard(stable);
+	}
+	else if (isStandard()) {
 	    return typeCheckStandard(stable);
 	}
 	// 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;
 	}
     }
 
@@ -243,8 +276,7 @@
      * thrown, then catch it and re-throw it with a new "this".
      */
     public Type typeCheckStandard(SymbolTable stable) throws TypeCheckError {
-
-	_fname.clearNamespace(); // HACK!!!
+	_fname.clearNamespace(); 	// HACK!!!
 
 	final int n = _arguments.size();
 	final Vector argsType = typeCheckArgs(stable);
@@ -367,8 +399,8 @@
      * Update true/false-lists.
      */
     public void translateDesynthesized(ClassGenerator classGen,
-				       MethodGenerator methodGen) {
-
+				       MethodGenerator methodGen) 
+    {
 	Type type = Type.Boolean;
 	if (_chosenMethodType != null)
 	    type = _chosenMethodType.resultType();
@@ -393,7 +425,7 @@
 	int index;
 
 	// Translate calls to methods in the BasisLibrary
-	if (isStandard()) {
+	if (isStandard() || isExtension()) {
 	    for (int i = 0; i < n; i++) {
 		final Expression exp = argument(i);
 		exp.translate(classGen, methodGen);
@@ -470,10 +502,13 @@
 
     public boolean isStandard() {
 	final String namespace = _fname.getNamespace();
-	if ((namespace == null) || (namespace.equals(Constants.EMPTYSTRING)))
-	    return true;
-	else
-	    return false;
+	return (namespace == null) || (namespace.equals(Constants.EMPTYSTRING));
+    }
+
+    public boolean isExtension() {
+	final String namespace = _fname.getNamespace();
+	return (namespace != null) && (namespace.equals(EXT_XSLTC) 
+	    || namespace.equals(EXT_XALAN));
     }
 
     /**
@@ -485,7 +520,7 @@
 	Vector result = null;
 	final String namespace = _fname.getNamespace();
 
-	if (namespace.startsWith(JAVA_EXT_PREFIX) ||
+	if (namespace.startsWith(JAVA_EXT_XSLTC) ||
 	    namespace.startsWith(JAVA_EXT_XALAN)) {
 	    final int nArgs = _arguments.size();
 	    try {
diff --git a/src/org/apache/xalan/xsltc/compiler/Include.java b/src/org/apache/xalan/xsltc/compiler/Include.java
index 9f50727..1719cc8 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;
@@ -88,8 +89,9 @@
 
     public void parseContents(final Parser parser) {
 	final Stylesheet context = parser.getCurrentStylesheet();
+	String docToLoad = getAttribute("href");
+
 	try {
-	    String docToLoad = getAttribute("href");
 	    if (context.checkForLoop(docToLoad)) {
 		final int errno = ErrorMsg.CIRCULAR_INCLUDE_ERR;
 		final ErrorMsg msg = new ErrorMsg(errno, docToLoad, this);
@@ -106,11 +108,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);
@@ -145,6 +164,22 @@
 		}
 	    }
 	}
+	catch (FileNotFoundException e) {
+	    // Update systemId in parent stylesheet for error reporting
+	    context.setSystemId(getAttribute("href"));
+
+	    final ErrorMsg msg = 
+		new ErrorMsg(ErrorMsg.FILE_NOT_FOUND_ERR, docToLoad, this);
+	    parser.reportError(Constants.FATAL, msg);
+	}
+	catch (MalformedURLException e) {
+	    // Update systemId in parent stylesheet for error reporting
+	    context.setSystemId(getAttribute("href"));
+
+	    final ErrorMsg msg = 
+		new ErrorMsg(ErrorMsg.FILE_NOT_FOUND_ERR, docToLoad, this);
+	    parser.reportError(Constants.FATAL, msg);
+	}
 	catch (Exception e) {
 	    e.printStackTrace();
 	}
diff --git a/src/org/apache/xalan/xsltc/compiler/LiteralElement.java b/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
index fffa79b..0308584 100644
--- a/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
+++ b/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
@@ -64,11 +64,13 @@
 
 package org.apache.xalan.xsltc.compiler;
 
-import java.util.Hashtable;
-import java.util.Enumeration;
 import java.util.Vector;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Enumeration;
 
 import javax.xml.parsers.*;
+import javax.xml.transform.OutputKeys;
 
 import org.xml.sax.*;
 
@@ -77,10 +79,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 +122,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 +142,7 @@
 		if (old != null) {
 		    if (old.equals(uri))
 			return;
-		    else
+		    else 
 			prefix = stable.generateNamespacePrefix();
 		}
 	    }
@@ -207,7 +210,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 +257,36 @@
      * 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);
 
+	// Determine output type if first literal output is html
+	if (_name.toString().equalsIgnoreCase("html")) {
+	    final SyntaxTreeNode parent = getParent();
+	    if (parent instanceof Template) {
+		final Template tt = (Template) parent;
+		if (tt.isRootTemplate()) {
+		    final Stylesheet stylesheet = parser.getCurrentStylesheet();
+		    stylesheet.setOutputProperty(OutputKeys.METHOD, "html");
+		}
+	    }
+	}
+
 	// 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 +305,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 +329,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 +339,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 +360,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 +372,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/LiteralExpr.java b/src/org/apache/xalan/xsltc/compiler/LiteralExpr.java
index 93623a9..b169eff 100644
--- a/src/org/apache/xalan/xsltc/compiler/LiteralExpr.java
+++ b/src/org/apache/xalan/xsltc/compiler/LiteralExpr.java
@@ -88,10 +88,7 @@
      */
     public LiteralExpr(String value, String namespace) {
 	_value = value;
-	if (namespace.equals(Constants.EMPTYSTRING))
-	    _namespace = null;
-	else
-	    _namespace = namespace;
+	_namespace = namespace.equals(Constants.EMPTYSTRING) ? null : namespace;
     }
 
     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
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/Output.java b/src/org/apache/xalan/xsltc/compiler/Output.java
index 907b793..7127f28 100644
--- a/src/org/apache/xalan/xsltc/compiler/Output.java
+++ b/src/org/apache/xalan/xsltc/compiler/Output.java
@@ -65,9 +65,11 @@
 package org.apache.xalan.xsltc.compiler;
 
 import java.util.Vector;
+import java.util.Properties;
 import java.util.Enumeration;
 import java.util.StringTokenizer;
 import java.io.OutputStreamWriter;
+import javax.xml.transform.OutputKeys;
 
 import org.apache.bcel.generic.*;
 import org.apache.bcel.classfile.JavaClass;
@@ -96,8 +98,9 @@
     private boolean _disabled = false;
 
     // Some global constants
-    private final static String STRING_SIG = "Ljava/lang/String;";
-    private final static String ONE_DOT_ZERO_STRING = "1.0";
+    private final static String STRING_SIG   = "Ljava/lang/String;";
+    private final static String XML_VERSION  = "1.0";
+    private final static String HTML_VERSION = "4.0";
 
     /**
      * Displays the contents of this element (for debugging)
@@ -124,6 +127,7 @@
      * Scans the attribute list for the xsl:output instruction
      */
     public void parseContents(Parser parser) {
+	final Properties outputProperties = new Properties();
 
 	// Ask the parser if it wants this <xsl:output> element
 	parser.setOutput(this);
@@ -133,25 +137,30 @@
 
 	String attrib = null;
 
-	// Get the output XML version - only version "1.0" should be used
+	// Get the output version
 	_version = getAttribute("version");
-	if ((_version == null) || (_version.equals(Constants.EMPTYSTRING))) {
-	    _version = ONE_DOT_ZERO_STRING;
+	if (_version == null || _version.equals(Constants.EMPTYSTRING)) {
+	    _version = null;
 	}
-	if (!_version.equals(ONE_DOT_ZERO_STRING)) {
-	    ErrorMsg msg = new ErrorMsg(ErrorMsg.OUTPUT_VERSION_ERR, this);
-	    parser.reportError(Constants.WARNING, msg);
+	else {
+	    outputProperties.setProperty(OutputKeys.VERSION, _version);
 	}
 
 	// Get the output method - "xml", "html", "text" or <qname>
 	_method = getAttribute("method");
-	if (_method.equals(Constants.EMPTYSTRING)) _method = null;
-	if (_method != null) _method = _method.toLowerCase();
+	if (_method.equals(Constants.EMPTYSTRING)) {
+	    _method = null;
+	}
+	if (_method != null) {
+	    _method = _method.toLowerCase();
+	    outputProperties.setProperty(OutputKeys.METHOD, _method);
+	}
 
 	// Get the output encoding - any value accepted here
 	_encoding = getAttribute("encoding");
-	if (_encoding.equals(Constants.EMPTYSTRING))
+	if (_encoding.equals(Constants.EMPTYSTRING)) {
 	    _encoding = null;
+	}
 	else {
 	    try {
 		OutputStreamWriter writer =
@@ -162,42 +171,96 @@
 					    _encoding, this);
 		parser.reportError(Constants.WARNING, msg);
 	    }
+	    outputProperties.setProperty(OutputKeys.ENCODING, _encoding);
 	}
 
 	// Should the XML header be omitted - translate to true/false
 	attrib = getAttribute("omit-xml-declaration");
-	if ((attrib != null) && (attrib.equals("yes"))) _omitHeader = true;
+	if (attrib != null && !attrib.equals(Constants.EMPTYSTRING)) {
+	    if (attrib.equals("yes")) {
+		_omitHeader = true;
+	    }
+	    outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, attrib);
+	}
 
 	// Add 'standalone' decaration to output - use text as is
 	_standalone = getAttribute("standalone");
-	if (_standalone.equals(Constants.EMPTYSTRING)) _standalone = null;
+	if (_standalone.equals(Constants.EMPTYSTRING)) {
+	    _standalone = null;
+	}
+	else {
+	    outputProperties.setProperty(OutputKeys.STANDALONE, _standalone);
+	}
 
 	// Get system/public identifiers for output DOCTYPE declaration
 	_doctypeSystem = getAttribute("doctype-system");
-	if (_doctypeSystem.equals(Constants.EMPTYSTRING)) _doctypeSystem = null;
+	if (_doctypeSystem.equals(Constants.EMPTYSTRING)) {
+	    _doctypeSystem = null;
+	}
+	else {
+	    outputProperties.setProperty(OutputKeys.DOCTYPE_SYSTEM, _doctypeSystem);
+	}
+
+
 	_doctypePublic = getAttribute("doctype-public");
-	if (_doctypePublic.equals(Constants.EMPTYSTRING)) _doctypePublic = null;
+	if (_doctypePublic.equals(Constants.EMPTYSTRING)) {
+	    _doctypePublic = null;
+	}
+	else {
+	    outputProperties.setProperty(OutputKeys.DOCTYPE_PUBLIC, _doctypePublic);
+	}
 
 	// Names the elements of whose text contents should be output as CDATA
 	_cdata = getAttribute("cdata-section-elements");
-	if ((_cdata != null) && (_cdata.equals(Constants.EMPTYSTRING)))
+	if (_cdata != null && _cdata.equals(Constants.EMPTYSTRING)) {
 	    _cdata = null;
+	}
+	else {
+	    outputProperties.setProperty(OutputKeys.CDATA_SECTION_ELEMENTS, _cdata);
+	}
 
 	// Get the indent setting - only has effect for xml and html output
 	attrib = getAttribute("indent");
-	if ((attrib != null) && (!attrib.equals(EMPTYSTRING))) {
-	    if (attrib.equals("yes")) _indent = true;
+	if (attrib != null && !attrib.equals(EMPTYSTRING)) {
+	    if (attrib.equals("yes")) {
+		_indent = true;
+	    }
+	    outputProperties.setProperty(OutputKeys.INDENT, attrib);
 	}
-	else if ((_method != null) && (_method.equals("html"))) {
+
+	else if (_method != null && _method.equals("html")) {
 	    _indent = true;
 	}
 
-	// Get the MIME type for the output file - we don't do anythign with it,
-	// but our client may use it to specify a data transport type, etc.
+	// Get the MIME type for the output file
 	_mediaType = getAttribute("media-type");
-	if (_mediaType.equals(Constants.EMPTYSTRING)) _mediaType = null;
+	if (_mediaType.equals(Constants.EMPTYSTRING)) {
+	    _mediaType = null;
+	}
+	else {
+	    outputProperties.setProperty(OutputKeys.MEDIA_TYPE, _mediaType);
+	}
 
-	// parseChildren(parser); - the element is always empty
+	// Implied properties
+	if (_method != null) {
+	    if (_method.equals("html")) {
+		if (_version == null) {
+		    _version = HTML_VERSION;
+		}
+		if (_mediaType == null) {
+		    _mediaType = "text/html";
+		}
+		_indent = true;
+	    }
+	    else if (_method.equals("text")) {
+		if (_mediaType == null) {
+		    _mediaType = "text/plain";
+		}
+	    }
+	}
+
+	// Set output properties in current stylesheet
+	parser.getCurrentStylesheet().setOutputProperties(outputProperties);
     }
 
     /**
@@ -216,7 +279,7 @@
         il.append(classGen.loadTranslet());
 
 	// Only update _version field if set and different from default
-	if ((_version != null) && (!_version.equals(ONE_DOT_ZERO_STRING))) {
+	if (_version != null && !_version.equals(XML_VERSION)) {
 	    field = cpg.addFieldref(TRANSLET_CLASS, "_version", STRING_SIG);
 	    il.append(DUP);
 	    il.append(new PUSH(cpg, _version));
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..6e71ffe 100644
--- a/src/org/apache/xalan/xsltc/compiler/Parser.java
+++ b/src/org/apache/xalan/xsltc/compiler/Parser.java
@@ -71,6 +71,7 @@
 import java.util.Vector;
 import java.util.Hashtable;
 import java.util.Dictionary;
+import java.util.Properties;
 import java.util.Enumeration;
 import java.util.StringTokenizer;
 import java.util.Stack;
@@ -99,6 +100,7 @@
     private Vector _warnings;         // Contains all compilation errors
 
     private Hashtable   _instructionClasses; // Maps instructions to classes
+    private Hashtable   _instructionAttrs;;  // reqd and opt attrs 
     private Hashtable   _qNames;
     private Hashtable   _namespaces;
     private QName       _useAttributeSets;
@@ -126,6 +128,7 @@
 	_qNames              = new Hashtable(512);
 	_namespaces          = new Hashtable();
 	_instructionClasses  = new Hashtable();
+	_instructionAttrs    = new Hashtable();
 	_variableScope       = new Hashtable();
 	_template            = null;
 	_errors              = new Vector();
@@ -136,6 +139,7 @@
 	_currentImportPrecedence = 1;
 	
 	initStdClasses();
+	initInstructionAttrs();
 	initExtClasses();
 	initSymbolTable();
 	
@@ -166,6 +170,10 @@
 	return _output;
     }
 
+    public Properties getOutputProperties() {
+	return getTopLevelStylesheet().getOutputProperties();
+    }
+
     public void addVariable(Variable var) {
 	addVariableOrParam(var);
     }
@@ -265,6 +273,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 +287,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);
@@ -567,6 +579,71 @@
 	return(external);
     }
 
+    private void initAttrTable(String elementName, String[] attrs) {
+	_instructionAttrs.put(getQName(XSLT_URI, XSL, elementName),
+				attrs);
+    }
+
+    private void initInstructionAttrs() {
+	initAttrTable("template", 
+	    new String[] {"match", "name", "priority", "mode"});
+	initAttrTable("stylesheet", 
+	    new String[] {"id", "version", "extension-element-prefixes",
+		"exclude-result-prefixes"});
+	initAttrTable("transform",
+	    new String[] {"id", "version", "extension-element-prefixes",
+		"exclude-result-prefixes"});
+	initAttrTable("text", new String[] {"disable-output-escaping"}); 
+	initAttrTable("if", new String[] {"test"}); 
+	initAttrTable("choose", new String[] {}); 
+	initAttrTable("when", new String[] {"test"}); 
+	initAttrTable("otherwise", new String[] {}); 
+	initAttrTable("for-each", new String[] {"select"}); 
+	initAttrTable("message", new String[] {"terminate"}); 
+	initAttrTable("number", 
+	    new String[] {"level", "count", "from", "value", "format", "lang",
+		"letter-value", "grouping-separator", "grouping-size"});
+		initAttrTable("comment", new String[] {}); 
+	initAttrTable("copy", new String[] {"use-attribute-sets"}); 
+	initAttrTable("copy-of", new String[] {"select"}); 
+	initAttrTable("param", new String[] {"name", "select"}); 
+	initAttrTable("with-param", new String[] {"name", "select"}); 
+	initAttrTable("variable", new String[] {"name", "select"}); 
+	initAttrTable("output", 
+	    new String[] {"method", "version", "encoding", 
+		"omit-xml-declaration", "standalone", "doctype-public",
+		"doctype-system", "cdata-section-elements", "indent",
+		"media-type"}); 
+	initAttrTable("sort", 
+	   new String[] {"select", "order", "case-order", "lang", "data-type"});
+	initAttrTable("key", new String[] {"name", "match", "use"}); 
+	initAttrTable("fallback", new String[] {}); 
+	initAttrTable("attribute", new String[] {"name", "namespace"}); 
+	initAttrTable("attribute-set", 
+	    new String[] {"name", "use-attribute-sets"}); 
+	initAttrTable("value-of", 
+	    new String[] {"select", "disable-output-escaping"}); 
+	initAttrTable("element", 
+	    new String[] {"name", "namespace", "use-attribute-sets"}); 
+	initAttrTable("call-template", new String[] {"name"}); 
+	initAttrTable("apply-templates", new String[] {"select", "mode"}); 
+	initAttrTable("apply-imports", new String[] {}); 
+	initAttrTable("decimal-format", 
+	    new String[] {"name", "decimal-separator", "grouping-separator",
+		"infinity", "minus-sign", "NaN", "percent", "per-mille",
+		"zero-digit", "digit", "pattern-separator"}); 
+	initAttrTable("import", new String[] {"href"}); 
+	initAttrTable("include", new String[] {"href"}); 
+	initAttrTable("strip-space", new String[] {"elements"}); 
+	initAttrTable("preserve-space", new String[] {"elements"}); 
+	initAttrTable("processing-instruction", new String[] {"name"}); 
+	initAttrTable("namespace-alias", 
+	   new String[] {"stylesheet-prefix", "result-prefix"}); 
+    }
+
+
+
+
     /**
      * Initialize the _instructionClasses Hashtable, which maps XSL element
      * names to Java classes in this package.
@@ -614,8 +691,8 @@
 				COMPILER_PACKAGE + '.' + className);
     }
 
-    public boolean elementSupported(QName qname) {
-	return(_instructionClasses.get(qname) != null);
+    public boolean elementSupported(String namespace, String localName) {
+	return(_instructionClasses.get(getQName(namespace, XSL, localName)) != null);
     }
 
     public boolean functionSupported(String fname) {
@@ -660,6 +737,7 @@
 	MethodType B_V  = new MethodType(Type.Boolean, Type.Void);
 	MethodType B_B  = new MethodType(Type.Boolean, Type.Boolean);
 	MethodType B_S  = new MethodType(Type.Boolean, Type.String);
+	MethodType D_T  = new MethodType(Type.NodeSet, Type.ResultTree);
 	MethodType R_RR = new MethodType(Type.Real, Type.Real, Type.Real);
 	MethodType I_II = new MethodType(Type.Int, Type.Int, Type.Int);
 	MethodType B_RR = new MethodType(Type.Boolean, Type.Real, Type.Real);
@@ -744,6 +822,9 @@
 	_symbolTable.addPrimop("normalize-space", S_S);
 	_symbolTable.addPrimop("system-property", S_S);
 
+	// Extensions
+	_symbolTable.addPrimop("nodeset", D_T);
+
 	// Operators +, -, *, /, % defined on real types.
 	_symbolTable.addPrimop("+", R_RR);	
 	_symbolTable.addPrimop("-", R_RR);	
@@ -814,10 +895,16 @@
      * until we have received all child elements of an unsupported element to
      * see if any <xsl:fallback> elements exist.
      */
-    public SyntaxTreeNode makeInstance(String uri, String prefix, String local){
+
+    private boolean versionIsOne = true;
+
+    public SyntaxTreeNode makeInstance(String uri, String prefix, 
+	String local, Attributes attributes)
+    {
+	boolean isStylesheet = false;
+	SyntaxTreeNode node = null;
 	QName  qname = getQName(uri, prefix, local);
 	String className = (String)_instructionClasses.get(qname);
-	SyntaxTreeNode node = null;
 
 	if (className != null) {
 	    try {
@@ -825,10 +912,41 @@
 		node = (SyntaxTreeNode)clazz.newInstance();
 		node.setQName(qname);
 		node.setParser(this);
-		if (_locator != null)
+		if (_locator != null){
 		    node.setLineNumber(_locator.getLineNumber());
+		}
 		if (node instanceof Stylesheet) {
-		    _xsltc.setStylesheet((Stylesheet)node);
+		    isStylesheet = true;
+		    _xsltc.setStylesheet((Stylesheet) node);
+		}
+
+			// Check for illegal attributes
+		String[] legal = (String[]) _instructionAttrs.get(qname);
+	        if (versionIsOne && legal != null) {
+		    int j;
+		    final int n = attributes.getLength();
+
+		    for (int i = 0; i < n; i++) {
+			final String attrQName = attributes.getQName(i);
+
+			if (isStylesheet && attrQName.equals("version")) {
+			    versionIsOne = attributes.getValue(i).equals("1.0");
+			}
+
+			if (attrQName.startsWith("xml")) continue;
+
+			for (j = 0; j < legal.length; j++) {
+			    if (attrQName.equalsIgnoreCase(legal[j])) {
+				break;
+			    }	
+			}
+			if (j == legal.length) {
+			    final ErrorMsg err = 
+			        new ErrorMsg(ErrorMsg.ILLEGAL_ATTRIBUTE_ERR, 
+					     attrQName, node);
+			    reportError(WARNING, err);
+		        }
+		    }
 		}
 	    }
 	    catch (ClassNotFoundException e) {
@@ -1072,7 +1190,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);
     }
 
@@ -1091,13 +1211,10 @@
 			     String qname, Attributes attributes) 
 	throws SAXException {
 	final int col = qname.lastIndexOf(':');
-	final String prefix;
-	if (col == -1)
-	    prefix = null;
-	else
-	    prefix = qname.substring(0, col);
+	final String prefix = (col == -1) ? null : qname.substring(0, col);
 
-	SyntaxTreeNode element = makeInstance(uri, prefix, localname);
+	SyntaxTreeNode element = makeInstance(uri, prefix, 
+			localname, attributes);
 	if (element == null) {
 	    ErrorMsg err = new ErrorMsg(ErrorMsg.ELEMENT_PARSE_ERR,
 					prefix+':'+localname);
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..9b04d02 100644
--- a/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
+++ b/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
@@ -66,6 +66,7 @@
 
 import java.util.Vector;
 import java.util.Hashtable;
+import java.util.Properties;
 import java.util.Enumeration;
 import java.util.StringTokenizer;
 import java.util.Iterator;
@@ -117,6 +118,7 @@
     private int _importPrecedence = 1;
     private Mode _defaultMode;
     private boolean _multiDocument = false;
+    private boolean _callsNodeset = false;
 
     // All named key elements (needed by Key/IdPattern)
     private Hashtable _keys = new Hashtable();
@@ -131,6 +133,8 @@
 
     private boolean _forwardReference = false;
 
+    private Properties _outputProperties = null;
+
     public void setForwardReference() {
 	_forwardReference = true;
     }
@@ -147,6 +151,21 @@
 	_simplified = true;
     }
     
+    public void setOutputProperty(String key, String value) {
+	if (_outputProperties == null) {
+	    _outputProperties = new Properties();
+	}
+	_outputProperties.setProperty(key, value);
+    }
+
+    public void setOutputProperties(Properties props) {
+	_outputProperties = props;
+    }
+
+    public Properties getOutputProperties() {
+	return _outputProperties;
+    }
+
     public void setMultiDocument(boolean flag) {	
 	_multiDocument = flag;
     }
@@ -155,6 +174,15 @@
 	return _multiDocument;
     }
 
+    public void setCallsNodeset(boolean flag) {
+	if (flag) setMultiDocument(flag);
+	_callsNodeset = flag;
+    }
+
+    public boolean callsNodeset() {
+	return _callsNodeset;
+    }
+
     public void numberFormattingUsed() {
 	_numberFormattingUsed = true;
     }
@@ -284,7 +312,6 @@
 	super.addPrefixMapping(prefix, uri);
     }
 
-
     /**
      * Store extension URIs
      */
@@ -308,8 +335,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);
@@ -692,12 +721,31 @@
 	return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V");
     }
 
-
+    /**
+     * This method returns a vector with variables in the order in which
+     * they are to be compiled. The order is determined by the dependencies
+     * between them. The first step is to close the input vector under
+     * the dependence relation (this is usually needed when variables are
+     * defined inside other variables in a RTF).
+     */
     private Vector resolveReferences(Vector input) {
+
+	// Make sure that the vector 'input' is closed
+	for (int i = 0; i < input.size(); i++) {
+	    final VariableBase var = (VariableBase) input.elementAt(i);
+	    final Vector dep  = var.getDependencies();
+	    final int depSize = (dep != null) ? dep.size() : 0;
+
+	    for (int j = 0; j < depSize; j++) {
+		final VariableBase depVar = (VariableBase) dep.elementAt(j);
+		if (!input.contains(depVar)) {
+		    input.addElement(depVar);
+		}
+	    }
+	}
+
 	Vector result = new Vector();
-
 	int zeroDep = 0;
-
 	while (input.size() > 0) {
 	    boolean changed = false;
 	    for (int i = 0; i < input.size(); ) {
@@ -717,6 +765,8 @@
 		    i++;
 		}
 	    }
+
+
 	    // If nothing was changed in this pass then we have a circular ref
 	    if (!changed) {
 		ErrorMsg err = new ErrorMsg(ErrorMsg.CIRCULAR_VARIABLE_ERR,
@@ -878,6 +928,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 +958,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..322781c 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);
     }
 
     /**
@@ -554,10 +552,11 @@
      * @param methodGen BCEL Java method generator
      */
     protected void compileResultTree(ClassGenerator classGen,
-				     MethodGenerator methodGen) {
-
+				     MethodGenerator methodGen) 
+    {
 	final ConstantPoolGen cpg = classGen.getConstantPool();
 	final InstructionList il = methodGen.getInstructionList();
+	final Stylesheet stylesheet = classGen.getStylesheet();
 
 	// Save the current handler base on the stack
 	il.append(methodGen.loadHandler());
@@ -602,13 +601,42 @@
 	    il.append(new NEW(cpg.addClass(DOM_ADAPTER_CLASS)));
 	    il.append(new DUP_X1());
 	    il.append(SWAP);
-	    // Give the DOM adapter an empty type mapping to start with.
-	    // Type mapping is expensive and will only be done when casting
-	    // a result tree fragment to a node-set.
-	    il.append(new ICONST(0));
-	    il.append(new ANEWARRAY(cpg.addClass(STRING)));
-	    il.append(DUP);
-	    il.append(new INVOKESPECIAL(index)); // leave DOMAdapter on stack
+
+	    /*
+	     * Give the DOM adapter an empty type mapping if the nodeset
+	     * extension function is never called.
+	     */
+	    if (!stylesheet.callsNodeset()) {
+		il.append(new ICONST(0));
+		il.append(new ANEWARRAY(cpg.addClass(STRING)));
+		il.append(DUP);
+		il.append(new INVOKESPECIAL(index));
+	    }
+	    else {
+		// Push name arrays on the stack
+		il.append(ALOAD_0);
+		il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
+					   NAMES_INDEX,
+					   NAMES_INDEX_SIG))); 
+		il.append(ALOAD_0);
+		il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
+					   NAMESPACE_INDEX,
+					   NAMESPACE_INDEX_SIG)));
+
+		// Initialized DOM adapter
+		il.append(new INVOKESPECIAL(index));
+
+		// Add DOM adapter to MultiDOM class by calling addDOMAdapter()
+		il.append(DUP);
+		il.append(methodGen.loadDOM());
+		il.append(new CHECKCAST(cpg.addClass(classGen.getDOMClass())));
+		il.append(SWAP);
+		index = cpg.addMethodref(MULTI_DOM_CLASS,
+					 "addDOMAdapter",
+					 "(" + DOM_ADAPTER_SIG + ")I");
+		il.append(new INVOKEVIRTUAL(index));
+		il.append(POP);		// ignore mask returned by addDOMAdapter
+	    }
 	}
 
 	// Restore old handler base from stack
diff --git a/src/org/apache/xalan/xsltc/compiler/Template.java b/src/org/apache/xalan/xsltc/compiler/Template.java
index 6191e9e..a02faac 100644
--- a/src/org/apache/xalan/xsltc/compiler/Template.java
+++ b/src/org/apache/xalan/xsltc/compiler/Template.java
@@ -132,6 +132,11 @@
 	return _name != null;
     }
 
+    public boolean isRootTemplate() {
+	final String match = getAttribute("match");
+	return (match != null && match.equals("/"));
+    }
+
     public Pattern getPattern() {
 	return _pattern;
     }
diff --git a/src/org/apache/xalan/xsltc/compiler/XSLTC.java b/src/org/apache/xalan/xsltc/compiler/XSLTC.java
index 4baf1ed..a5676d5 100644
--- a/src/org/apache/xalan/xsltc/compiler/XSLTC.java
+++ b/src/org/apache/xalan/xsltc/compiler/XSLTC.java
@@ -72,6 +72,7 @@
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Properties;
 import java.util.Enumeration;
 import java.util.StringTokenizer;
 import java.util.Date;
@@ -139,6 +140,7 @@
     private int     _outputType = FILE_OUTPUT; // by default
 
     private Vector  _classes;
+    private boolean _callsNodeset = false;
     private boolean _multiDocument = false;
 
     /**
@@ -163,6 +165,13 @@
     }
 
     /**
+     * Only for user by the internal TrAX implementation.
+     */
+    public Properties getOutputProperties() {
+	return _parser.getOutputProperties();
+    }
+
+    /**
      * Initializes the compiler to compile a new stylesheet
      */
     public void init() {
@@ -317,6 +326,7 @@
 	    }
 	    // Generate the bytecodes and output the translet class(es)
 	    if ((!_parser.errorsFound()) && (_stylesheet != null)) {
+		_stylesheet.setCallsNodeset(_callsNodeset);
 		_stylesheet.setMultiDocument(_multiDocument);
 		_stylesheet.translate();
 	    }
@@ -435,7 +445,6 @@
 	_parser.printWarnings();
     }
 
-
     /**
      * This method is called by the XPathParser when it encounters a call
      * to the document() function. Affects the DOM used by the translet.
@@ -449,6 +458,19 @@
     }
 
     /**
+     * This method is called by the XPathParser when it encounters a call
+     * to the nodeset() extension function. Implies multi document.
+     */
+    protected void setCallsNodeset(boolean flag) {
+	if (flag) setMultiDocument(flag);
+	_callsNodeset = flag;
+    }
+
+    public boolean callsNodeset() {
+	return _callsNodeset;
+    }
+
+    /**
      * Set the class name for the generated translet. This class name is
      * overridden if multiple stylesheets are compiled in one go using the
      * compile(Vector urls) method.
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/ErrorMessages.java b/src/org/apache/xalan/xsltc/compiler/util/ErrorMessages.java
index 5c5b243..1ff59cd 100644
--- a/src/org/apache/xalan/xsltc/compiler/util/ErrorMessages.java
+++ b/src/org/apache/xalan/xsltc/compiler/util/ErrorMessages.java
@@ -220,8 +220,8 @@
 	"The -i option must be used with the -o option.",
 	// COMPILE_USAGE_STR
 	"Usage:\n" + 
-	"   xsltc [-o <output>] [-d <directory>] [-j <jarfile>]\n"+
-	"         [-p <package name>] [-x] [-s] [-u] <stylesheet>|-i\n\n"+
+	"   java org.apache.xalan.xsltc.cmdline.Compile [-o <output>] [-d <directory>] [-j <jarfile>]\n"+
+	"         [-p <package name>] [-x] [-s] [-u] { <stylesheet> | -i }\n\n"+
 	"   Where <output> is the name to give the the generated translet.\n"+
 	"         <stylesheet> is one or more stylesheet file names, or if\n"+
 	"         the -u options is specified, one or more stylesheet URLs.\n"+
@@ -235,8 +235,8 @@
 	"         The -s option disables calling System.exit.",
 	// TRANSFORM_USAGE_STR
 	"Usage: \n" +
-	"   xslt  [-j <jarfile>] {-u <document_url> | <document>} <class>\n"+
-	"         [<name1>=<value1> ...]\n\n" +
+	"   java org.apache.xalan.xsltc.cmdline.Transform [-j <jarfile>] [-x] [-s]\n" +
+	"         {-u <document_url> | <document>} <class> [<param1>=<value1> ...]\n" +
 	"   Where <document> is the xml document to be transformed, or\n" +
 	"         <document_url> is a url for the xml document,\n" +
 	"         <class> is the translet class which is either in\n" +
diff --git a/src/org/apache/xalan/xsltc/compiler/util/MethodGenerator.java b/src/org/apache/xalan/xsltc/compiler/util/MethodGenerator.java
index a0e5fc8..45b42a0 100644
--- a/src/org/apache/xalan/xsltc/compiler/util/MethodGenerator.java
+++ b/src/org/apache/xalan/xsltc/compiler/util/MethodGenerator.java
@@ -103,6 +103,7 @@
     private final Instruction _nextNode;
 
     private SlotAllocator _slotAllocator;
+    private boolean _allocatorInit = false;
     
     public MethodGenerator(int access_flags, Type return_type,
 			   Type[] arg_types, String[] arg_names,
@@ -173,17 +174,26 @@
 	
 	_slotAllocator = new SlotAllocator();
 	_slotAllocator.initialize(getLocalVariables());
+	_allocatorInit = true;
     }
 
+    /**
+     * Allocates a local variable. If the slot allocator has already been
+     * initialized, then call addLocalVariable2() so that the new variable
+     * is known to the allocator. Failing to do this may cause the allocator 
+     * to return a slot that is already in use.
+     */
     public LocalVariableGen addLocalVariable(String name, Type type,
 					     InstructionHandle start,
-					     InstructionHandle end) {
-	
-	return super.addLocalVariable(name, type, start, end);
+					     InstructionHandle end) 
+    {
+	return (_allocatorInit) ? addLocalVariable2(name, type, start) 
+	    : super.addLocalVariable(name, type, start, end);
     }
     
     public LocalVariableGen addLocalVariable2(String name, Type type,
-					      InstructionHandle start) {
+					      InstructionHandle start) 
+    {
 	return super.addLocalVariable(name, type,
 				      _slotAllocator.allocateSlot(type),
 				      start, null);
diff --git a/src/org/apache/xalan/xsltc/compiler/util/ReferenceType.java b/src/org/apache/xalan/xsltc/compiler/util/ReferenceType.java
index 8d56714..b04a7f8 100644
--- a/src/org/apache/xalan/xsltc/compiler/util/ReferenceType.java
+++ b/src/org/apache/xalan/xsltc/compiler/util/ReferenceType.java
@@ -113,6 +113,9 @@
 	else if (type == Type.Node) {
 	    translateTo(classGen, methodGen, (NodeType) type);
 	}
+	else if (type == Type.ResultTree) {
+	    translateTo(classGen, methodGen, (ResultTreeType) type);
+	}
 	else {
 	    ErrorMsg err = new ErrorMsg(ErrorMsg.INTERNAL_ERR, type.toString());
 	    classGen.getParser().reportError(Constants.FATAL, err);
@@ -211,6 +214,20 @@
     }
 
     /**
+     * Casts a reference into a ResultTree.
+     *
+     * @see	org.apache.xalan.xsltc.compiler.util.Type#translateTo
+     */
+    public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
+			    ResultTreeType type) {
+	final ConstantPoolGen cpg = classGen.getConstantPool();
+	final InstructionList il = methodGen.getInstructionList();
+	int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToResultTree", 
+				     "(" + OBJECT_SIG + ")" + DOM_INTF_SIG);
+	il.append(new INVOKESTATIC(index));
+    }
+
+    /**
      * Expects a reference on the stack and translates it to a non-synthesized
      * boolean. It does not push a 0 or a 1 but instead returns branchhandle 
      * list to be appended to the false list.
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/compiler/xpath.cup b/src/org/apache/xalan/xsltc/compiler/xpath.cup
index 31a8a68..a4f1e85 100644
--- a/src/org/apache/xalan/xsltc/compiler/xpath.cup
+++ b/src/org/apache/xalan/xsltc/compiler/xpath.cup
@@ -119,6 +119,10 @@
           _xsltc.setMultiDocument(flag);
     }
 
+    public void setCallsNodeset(boolean flag) {
+          _xsltc.setCallsNodeset(flag);
+    }
+
     public int findNodeType(int axis, Object test) {
 
 	if (test == null) {  // *
@@ -895,6 +899,11 @@
           else if (fname == parser.getQName("namespace-uri")) {
             RESULT = new NamespaceUriCall(fname, argl);
 	  }
+	  // Special case for extension function nodeset()
+          else if (fname.getLocalPart().equals("nodeset")) {
+	    parser.setCallsNodeset(true);  // implies MultiDOM
+            RESULT = new FunctionCall(fname, argl);
+	  }
           else {
             RESULT = new FunctionCall(fname, argl);
 	  }
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..e0cc9bf 100644
--- a/src/org/apache/xalan/xsltc/dom/DOMAdapter.java
+++ b/src/org/apache/xalan/xsltc/dom/DOMAdapter.java
@@ -80,6 +80,8 @@
     private short[] _NSreverse;
 
     private StripFilter _filter = null;
+
+    private int _multiDOMMask;
     
     public DOMAdapter(DOMImpl dom,
 		      String[] namesArray,
@@ -111,6 +113,14 @@
 	return _domImpl.getTreeString();
     }
     
+    public int getMultiDOMMask() {
+	return _multiDOMMask;
+    }
+
+    public void setMultiDOMMask(int mask) {
+	_multiDOMMask = mask;
+    }
+
     public NodeIterator getChildren(final int node) {
 	NodeIterator iterator = _domImpl.getChildren(node);
 	if (_filter == null) {
@@ -139,8 +149,9 @@
 
     public NodeIterator getAxisIterator(final int axis) {
 	NodeIterator iterator = _domImpl.getAxisIterator(axis);
-	if (_filter != null)
+	if (_filter != null) {
 	    iterator = _domImpl.strippingIterator(iterator,_mapping,_filter);
+	}
 	return(iterator);
     }
     
@@ -278,4 +289,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..8721aab 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,8 +137,12 @@
     // 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;
+    private String    _documentURI = null;
+    static private int _documentURIIndex = 0;
 
     // Support for access/navigation through org.w3c.dom API
     private Node[] _nodes;
@@ -159,11 +164,11 @@
      * Returns the origin of the document from which the tree was built
      */
     public String getDocumentURI() {
-	return(_documentURI);
+	return (_documentURI != null) ? _documentURI : "rtf" + _documentURIIndex++;
     }
 
     public String getDocumentURI(int node) {
-	return(_documentURI);
+	return getDocumentURI();
     }
 
     public void setupMapping(String[] names, String[] namespaces) {
@@ -171,6 +176,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 +1089,7 @@
 		while ((_ns == DOM.NULL) && (_node != DOM.NULL)) {
 		    _node = _parent[_node];
 		    _ns = _lengthOrAttr[_node];
+
 		    while ((_ns != DOM.NULL) && (_type[_ns] != NAMESPACE)) {
 			_ns = _nextSibling[_ns];
 		    }
@@ -1482,7 +1519,9 @@
 
 	public int next() {
 	    while (++_node < _limit) {
-		if (_type[_node] > TEXT) return(returnNode(_node));
+		if (_type[_node] > TEXT) {
+		    return(returnNode(_node));
+		}
 	    } 
 	    return(NULL);
 	}
@@ -1980,6 +2019,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 +2202,13 @@
 
 	out.writeObject(_whitespace);
 
+	if (_dontEscape != null) {
+	    out.writeObject(_dontEscape);
+	}
+	else {
+	    out.writeObject(new BitArray(0));
+	}
+
 	out.flush();
     }
 
@@ -2190,6 +2237,11 @@
 
 	_whitespace    = (BitArray)in.readObject();
 
+	_dontEscape    = (BitArray)in.readObject();
+	if (_dontEscape.size() == 0) {
+	    _dontEscape = null;
+        }
+
 	_types         = setupMapping(_namesArray);
     }
 
@@ -2614,9 +2666,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 +2694,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 +2761,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 +2968,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 +3027,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 +3149,6 @@
 	 */
 	private short makeElementNode(String uri, String localname)
 	    throws SAXException {
-	    
 	    final String name;
 	    if (uri != EMPTYSTRING)
 		name = uri + ':' + localname;
@@ -3170,6 +3242,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 +3261,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 +3298,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 +3362,9 @@
 	    }
 	    System.arraycopy(ch, start, _text, _currentOffset, length);
 	    _currentOffset += length;
+
+	    _disableEscaping = !_escaping;	
+
 	}
 
 	/**
@@ -3295,7 +3380,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 +3459,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 +3607,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 +3693,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 +3767,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..42f9f19 100644
--- a/src/org/apache/xalan/xsltc/dom/MultiDOM.java
+++ b/src/org/apache/xalan/xsltc/dom/MultiDOM.java
@@ -114,6 +114,7 @@
 	public NodeIterator setStartNode(final int node) {
 	    _mask = node & SET;
 	    int dom = node >>> 24;
+
 	    // consider caching these
 	    if ((_type == NO_TYPE) || (_type == DOM.ELEMENT)) {
 		_source = _adapters[dom].getAxisIterator(_axis);
@@ -262,8 +263,7 @@
 	// This method only has a function in DOM adapters
     }
 
-    public int addDOMAdapter(DOM dom) {
-
+    public int addDOMAdapter(DOMAdapter dom) {
 	// Add the DOM adapter to the array of DOMs
 	final int domNo = _free++;
 	if (domNo == _size) {
@@ -275,9 +275,11 @@
 
 	// Store reference to document (URI) in hashtable
 	String uri = dom.getDocumentURI(0);
-	_documents.put(uri,new Integer(domNo));
+	_documents.put(uri, new Integer(domNo));
 	
-	return domNo << 24;
+	// Store mask in DOMAdapter
+	dom.setMultiDOMMask(domNo << 24);
+	return (domNo << 24);
     }
     
     public int getDocumentMask(String uri) {
@@ -453,4 +455,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..a623187 100644
--- a/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java
+++ b/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java
@@ -79,6 +79,10 @@
 import org.apache.xalan.xsltc.*;
 import org.apache.xalan.xsltc.DOM;
 import org.apache.xalan.xsltc.NodeIterator;
+import org.apache.xalan.xsltc.dom.Axis;
+import org.apache.xalan.xsltc.dom.DOMAdapter;
+import org.apache.xalan.xsltc.dom.MultiDOM;
+import org.apache.xalan.xsltc.dom.AbsoluteIterator;
 import org.apache.xalan.xsltc.dom.SingletonIterator;
 
 /**
@@ -427,7 +431,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");
 	
@@ -447,6 +451,15 @@
 	    return EMPTYSTRING;
     }
 
+    /**
+     * Implements the nodeset() extension function. 
+     */
+    public static NodeIterator nodesetF(DOM rtf) {
+	final DOMAdapter adapter = (DOMAdapter) rtf;
+	return new SingletonIterator(
+	    DOM.ROOTNODE | adapter.getMultiDOMMask(), true);
+    }
+
     //-- Begin utility functions
 
     private static boolean isWhiteSpace(char ch) {
@@ -891,28 +904,31 @@
      * obj is an instanceof Node then create a singleton iterator.
      */
     public static NodeIterator referenceToNodeSet(Object obj) {
-	try {
-	    // Convert var/param -> node
-	    if (obj instanceof Node) {
-		return(new SingletonIterator(((Node)obj).node));
-	    }
-	    // Convert var/param -> node-set
-	    else if (obj instanceof NodeIterator) {
-		return(((NodeIterator)obj).cloneIterator());
-	    }
-	    // Convert var/param -> result-tree fragment
-	    else if (obj instanceof DOM) {
-		DOM dom = (DOM)obj;
-		return(dom.getIterator());
-	    }
-	    else {
-		final String className = obj.getClass().getName();
-		runTimeError(DATA_CONVERSION_ERR, "reference", className);
-		return null;
-	    }
+	// Convert var/param -> node
+	if (obj instanceof Node) {
+	    return(new SingletonIterator(((Node)obj).node));
 	}
-	catch (ClassCastException e) {
-	    runTimeError(DATA_CONVERSION_ERR, "reference", "node-set");
+	// Convert var/param -> node-set
+	else if (obj instanceof NodeIterator) {
+	    return(((NodeIterator)obj).cloneIterator());
+	}
+	else {
+	    final String className = obj.getClass().getName();
+	    runTimeError(DATA_CONVERSION_ERR, "reference", className);
+	    return null;
+	}
+    }
+
+    /**
+     * Utility function used to convert references to DOMs. 
+     */
+    public static DOM referenceToResultTree(Object obj) {
+	try {
+	    return ((DOM) obj);
+	}
+	catch (IllegalArgumentException e) {
+	    final String className = obj.getClass().getName();
+	    runTimeError(DATA_CONVERSION_ERR, "reference", className);
 	    return null;
 	}
     }
@@ -960,6 +976,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..22eb12c 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
@@ -96,12 +97,11 @@
     private boolean   _startTagOpen = false;
     private boolean   _headTagOpen = false;
     private boolean   _cdataTagOpen = false;
+    private boolean   _is8859Encoded = false;
 
     // 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 +124,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;
@@ -179,6 +179,7 @@
         _saxHandler = handler;
         init();
 	_encoding = encoding;
+	_is8859Encoded = _encoding.equalsIgnoreCase("iso-8859-1");	
     }
 
     /**
@@ -194,6 +195,7 @@
 	_lexHandler = lex;
         init();
 	_encoding = encoding;
+	_is8859Encoded = _encoding.equalsIgnoreCase("iso-8859-1");	
     }
 
     /**
@@ -252,8 +254,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 +266,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) {
@@ -417,17 +402,19 @@
 		// the first CDATA and '>' at the beginning of the next. Other
 		// special characters/sequences are _NOT_ escaped within CDATA.
 		Integer I = (Integer)_cdataStack.peek();
-		if ((I.intValue() == _depth) && (!_cdataTagOpen))
+		if ((I.intValue() == _depth) && (!_cdataTagOpen)) {
 		    startCDATA(ch, off, len);
-		// Output characters escaped if required.
-		else if (_escapeChars)
-		    if (_cdataTagOpen)
+		} 
+		else if (_escapeChars) {
+		    if (_cdataTagOpen) {
 			escapeCDATA(ch, off, len);
-		    else
+		    } else {
 			escapeCharacters(ch, off, len);
-		// Output the chracters as the are if not.
-		else
+		    }
+		} 
+		else {
 		    _saxHandler.characters(ch, off, len);
+		}
 		return;
 
 	    case HTML:
@@ -467,9 +454,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) {
 
@@ -552,9 +537,11 @@
 
 	if (limit > ch.length) limit = ch.length;;
 
+
 	// Step through characters and escape all special characters
 	for (int i = off; i < limit; i++) {
-	    switch (ch[i]) {
+	    char current = ch[i];
+	    switch (current) {
 	    case '&':
 		_saxHandler.characters(ch, offset, i - offset);
 		_saxHandler.characters(AMP, 0, AMP_length);
@@ -576,9 +563,9 @@
 		offset = i + 1;
 		break;
 	    default:
-		// Escape all characters not in the basic ASCII character set
-		// to simple (hexadecimal) character references
-		if (ch[i] > '\u007F') {
+		if ( (current >= '\u007F' && current < '\u00A0') ||
+		     (_is8859Encoded && (current > '\u00FF')) )
+		{
 		    StringBuffer buf = new StringBuffer(CHAR_ESC_START);
 		    buf.append(Integer.toString((int)ch[i]));
 		    buf.append(';');
@@ -670,6 +657,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 +676,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 +708,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 +762,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 +818,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 +932,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 +944,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 +1012,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 +1029,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 +1046,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..0fcddbb 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,12 +161,13 @@
 	    xsltc.printWarnings();
 
 	    // Check that the transformation went well before returning
+	    final byte[][] bytecodes = xsltc.getBytecodes();
 	    if (bytecodes == null) {
 		xsltc.printErrors();
 		return null;
 	    }
 
-	    return(new TemplatesImpl(bytecodes, transletName));
+	    return new TemplatesImpl(bytecodes, transletName, getOutputProperties());
 	}
 	catch (CompilerException e) {
 	    return null;
diff --git a/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java b/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java
index e1c099c..0686969 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 
  *
  */
 
@@ -96,6 +97,8 @@
     // and _bytecodes arrays (above).
     private int _transletIndex = -1;
     
+    private Properties _outputProperties;
+
     // Our own private class loader - builds Class definitions from bytecodes
     private class TransletClassLoader extends ClassLoader {
 
@@ -126,9 +129,12 @@
      * The bytecodes for the translet and auxiliary classes, plus the name of
      * the main translet class, must be supplied
      */
-    protected TemplatesImpl(byte[][] bytecodes, String transletName) {
+    protected TemplatesImpl(byte[][] bytecodes, String transletName,
+	Properties outputProperties) 
+    {
 	_bytecodes = bytecodes;
 	_name      = transletName;
+	_outputProperties = outputProperties;
     }
 
     /**
@@ -176,8 +182,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());
 			}
 		    }
 		);
@@ -250,7 +261,7 @@
      */
     public Transformer newTransformer()
 	throws TransformerConfigurationException {
-        return(new TransformerImpl(getTransletInstance()));
+        return new TransformerImpl(getTransletInstance(), _outputProperties);
     }
 
     /**
diff --git a/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java b/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
index 2f2cc9b..6ebfe90 100644
--- a/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
@@ -336,7 +336,8 @@
 	}
 
 	// Create a Transformer object and store for other calls
-	Templates templates = new TemplatesImpl(bytecodes,_defaultTransletName);
+	Templates templates = new TemplatesImpl(bytecodes, 
+	    _defaultTransletName, xsltc.getOutputProperties());
 	_copyTransformer = templates.newTransformer();
 	if (_uriResolver != null) _copyTransformer.setURIResolver(_uriResolver);
 	return(_copyTransformer);
@@ -363,22 +364,20 @@
     /**
      * Pass warning messages from the compiler to the error listener
      */
-    private void passWarningsToListener(Vector messages) {
-	try {
-	    // Nothing to do if there is no registered error listener
-	    if (_errorListener == null) return;
-	    // Nothing to do if there are not warning messages
-	    if (messages == null) return;
-	    // Pass messages to listener, one by one
-	    final int count = messages.size();
-	    for (int pos=0; pos<count; pos++) {
-		String message = messages.elementAt(pos).toString();
-		_errorListener.warning(new TransformerException(message));
-	    }
+    private void passWarningsToListener(Vector messages)  
+	throws TransformerException
+    {
+	if (_errorListener == null || messages == null ) {
+	    return;
 	}
-	catch (TransformerException e) {
-	    // nada
+	// Pass messages to listener, one by one
+	final int count = messages.size();
+	for (int pos = 0; pos < count; pos++) {
+	    String message = messages.elementAt(pos).toString();
+	    _errorListener.error(
+		new TransformerConfigurationException(message));
 	}
+
     }
 
     /**
@@ -474,7 +473,6 @@
      */
     public Templates newTemplates(Source source)
 	throws TransformerConfigurationException {
-
 	// Create and initialize a stylesheet compiler
 	final XSLTC xsltc = new XSLTC();
 	if (_debug) xsltc.setDebug(true);
@@ -499,10 +497,18 @@
 	final String transletName = xsltc.getClassName();
 
 	// Pass compiler warnings to the error listener
-	if (_errorListener != null)
-	    passWarningsToListener(xsltc.getWarnings());
-	else
+	if (_errorListener != this){  
+	    //passWarningsToListener(xsltc.getWarnings());
+	   try {
+		passWarningsToListener(xsltc.getWarnings());
+	    }
+	    catch (TransformerException e) {
+		throw new TransformerConfigurationException(e);
+	    }
+	} 
+	else {
 	    xsltc.printWarnings();
+	}
 
 	// Check that the transformation went well before returning
 	if (bytecodes == null) {
@@ -514,7 +520,8 @@
 	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR);
 	    throw new TransformerConfigurationException(err.toString());
 	}
-	return(new TemplatesImpl(bytecodes, transletName));
+	return new TemplatesImpl(bytecodes, transletName, 
+	    xsltc.getOutputProperties());
     }
 
     /**
@@ -527,7 +534,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..9ff16cd 100644
--- a/src/org/apache/xalan/xsltc/trax/TransformerImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TransformerImpl.java
@@ -118,7 +118,7 @@
 
     private ErrorListener _errorListener = this;
     private URIResolver   _uriResolver = null;
-    private Properties    _properties = null;
+    private Properties    _properties, _propertiesClone;
 
     // Used for default output property settings
     private final static String EMPTY_STRING = "";
@@ -138,9 +138,10 @@
      * Implements JAXP's Transformer constructor
      * Our Transformer objects always need a translet to do the actual work
      */
-    protected TransformerImpl(Translet translet) {
+    protected TransformerImpl(Translet translet, Properties outputProperties) {
 	_translet = (AbstractTranslet)translet;
-	_properties = createOutputProperties();
+	_properties = createOutputProperties(outputProperties);
+	_propertiesClone = (Properties) _properties.clone();
     }
 
     /**
@@ -211,7 +212,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 +410,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 +432,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
@@ -630,17 +643,12 @@
 
     /**
      * Implements JAXP's Transformer.getOutputProperties().
-     * Returns a copy of the output properties for the transformation. This is
-     * a set of layered properties. The first layer contains properties set by
-     * calls to setOutputProperty() and setOutputProperties() on this class,
-     * and the output settings defined in the stylesheet's <xsl:output>
-     * element makes up the second level, while the default XSLT output
-     * settings are returned on the third level.
+     * Returns a copy of the output properties for the transformation. 
      *
      * @return Properties in effect for this Transformer
      */
     public Properties getOutputProperties() {
-	return(_properties);
+	return (Properties) _properties.clone();
     }
 
     /**
@@ -658,7 +666,7 @@
 	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
 	    throw new IllegalArgumentException(err.toString());
 	}
-	return(_properties.getProperty(name));
+	return _properties.getProperty(name);
     }
 
     /**
@@ -671,8 +679,25 @@
      * @throws IllegalArgumentException Never, errors are ignored
      */
     public void setOutputProperties(Properties properties)
-	throws IllegalArgumentException {
-	_properties.putAll(properties);
+	throws IllegalArgumentException 
+    {
+	if (properties != null) {
+	    final Enumeration names = properties.propertyNames();
+
+	    while (names.hasMoreElements()) {
+		final String name = (String) names.nextElement();
+		if (validOutputProperty(name)) {
+		    _properties.setProperty(name, properties.getProperty(name));
+		}
+		else {
+		    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
+		    throw new IllegalArgumentException(err.toString());
+		}
+	    }
+	}
+	else {
+	    _properties = _propertiesClone;
+	}
     }
 
     /**
@@ -708,7 +733,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))
@@ -753,65 +779,40 @@
      * Internal method to pass any properties to the translet prior to
      * initiating the transformation
      */
-    private Properties createOutputProperties() {
-	
-	// Level3: Return the default property value
-	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);
-	third.setProperty(OutputKeys.VERSION, "1.0");
+    private Properties createOutputProperties(Properties outputProperties) {
+	final Properties defaults = new Properties();
+	defaults.setProperty(OutputKeys.ENCODING, "UTF-8");
+	defaults.setProperty(OutputKeys.METHOD, XML_STRING);
+	defaults.setProperty(OutputKeys.INDENT, NO_STRING);
+	defaults.setProperty(OutputKeys.MEDIA_TYPE, "text/xml");
+	defaults.setProperty(OutputKeys.OMIT_XML_DECLARATION, NO_STRING);
+	defaults.setProperty(OutputKeys.STANDALONE, NO_STRING);
+	defaults.setProperty(OutputKeys.VERSION, "1.0");
 
-	// Level2: Return the property value is set in the translet
-	// Creating these properties with the third-level properties as default
-	Properties second = new Properties(third);
-	if (_translet != null) {
-	    String value = _translet._encoding;
-	    if (value != null) second.setProperty(OutputKeys.ENCODING, value);
-
-	    value = _translet._method;
-	    if (value != null) second.setProperty(OutputKeys.METHOD, value);
-
-	    if (_translet._indent)
-		second.setProperty(OutputKeys.INDENT, "yes");
-	    else
-		second.setProperty(OutputKeys.INDENT, "no");
-
-	    value = _translet._doctypePublic;
-	    if (value != null) 
-		second.setProperty(OutputKeys.DOCTYPE_PUBLIC, value);
-
-	    value = _translet._doctypeSystem;
-	    if (value != null) 
-		second.setProperty(OutputKeys.DOCTYPE_SYSTEM, value);
-
-	    value = makeCDATAString(_translet._cdata);
-	    if (value != null) 
-		second.setProperty(OutputKeys.CDATA_SECTION_ELEMENTS,value);
-
-	    value = _translet._mediaType;
-	    if (value != null) second.setProperty(OutputKeys.MEDIA_TYPE, value);
-
-	    if (_translet._omitHeader)
-		second.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
-	    else
-		second.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
-
-	    value = _translet._standalone;
-	    if (value != null) second.setProperty(OutputKeys.STANDALONE, value);
-
-	    value = _translet._version;
-	    if (value != null) second.setProperty(OutputKeys.VERSION, value);
+	// Copy propeties set in stylesheet to base
+	final Properties base = new Properties(defaults);
+	if (outputProperties != null) {
+	    final Enumeration names = outputProperties.propertyNames();
+	    while (names.hasMoreElements()) {
+		final String name = (String) names.nextElement();
+		base.setProperty(name, outputProperties.getProperty(name));
+	    }
 	}
 
-	// Creating the properties with the second-level properties as default
-	return(new Properties(second));
+	// Update defaults based on output method
+	final String method = base.getProperty(OutputKeys.METHOD);
+	if (method != null) {
+	    if (method.equals("html")) {
+		defaults.setProperty(OutputKeys.INDENT, "yes");
+		defaults.setProperty(OutputKeys.VERSION, "4.0");
+		defaults.setProperty(OutputKeys.MEDIA_TYPE, "text/html");
+	    }
+	    else if (method.equals("text")) {
+		defaults.setProperty(OutputKeys.MEDIA_TYPE, "text/plain");
+	    }
+	}
+
+	return base; 
     }
 
     /**
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