You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by gg...@apache.org on 2019/04/20 23:32:00 UTC

[xalan-java] annotated tag jaxp-ri-1_2_0-fcs-05 created (now 96b339e)

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a change to annotated tag jaxp-ri-1_2_0-fcs-05
in repository https://gitbox.apache.org/repos/asf/xalan-java.git.


      at 96b339e  (tag)
 tagging 4f59533bfe3ba7922c393e601db950c24063ee55 (commit)
      by No Author
      on Sat Jun 15 16:39:48 2002 +0000

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

This annotated tag includes the following new commits:

     new 4f59533  This commit was manufactured by cvs2svn to create tag 'jaxp-ri-1_2_0-fcs-05'.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



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


[xalan-java] 01/01: This commit was manufactured by cvs2svn to create tag 'jaxp-ri-1_2_0-fcs-05'.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to annotated tag jaxp-ri-1_2_0-fcs-05
in repository https://gitbox.apache.org/repos/asf/xalan-java.git

commit 4f59533bfe3ba7922c393e601db950c24063ee55
Author: No Author <de...@apache.org>
AuthorDate: Sat Jun 15 16:39:48 2002 +0000

    This commit was manufactured by cvs2svn to create tag
    'jaxp-ri-1_2_0-fcs-05'.
---
 build.xml                                          |  19 +-
 src/org/apache/xalan/xsltc/DOM.java                |   2 +
 .../xalan/xsltc/compiler/ApplyTemplates.java       |   5 +-
 .../xalan/xsltc/compiler/AttributeValue.java       |   6 +-
 .../xsltc/compiler/AttributeValueTemplate.java     |   8 +-
 src/org/apache/xalan/xsltc/compiler/CastExpr.java  |   1 +
 src/org/apache/xalan/xsltc/compiler/Constants.java |   4 +
 .../apache/xalan/xsltc/compiler/DocumentCall.java  |  10 +-
 .../xalan/xsltc/compiler/ElementAvailableCall.java |   9 +-
 .../apache/xalan/xsltc/compiler/Expression.java    |   2 +-
 .../xalan/xsltc/compiler/FormatNumberCall.java     |   2 +-
 .../xsltc/compiler/FunctionAvailableCall.java      | 174 +++++++++++-
 .../apache/xalan/xsltc/compiler/FunctionCall.java  | 115 +++++---
 src/org/apache/xalan/xsltc/compiler/Include.java   |  47 +++-
 .../xalan/xsltc/compiler/LiteralElement.java       | 103 +++++--
 .../apache/xalan/xsltc/compiler/LiteralExpr.java   |   5 +-
 src/org/apache/xalan/xsltc/compiler/Number.java    |  10 +-
 src/org/apache/xalan/xsltc/compiler/Output.java    | 111 ++++++--
 .../xalan/xsltc/compiler/ParentLocationPath.java   |   2 +
 src/org/apache/xalan/xsltc/compiler/Parser.java    | 145 +++++++++-
 .../xsltc/compiler/ProcessingInstruction.java      |   6 +-
 src/org/apache/xalan/xsltc/compiler/Step.java      |  16 --
 .../apache/xalan/xsltc/compiler/StepPattern.java   |   6 +-
 .../apache/xalan/xsltc/compiler/Stylesheet.java    |  85 ++++--
 .../apache/xalan/xsltc/compiler/SymbolTable.java   |   9 +-
 .../xalan/xsltc/compiler/SyntaxTreeNode.java       |  62 ++--
 src/org/apache/xalan/xsltc/compiler/Template.java  |   5 +
 src/org/apache/xalan/xsltc/compiler/XSLTC.java     |  24 +-
 .../apache/xalan/xsltc/compiler/XslAttribute.java  |  77 +++--
 .../apache/xalan/xsltc/compiler/XslElement.java    | 272 ++++++++++++------
 .../xalan/xsltc/compiler/util/ErrorMessages.java   |   8 +-
 .../xalan/xsltc/compiler/util/MethodGenerator.java |  18 +-
 .../xalan/xsltc/compiler/util/ReferenceType.java   |  17 ++
 src/org/apache/xalan/xsltc/compiler/util/Util.java |  27 +-
 src/org/apache/xalan/xsltc/compiler/xpath.cup      |   9 +
 .../xalan/xsltc/dom/CurrentNodeListIterator.java   |  17 +-
 src/org/apache/xalan/xsltc/dom/DOMAdapter.java     |  18 +-
 src/org/apache/xalan/xsltc/dom/DOMBuilder.java     |   2 +-
 src/org/apache/xalan/xsltc/dom/DOMImpl.java        | 187 +++++++++---
 .../dom/{DOMBuilder.java => ExtendedSAX.java}      |   4 +-
 src/org/apache/xalan/xsltc/dom/MultiDOM.java       |  15 +-
 .../apache/xalan/xsltc/dom/SortingIterator.java    |  28 +-
 src/org/apache/xalan/xsltc/dom/UnionIterator.java  |   4 +-
 .../xalan/xsltc/runtime/AbstractTranslet.java      |  84 +++---
 .../apache/xalan/xsltc/runtime/BasisLibrary.java   |  81 ++++--
 src/org/apache/xalan/xsltc/runtime/Constants.java  |   5 +
 .../xsltc/runtime/DefaultSAXOutputHandler.java     |  45 +--
 src/org/apache/xalan/xsltc/runtime/SAXAdapter.java |  42 ++-
 .../xalan/xsltc/runtime/StringValueHandler.java    |  25 ++
 src/org/apache/xalan/xsltc/runtime/TextOutput.java | 312 +++++++++++++--------
 .../apache/xalan/xsltc/runtime/TransletLoader.java |  19 +-
 src/org/apache/xalan/xsltc/trax/DOM2SAX.java       | 302 +++++++++++++++++---
 src/org/apache/xalan/xsltc/trax/SAX2DOM.java       | 213 ++++++--------
 .../xalan/xsltc/trax/TemplatesHandlerImpl.java     |  11 +-
 src/org/apache/xalan/xsltc/trax/TemplatesImpl.java |  19 +-
 .../xalan/xsltc/trax/TransformerFactoryImpl.java   |  51 ++--
 .../apache/xalan/xsltc/trax/TransformerImpl.java   | 147 +++++-----
 src/trax/trax.properties                           |  11 -
 58 files changed, 2149 insertions(+), 914 deletions(-)

diff --git a/build.xml b/build.xml
index 0e09c0f..0378c20 100644
--- a/build.xml
+++ b/build.xml
@@ -361,7 +361,19 @@ Copyright:
     </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 @@ Copyright:
   </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 @@ Copyright:
         includeEmptyDirs="true" quiet="true"/>
 
     <!-- create new META-INF dir w/ transformer factory default -->
+    <!-- GTM: comment this out so that bundled xsltc.jar does not have
+	 service provider default until further notice 2/20/2002
     <mkdir dir="${build.dir}/xsltctmp/META-INF"/>
     <mkdir dir="${build.dir}/xsltctmp/META-INF/services"/>
     <copy todir="${build.dir}/xsltctmp/META-INF/services"
       file="${src.dir}/${xsltc.reldir}/javax.xml.transform.TransformerFactory"
     />
+    -->
 
     <!-- Copy over the manifest, with filtering (for version number) -->
     <filter token="impl.version" value="${impl.version}"/>
diff --git a/src/org/apache/xalan/xsltc/DOM.java b/src/org/apache/xalan/xsltc/DOM.java
index 040e74e..97e1d47 100644
--- a/src/org/apache/xalan/xsltc/DOM.java
+++ b/src/org/apache/xalan/xsltc/DOM.java
@@ -132,4 +132,6 @@ public interface DOM {
     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 @@ final class ApplyTemplates extends Instruction {
      * 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 @@ final class ApplyTemplates extends Instruction {
 	    translateContents(classGen, methodGen);
 	}
 
+
 	il.append(classGen.loadTranslet());
 
 	// The 'select' expression is a result-tree
@@ -192,6 +194,7 @@ final class ApplyTemplates extends Instruction {
 							     NODE_ITERATOR_SIG);
 		il.append(methodGen.loadCurrentNode());
 		il.append(new INVOKEINTERFACE(setStartNode,2));
+		setStartNodeCalled = true;	
 	    }
 	    else {
 		if (_select == null)
@@ -201,7 +204,7 @@ final class ApplyTemplates extends Instruction {
 	    }
 	}
 
-	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 @@ abstract class AttributeValue extends Expression {
 
 	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 @@ import org.apache.xalan.xsltc.compiler.util.*;
 
 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 @@ final class CastExpr extends Expression {
 	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 interface Constants extends InstructionConstants {
     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 @@ final class DocumentCall extends FunctionCall {
 	// 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 @@ final class ElementAvailableCall extends FunctionCall {
      * 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 @@ abstract class Expression extends SyntaxTreeNode {
     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 @@ final class FormatNumberCall extends FunctionCall {
 	    _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 @@ final class FunctionAvailableCall extends FunctionCall {
      */
     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 @@ class FunctionCall extends Expression {
     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 @@ class FunctionCall extends Expression {
     public FunctionCall(QName fname, Vector arguments) {
 	_fname = fname;
 	_arguments = arguments;
+	_type = null;
     }
 
     public FunctionCall(QName fname) {
@@ -192,48 +202,71 @@ class FunctionCall extends Expression {
 	}
     }
 
+    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));
+		}
+		else {
+		    _fname = new QName(namespace, null, local);
+		}
+		if (_className.length() > 0) {
+		    return typeCheckExternal(stable);
 		}
-		unresolvedExternal = true;
-		return _type = Type.Void;
+	    } catch (TypeCheckError e) {
+		// Falls through
+	    }
+
+	    /*
+	     * 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());
 	    }
-	    return typeCheckExternal(stable);
+	    unresolvedExternal = true;
+	    return _type = Type.Void;
 	}
     }
 
@@ -243,8 +276,7 @@ class FunctionCall extends Expression {
      * 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 @@ class FunctionCall extends Expression {
      * 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 @@ class FunctionCall extends Expression {
 	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 @@ class FunctionCall extends Expression {
 
     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 @@ class FunctionCall extends Expression {
 	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 @@ final class Include extends TopLevelElement {
 
     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 @@ final class Include extends TopLevelElement {
 		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 @@ final class Include extends TopLevelElement {
 		}
 	    }
 	}
+	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.Vector;
 import java.util.Hashtable;
+import java.util.Properties;
 import java.util.Enumeration;
-import java.util.Vector;
 
 import javax.xml.parsers.*;
+import javax.xml.transform.OutputKeys;
 
 import org.xml.sax.*;
 
@@ -77,10 +79,11 @@ import org.apache.bcel.generic.*;
 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 @@ final class LiteralElement extends Instruction {
 				  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 @@ final class LiteralElement extends Instruction {
 		if (old != null) {
 		    if (old.equals(uri))
 			return;
-		    else
+		    else 
 			prefix = stable.generateNamespacePrefix();
 		}
 	    }
@@ -207,7 +210,6 @@ final class LiteralElement extends Instruction {
 	_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 @@ final class LiteralElement extends Instruction {
      * 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 @@ final class LiteralElement extends Instruction {
 	    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 class LiteralElement extends Instruction {
 	    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 @@ final class LiteralElement extends Instruction {
 
 	// 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 @@ final class LiteralElement extends Instruction {
     /**
      * 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 @@ final class LiteralElement extends Instruction {
 	// 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 @@ final class LiteralExpr extends Expression {
      */
     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 @@ final class Number extends Instruction {
 		}
 	    }
 	    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 @@ final class Output extends TopLevelElement {
     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 @@ final class Output extends TopLevelElement {
      * 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 @@ final class Output extends TopLevelElement {
 
 	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 @@ final class Output extends TopLevelElement {
 					    _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);
+	}
+
+	// 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";
+		}
+	    }
+	}
 
-	// parseChildren(parser); - the element is always empty
+	// Set output properties in current stylesheet
+	parser.getCurrentStylesheet().setOutputProperties(outputProperties);
     }
 
     /**
@@ -216,7 +279,7 @@ final class Output extends TopLevelElement {
         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 @@ final class ParentLocationPath extends RelativeLocationPath {
 	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.net.URL;
 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 @@ public class Parser implements Constants, ContentHandler {
     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 @@ public class Parser implements Constants, ContentHandler {
 	_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 @@ public class Parser implements Constants, ContentHandler {
 	_currentImportPrecedence = 1;
 	
 	initStdClasses();
+	initInstructionAttrs();
 	initExtClasses();
 	initSymbolTable();
 	
@@ -166,6 +170,10 @@ public class Parser implements Constants, ContentHandler {
 	return _output;
     }
 
+    public Properties getOutputProperties() {
+	return getTopLevelStylesheet().getOutputProperties();
+    }
+
     public void addVariable(Variable var) {
 	addVariableOrParam(var);
     }
@@ -265,6 +273,10 @@ public class Parser implements Constants, ContentHandler {
     }
     
     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 @@ public class Parser implements Constants, ContentHandler {
 	    // 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 @@ public class Parser implements Constants, ContentHandler {
 	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 @@ public class Parser implements Constants, ContentHandler {
 				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 @@ public class Parser implements Constants, ContentHandler {
 	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 @@ public class Parser implements Constants, ContentHandler {
 	_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 @@ public class Parser implements Constants, ContentHandler {
      * 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 @@ public class Parser implements Constants, ContentHandler {
 		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 @@ public class Parser implements Constants, ContentHandler {
      *       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 @@ public class Parser implements Constants, ContentHandler {
 			     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 @@ final class ProcessingInstruction extends Instruction {
 
 	// 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 @@ final class Step extends RelativeLocationPath {
 		    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 @@ class StepPattern extends RelativePathPattern {
     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 @@ package org.apache.xalan.xsltc.compiler;
 
 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 @@ public final class Stylesheet extends SyntaxTreeNode {
     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 @@ public final class Stylesheet extends SyntaxTreeNode {
 
     private boolean _forwardReference = false;
 
+    private Properties _outputProperties = null;
+
     public void setForwardReference() {
 	_forwardReference = true;
     }
@@ -147,6 +151,21 @@ public final class Stylesheet extends SyntaxTreeNode {
 	_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 @@ public final class Stylesheet extends SyntaxTreeNode {
 	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 @@ public final class Stylesheet extends SyntaxTreeNode {
 	super.addPrefixMapping(prefix, uri);
     }
 
-
     /**
      * Store extension URIs
      */
@@ -308,8 +335,10 @@ public final class Stylesheet extends SyntaxTreeNode {
     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 @@ public final class Stylesheet extends SyntaxTreeNode {
 	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) {
-	Vector result = new Vector();
 
-	int zeroDep = 0;
+	// 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 @@ public final class Stylesheet extends SyntaxTreeNode {
 		    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 @@ public final class Stylesheet extends SyntaxTreeNode {
 					   "("+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 @@ public final class Stylesheet extends SyntaxTreeNode {
 	    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 @@ final class SymbolTable {
      * 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 @@ public abstract class SyntaxTreeNode implements Constants {
      * @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 @@ public abstract class SyntaxTreeNode implements Constants {
      * @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 @@ public abstract class SyntaxTreeNode implements Constants {
 	    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 @@ public final class Template extends TopLevelElement {
 	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.Hashtable;
 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 @@ public final class XSLTC {
     private int     _outputType = FILE_OUTPUT; // by default
 
     private Vector  _classes;
+    private boolean _callsNodeset = false;
     private boolean _multiDocument = false;
 
     /**
@@ -163,6 +165,13 @@ public final class XSLTC {
     }
 
     /**
+     * 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 @@ public final class XSLTC {
 	    }
 	    // 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 @@ public final class XSLTC {
 	_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 @@ public final class XSLTC {
     }
 
     /**
+     * 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 @@ import org.apache.xalan.xsltc.compiler.util.*;
 
 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 @@ final class XslAttribute extends Instruction {
      * Parses the attribute's contents. Special care taken for namespaces.
      */
     public void parseContents(Parser parser) {
-
+	boolean generated = false;
 	final SymbolTable stable = parser.getSymbolTable();
-	String namespace = getAttribute("namespace");
+
 	String name = getAttribute("name");
-	QName qname = parser.getQName(name);
+	String namespace = getAttribute("namespace");
+	QName qname = parser.getQName(name, false);
 	final String prefix = qname.getPrefix();
-	boolean generated = false;
 
-	if ((prefix != null) && (prefix.equals("xmlns"))) {
+	if ((prefix != null) && (prefix.equals(XMLNS_PREFIX))) {
 	    reportError(this, parser, ErrorMsg.ILLEGAL_ATTR_NAME_ERR, name);
 	    return;
 	}
@@ -118,11 +117,13 @@ final class XslAttribute extends Instruction {
 	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 @@ final class XslAttribute extends Instruction {
 	}
 
 	// 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 @@ final class XslAttribute extends Instruction {
 		    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 @@ final class XslAttribute extends Instruction {
 	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 @@ import org.apache.xalan.xsltc.compiler.util.*;
 
 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 @@ final class XslElement extends Instruction {
     }
 
     /**
-     * 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;
-	}
-	// 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();
-	}
 
-	_name = AttributeValue.create(this, name, parser);
+	    final QName qname = parser.getQNameSafe(name);
+	    String prefix = qname.getPrefix();
+	    String local = qname.getLocalPart();
+	    
+	    if (prefix == null) {
+		prefix = EMPTYSTRING;
+	    }
 
-	// 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;
+	    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);
 	    }
 	}
+	else {
+	    _namespace = (namespace == EMPTYSTRING) ? null :
+			 new AttributeValueTemplate(namespace, parser, this);
+	}
+
+	_name = new AttributeValueTemplate(name, parser, this);
 
-	// 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 @@ final class XslElement extends Instruction {
     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 @@ final class XslElement extends Instruction {
 	    }
 	}
 
-	// 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 @@ final class XslElement extends Instruction {
 	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 @@ public class ErrorMessages extends ResourceBundle {
 	"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 @@ public class ErrorMessages extends ResourceBundle {
 	"         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 @@ public class MethodGenerator extends MethodGen
     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 @@ public class MethodGenerator extends MethodGen
 	
 	_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 @@ public final class ReferenceType extends Type {
 	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 @@ public final class ReferenceType extends Type {
     }
 
     /**
+     * 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 @@ public final class Util {
      * 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 final class Util {
     }
 
     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 @@ parser code {:
           _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 @@ FunctionCall ::= FunctionName:fname LPAREN RPAREN
           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 @@ public final class CurrentNodeListIterator extends NodeIteratorBase {
 	_currentNode = currentNode;
     }
 
-    public NodeIterator forceNaturalOrder() {
-	_docOrder = true;
-	return this;
-    }
-
     public void setRestartable(boolean isRestartable) {
 	_isRestartable = isRestartable;
 	_source.setRestartable(isRestartable);
@@ -139,9 +134,8 @@ public final class CurrentNodeListIterator extends NodeIteratorBase {
 	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 @@ public final class CurrentNodeListIterator extends NodeIteratorBase {
         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 final class CurrentNodeListIterator extends NodeIteratorBase {
     }
 	
     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 @@ public final class DOMAdapter implements DOM {
     private short[] _NSreverse;
 
     private StripFilter _filter = null;
+
+    private int _multiDOMMask;
     
     public DOMAdapter(DOMImpl dom,
 		      String[] namesArray,
@@ -111,6 +113,14 @@ public final class DOMAdapter implements DOM {
 	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 final class DOMAdapter implements DOM {
 
     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 @@ public final class DOMAdapter implements DOM {
 	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 @@ package org.apache.xalan.xsltc.dom;
 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.w3c.dom.Document;
 
 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 @@ public final class DOMImpl implements DOM, Externalizable {
     // 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 @@ public final class DOMImpl implements DOM, Externalizable {
      * 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 @@ public final class DOMImpl implements DOM, Externalizable {
     }
 
     /**
+     * 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 @@ public final class DOMImpl implements DOM, Externalizable {
 		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 final class DOMImpl implements DOM, Externalizable {
 
 	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 @@ public final class DOMImpl implements DOM, Externalizable {
 	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 @@ public final class DOMImpl implements DOM, Externalizable {
 
 	out.writeObject(_whitespace);
 
+	if (_dontEscape != null) {
+	    out.writeObject(_dontEscape);
+	}
+	else {
+	    out.writeObject(new BitArray(0));
+	}
+
 	out.flush();
     }
 
@@ -2190,6 +2237,11 @@ public final class DOMImpl implements DOM, Externalizable {
 
 	_whitespace    = (BitArray)in.readObject();
 
+	_dontEscape    = (BitArray)in.readObject();
+	if (_dontEscape.size() == 0) {
+	    _dontEscape = null;
+        }
+
 	_types         = setupMapping(_namesArray);
     }
 
@@ -2614,9 +2666,23 @@ public final class DOMImpl implements DOM, Externalizable {
 				       _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 @@ public final class DOMImpl implements DOM, Externalizable {
 	    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 @@ public final class DOMImpl implements DOM, Externalizable {
 	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 @@ public final class DOMImpl implements DOM, Externalizable {
      * 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 @@ public final class DOMImpl implements DOM, Externalizable {
 	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 @@ public final class DOMImpl implements DOM, Externalizable {
 	 */
 	private short makeElementNode(String uri, String localname)
 	    throws SAXException {
-	    
 	    final String name;
 	    if (uri != EMPTYSTRING)
 		name = uri + ':' + localname;
@@ -3170,6 +3242,7 @@ public final class DOMImpl implements DOM, Externalizable {
 	 */
 	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 @@ public final class DOMImpl implements DOM, Externalizable {
 		_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 @@ public final class DOMImpl implements DOM, Externalizable {
 	 * 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 @@ public final class DOMImpl implements DOM, Externalizable {
 	    }
 	    System.arraycopy(ch, start, _text, _currentOffset, length);
 	    _currentOffset += length;
+
+	    _disableEscaping = !_escaping;	
+
 	}
 
 	/**
@@ -3295,7 +3380,7 @@ public final class DOMImpl implements DOM, Externalizable {
 	    _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 @@ public final class DOMImpl implements DOM, Externalizable {
 
 	    _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 @@ public final class DOMImpl implements DOM, Externalizable {
 		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 @@ public final class DOMImpl implements DOM, Externalizable {
 	    // 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 final class DOMImpl implements DOM, Externalizable {
 	    }
 	}
 
+ 	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/DOMBuilder.java b/src/org/apache/xalan/xsltc/dom/ExtendedSAX.java
similarity index 95%
copy from src/org/apache/xalan/xsltc/dom/DOMBuilder.java
copy to src/org/apache/xalan/xsltc/dom/ExtendedSAX.java
index cc67a53..8e87428 100644
--- a/src/org/apache/xalan/xsltc/dom/DOMBuilder.java
+++ b/src/org/apache/xalan/xsltc/dom/ExtendedSAX.java
@@ -64,4 +64,6 @@ package org.apache.xalan.xsltc.dom;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.ext.LexicalHandler;
 
-public interface DOMBuilder extends ContentHandler, 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 final class MultiDOM implements DOM {
 	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 @@ public final class MultiDOM implements DOM {
 	// 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 @@ public final class MultiDOM implements DOM {
 
 	// 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 @@ public final class MultiDOM implements DOM {
 	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 @@ package org.apache.xalan.xsltc.dom;
 
 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 @@ public final class SortingIterator extends NodeIteratorBase {
 	_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 @@ public final class UnionIterator extends NodeIteratorBase {
 	    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 abstract class AbstractTranslet implements Translet {
      */
     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 @@ public abstract class AbstractTranslet implements Translet {
      * Clears the parameter stack.
      */
     public void clearParameters() {  
+	pbase = pframe = 0;
 	paramsStack.clear();
     }
 
@@ -246,6 +218,7 @@ public abstract class AbstractTranslet implements Translet {
 	varsStack.insertElementAt(new Integer(vbase), vframe);
 	vbase = ++vframe;
 	vframe += frameSize;
+	varsStack.setSize(vframe + 1);	// clear stack frame
     }
 
     /**
@@ -253,16 +226,11 @@ public abstract class AbstractTranslet implements Translet {
      */
     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 @@ public abstract class AbstractTranslet implements Translet {
      * 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 @@ public abstract class AbstractTranslet implements Translet {
 	    // 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.xml.sax.AttributeList;
 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 @@ public final class BasisLibrary implements Operators {
 	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 @@ public final class BasisLibrary implements Operators {
 	    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 @@ public final class BasisLibrary implements Operators {
      * obj is an instanceof Node then create a singleton iterator.
      */
     public static NodeIterator referenceToNodeSet(Object obj) {
+	// 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());
+	}
+	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 {
-	    // 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;
-	    }
+	    return ((DOM) obj);
 	}
-	catch (ClassCastException e) {
-	    runTimeError(DATA_CONVERSION_ERR, "reference", "node-set");
+	catch (IllegalArgumentException e) {
+	    final String className = obj.getClass().getName();
+	    runTimeError(DATA_CONVERSION_ERR, "reference", className);
 	    return null;
 	}
     }
@@ -960,6 +976,29 @@ public final class BasisLibrary implements Operators {
 	}
     }
     
+    /**
+     * 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 interface Constants {
     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 @@ public class DefaultSAXOutputHandler implements ContentHandler, LexicalHandler {
     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 @@ public class DefaultSAXOutputHandler implements ContentHandler, LexicalHandler {
     /**
      * 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 @@ public class DefaultSAXOutputHandler implements ContentHandler, LexicalHandler {
             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 @@ public class DefaultSAXOutputHandler implements ContentHandler, LexicalHandler {
 	    _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 @@ public class DefaultSAXOutputHandler implements ContentHandler, LexicalHandler {
      *       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 final class SAXAdapter implements TransletOutputHandler {
     
     public void endDocument() throws TransletException {
 	try {
-	    _saxHandler.endDocument();
+	    _domBuilder.endDocument();
 	}
 	catch (SAXException e) {
 	    throw new TransletException(e);
@@ -115,7 +110,7 @@ public final class SAXAdapter implements TransletOutputHandler {
 	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 final class SAXAdapter implements TransletOutputHandler {
     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 final class SAXAdapter implements TransletOutputHandler {
     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 @@ public final class SAXAdapter implements TransletOutputHandler {
 	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 final class SAXAdapter implements TransletOutputHandler {
     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 @@ public final class StringValueHandler extends TransletOutputBase {
 	_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 java.util.Enumeration;
 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 @@ public final class TextOutput implements TransletOutputHandler {
     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 @@ public final class TextOutput implements TransletOutputHandler {
     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 @@ public final class TextOutput implements TransletOutputHandler {
         _saxHandler = handler;
         init();
 	_encoding = encoding;
+	_is8859Encoded = _encoding.equalsIgnoreCase("iso-8859-1");	
     }
 
     /**
@@ -194,6 +195,7 @@ public final class TextOutput implements TransletOutputHandler {
 	_lexHandler = lex;
         init();
 	_encoding = encoding;
+	_is8859Encoded = _encoding.equalsIgnoreCase("iso-8859-1");	
     }
 
     /**
@@ -252,8 +254,8 @@ public final class TextOutput implements TransletOutputHandler {
 	    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 final class TextOutput implements TransletOutputHandler {
     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 @@ public final class TextOutput implements TransletOutputHandler {
 		// 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 @@ public final class TextOutput implements TransletOutputHandler {
      * 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 @@ public final class TextOutput implements TransletOutputHandler {
 
 	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 @@ public final class TextOutput implements TransletOutputHandler {
 		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 @@ public final class TextOutput implements TransletOutputHandler {
 	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 @@ public final class TextOutput implements TransletOutputHandler {
 	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 @@ public final class TextOutput implements TransletOutputHandler {
 		        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 @@ public final class TextOutput implements TransletOutputHandler {
 	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 final class TextOutput implements TransletOutputHandler {
     public void attribute(String name, final String value)
 	throws TransletException {
 
+	if (_outputType == TEXT) return;
+
+	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 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);
+	    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 {
-		// Output as regular attribute
-		_attributes.add(expandAttribute(name), escapeString(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)
+	    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.
-
-	    // URL-encode href attributes in HTML output
+	    }
+
+	    /* 
+	     * 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)) {
-		_attributes.add(name,quickAndDirtyUrlEncode(escapeAttr(value)));
+	    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 {
-		_attributes.add(expandAttribute(name), escapeAttr(value));
+		if (index >= 0) {
+		    _attributes.setAttribute(index, EMPTYSTRING, EMPTYSTRING, 
+			name, "CDATA", escapeNonURLAttr(value));
+		}
+		else {
+		    _attributes.addAttribute(EMPTYSTRING, EMPTYSTRING, 
+			name, "CDATA", escapeNonURLAttr(value));
+		}
 	    }
-	    return;
+	    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 @@ public final class TextOutput implements TransletOutputHandler {
 		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 @@ public final class TextOutput implements TransletOutputHandler {
 	    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 @@ public final class TextOutput implements TransletOutputHandler {
 	_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 @@ public final class TextOutput implements TransletOutputHandler {
      * 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 @@ public final class TextOutput implements TransletOutputHandler {
 	_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 @@ package org.apache.xalan.xsltc.runtime;
 
 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 @@ final public class TransletLoader {
      * 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 @@ final public class TransletLoader {
     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.SAXNotRecognizedException;
 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 java.io.IOException;
 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 final static String EMPTYSTRING = "";
+    private static final String XMLNS_PREFIX = "xmlns";
 
-    private Document _dom = null;
+    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 void setContentHandler(ContentHandler handler) throws 
+	NullPointerException 
+    {
+	if (handler == null) throw new NullPointerException();
+	_sax = handler;
     }
 
-    public ErrorHandler getErrorHandler() {
-	return null;
+    /**
+     * 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;
     }
 
-    public boolean getFeature(String name) throws SAXNotRecognizedException,
-	SAXNotSupportedException
+    /*
+     * 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
     {
-	return false;
+	final Stack uriStack = (Stack) _nsPrefixes.get(prefix);
+
+	if (uriStack != null) {
+	    _sax.endPrefixMapping(prefix);
+	    uriStack.pop();
+	}
     }
 
-    public void setFeature(String name, boolean value) throws 
-	SAXNotRecognizedException, SAXNotSupportedException 
-    {
-	
+    /**
+     * 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 @@ class DOM2SAX implements XMLReader , Locator {
 
 	case Node.DOCUMENT_NODE:
 	    _sax.setDocumentLocator(this);
+
 	    _sax.startDocument();
 	    Node next = node.getFirstChild();
 	    while (next != null) {
@@ -149,29 +218,85 @@ class DOM2SAX implements XMLReader , Locator {
 	    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 @@ class DOM2SAX implements XMLReader , Locator {
 	}
     }
 
-    public void parse(String sysId) throws IOException, SAXException {
-	throw new IOException("This method is not yet implemented.");
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public DTDHandler getDTDHandler() { 
+	return null;
     }
-    public void setContentHandler(ContentHandler handler) throws 
-	NullPointerException 
+
+    /**
+     * 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
     {
-	if (handler == null ) throw new NullPointerException();
-	_sax = handler;
+	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.");
     }
+
+    /**
+     * 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; 
+    }
 
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public String getSystemId() { 
+	return null; 
+    }
 
-    // private 
+    // 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.DOMException;
 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 _root = null;
+    private Stack _nodeStk = new Stack();
+    private Vector _namespaceDecls = null;
 
-    private Document _document = null;
-    private DocumentBuilder _builder = null;
-    private Stack _nodeStk = 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();  
+	_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) {
     }
 
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void processingInstruction(String target, String data) {
     }
 
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void setDocumentLocator(Locator locator) {
     }
 
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void skippedEntity(String name) {
     }
-
-    public void startPrefixMapping(String prefix, String uri) {
-    }
-
-    public void endPrefixMapping(String prefix) {
-    }
-
-
-    // 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;
-            }
-
-            // move to first child
-            Node next = currNode.getFirstChild();
-            if (next != null) {
-                currNode = next;
-                continue;
-            }
-
-            // 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();
-            }
-        }
-   }
-
 }
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 @@ public class TemplatesHandlerImpl extends Parser implements TemplatesHandler {
 	// 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 @@ public class TemplatesHandlerImpl extends Parser implements TemplatesHandler {
      *         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 @@ public class TemplatesHandlerImpl extends Parser implements TemplatesHandler {
 	    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 @@ public class TemplatesHandlerImpl extends Parser implements TemplatesHandler {
 	    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 <Jo...@t-online.de>
+ * @author Santiago Pericas-Geertsen 
  *
  */
 
@@ -96,6 +97,8 @@ public final class TemplatesImpl implements Templates, Serializable {
     // 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 @@ public final class TemplatesImpl implements Templates, Serializable {
      * 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 @@ public final class TemplatesImpl implements Templates, Serializable {
 	    (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 final class TemplatesImpl implements Templates, Serializable {
      */
     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 @@ public class TransformerFactoryImpl
 	}
 
 	// 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 @@ public class TransformerFactoryImpl
     /**
      * 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 class TransformerFactoryImpl
      */
     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 @@ public class TransformerFactoryImpl
 	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 @@ public class TransformerFactoryImpl
 	    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 class TransformerFactoryImpl
      */
     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 @@ public final class TransformerImpl extends Transformer
 
     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 @@ public final class TransformerImpl extends Transformer
      * 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 @@ public final class TransformerImpl extends Transformer
                 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 @@ public final class TransformerImpl extends Transformer
 	    // 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 @@ public final class TransformerImpl extends Transformer
 		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 @@ public final class TransformerImpl extends Transformer
 
     /**
      * 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 @@ public final class TransformerImpl extends Transformer
 	    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 @@ public final class TransformerImpl extends Transformer
      * @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 @@ public final class TransformerImpl extends Transformer
 	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 @@ public final class TransformerImpl extends Transformer
      * 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");
-
-	// 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);
+    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");
+
+	// 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));
+	    }
+	}
 
-	    value = _translet._version;
-	    if (value != null) second.setProperty(OutputKeys.VERSION, value);
+	// 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");
+	    }
 	}
 
-	// Creating the properties with the second-level properties as default
-	return(new Properties(second));
+	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


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