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:31:54 UTC

[xalan-java] annotated tag jaxp-ri-1_2_0-fcs-02 created (now 622cd2a)

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-02
in repository https://gitbox.apache.org/repos/asf/xalan-java.git.


      at 622cd2a  (tag)
 tagging a78a29a4c1058914cc57ef8ba6f8cd0759b4c433 (commit)
      by No Author
      on Tue Apr 9 18:55:56 2002 +0000

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

This annotated tag includes the following new commits:

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

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-02'.

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-02
in repository https://gitbox.apache.org/repos/asf/xalan-java.git

commit a78a29a4c1058914cc57ef8ba6f8cd0759b4c433
Author: No Author <de...@apache.org>
AuthorDate: Tue Apr 9 18:55:56 2002 +0000

    This commit was manufactured by cvs2svn to create tag
    'jaxp-ri-1_2_0-fcs-02'.
---
 build.xml                                          |   7 +-
 .../xalan/xsltc/compiler/ApplyTemplates.java       |   5 +-
 src/org/apache/xalan/xsltc/compiler/Constants.java |   4 +
 .../apache/xalan/xsltc/compiler/Expression.java    |   2 +-
 .../xalan/xsltc/compiler/FormatNumberCall.java     |   2 +-
 .../xsltc/compiler/FunctionAvailableCall.java      | 174 +++++++++++-
 .../apache/xalan/xsltc/compiler/FunctionCall.java  |  77 ++++--
 .../xalan/xsltc/compiler/LiteralElement.java       |  87 ++++--
 .../xalan/xsltc/compiler/ParentLocationPath.java   |   2 +
 src/org/apache/xalan/xsltc/compiler/Parser.java    |  10 +-
 .../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    |  30 +-
 .../apache/xalan/xsltc/compiler/SymbolTable.java   |   9 +-
 .../xalan/xsltc/compiler/SyntaxTreeNode.java       |  14 +-
 .../apache/xalan/xsltc/compiler/XslAttribute.java  |  73 +++--
 .../apache/xalan/xsltc/compiler/XslElement.java    |   4 +
 src/org/apache/xalan/xsltc/compiler/util/Util.java |  27 +-
 .../xalan/xsltc/dom/CurrentNodeListIterator.java   |  17 +-
 src/org/apache/xalan/xsltc/dom/DOMBuilder.java     |   2 +-
 src/org/apache/xalan/xsltc/dom/DOMImpl.java        | 135 ++++++---
 .../dom/{DOMBuilder.java => ExtendedSAX.java}      |   4 +-
 .../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   |   2 +-
 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 | 283 ++++++++++++-------
 .../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     |   7 +-
 src/org/apache/xalan/xsltc/trax/TemplatesImpl.java |  10 +-
 .../xalan/xsltc/trax/TransformerFactoryImpl.java   |   4 +-
 .../apache/xalan/xsltc/trax/TransformerImpl.java   |  28 +-
 src/trax/trax.properties                           |  11 -
 40 files changed, 1215 insertions(+), 610 deletions(-)

diff --git a/build.xml b/build.xml
index 0e09c0f..5316f9c 100644
--- a/build.xml
+++ b/build.xml
@@ -361,7 +361,7 @@ Copyright:
     </javac>
   </target>
 
-  <target name="xsltc.jar" depends="xsltc.compile"
+  <target name="xsltc.unbundledjar" depends="xsltc.compile"
     description="Jar just the xsltc.jar file" >
     <!-- Copy over the manifest, with filtering (for version number) -->
     <filter token="impl.version" value="${impl.version}"/>
@@ -374,7 +374,7 @@ 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 +449,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/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/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/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..af45184 100644
--- a/src/org/apache/xalan/xsltc/compiler/FunctionAvailableCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/FunctionAvailableCall.java
@@ -56,7 +56,7 @@
  * information on the Apache Software Foundation, please see
  * <http://www.apache.org/>.
  *
- * @author Jacek Ambroziak
+ * @author G. Todd Miller 
  * @author Santiago Pericas-Geertsen
  *
  */
@@ -64,38 +64,188 @@
 package org.apache.xalan.xsltc.compiler;
 
 import java.util.Vector;
-import java.util.HashSet;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Method;
 import org.apache.xalan.xsltc.compiler.util.Type;
 import org.apache.bcel.generic.*;
 import org.apache.xalan.xsltc.compiler.util.*;
+import org.apache.xalan.xsltc.runtime.TransletLoader;
 
 final class FunctionAvailableCall extends FunctionCall {
 
+    private boolean    _isFunctionAvailable = false; 
+    private Expression _arg; 
+    private String     _namespaceOfFunct =null; 	
+    private String     _nameOfFunct =null; 
+
+
+    /**
+     * Constructs a FunctionAvailableCall FunctionCall. Takes the
+     * function name qname, for example, 'function-available', and a list
+     * of arguments where the arguments must be instances of 
+     * LiteralExpression. The test for availability considers
+     * internal xsl functions such as 'floor' as well as external
+     * Java functions, such as 'java.lang.Math.sin'.  The case of
+     * external functions is handled here, the case of internal
+     * functions is handled in getResult. 
+     */
     public FunctionAvailableCall(QName fname, Vector arguments) {
 	super(fname, arguments);
+	_arg = (Expression)arguments.elementAt(0);
+	_type = null; 
+        if (_arg instanceof LiteralExpr) {
+	    LiteralExpr arg = (LiteralExpr)_arg;
+            _namespaceOfFunct = arg.getNamespace();
+            _nameOfFunct = arg.getValue();
+            if ((_namespaceOfFunct != null) && 
+                (!_namespaceOfFunct.equals(Constants.EMPTYSTRING)))
+	    {
+		// the function is external, such as a java function
+                _isFunctionAvailable = hasMethods();
+            }
+	    // the case of internal function is handled in getResult.
+        }
+	// case where _arg is not instanceof LiteralExpr can not be handled.
     }
 
     /**
-     * Force the argument to this function to be a literal string.
+     * Argument of function-available call must be literal, typecheck
+     * returns the type of function-available to be boolean.  
      */
     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
-	if (argument() instanceof LiteralExpr) {
-	    return _type = Type.Boolean;
+	// may be already set
+	if ( _type != null ) {
+	   return _type;
+	}
+	if (_arg instanceof LiteralExpr) {
+	    _type = Type.Boolean;
+	    return Type.Boolean;	
 	}
 	ErrorMsg err = new ErrorMsg(ErrorMsg.NEED_LITERAL_ERR,
-				    "function-available", this);
+			"function-available", this);
 	throw new TypeCheckError(err);
     }
 
     /**
-     * Returns the result that this function will return
+     * (For ext. java functions only)
+     * Parses the argument to function-available to extract the package 
+     * qualified class name, for example, given the argument 
+     * 'java:java.lang.Math.sin', getClassName would return
+     * 'java.lang.Math'. See also 'getMethodName'.
+     */
+    private String getClassName(String argValue){
+	int colonSep = argValue.indexOf(":");
+	if (colonSep != -1) {
+	    argValue = argValue.substring(colonSep+1);  
+	}		
+	int lastDot  = argValue.lastIndexOf(".");
+	if (lastDot != -1) {
+	    argValue = argValue.substring(0, lastDot);
+	}
+	return argValue;
+    }
+
+    /**
+     * (For ext. java functions only) 
+     * Parses the argument to function-available
+     * to extract the method name, for example, given the argument
+     * 'java.lang.Math.sin', getMethodName would return 'sin'. 
+     */
+    private String getMethodName(String argValue){
+	int lastDot  = argValue.lastIndexOf(".");
+	if (lastDot != -1) {
+	    argValue = argValue.substring(lastDot+1);
+	}
+	return argValue;
+    }
+
+    /**
+     * (For java external functions only) 
+     * Creates a full package qualified 
+     * function name taking into account the namespace and the
+     * function name derived from the argument passed to function-available.
+     * For example, given a name of 'java:java.lang.Math.sin' and a
+     * namespace of 'http://xml.apache.org/xalan/xsltc/java' this routine
+     * constructs a uri and then derives the class name 
+     * 'java.lang.Math.sin' from the uri. The uri in this example would
+     * be 'http://xml.apache.org/xalan/xsltc/java.java.lang.Math.sin'
+     */
+    private String getExternalFunctionName() {
+	int colonIndex = _nameOfFunct.indexOf(":");
+	String uri = _namespaceOfFunct + 
+                    "." + _nameOfFunct.substring(colonIndex+1);
+	try{
+	    return getClassNameFromUri(uri); 
+        } catch (TypeCheckError e) {
+	    return null; 
+        }
+    }
+
+    /**
+     * for external java functions only: reports on whether or not
+     * the specified method is found in the specifed class. 
+     */
+    private boolean hasMethods() {
+        
+	LiteralExpr arg = (LiteralExpr)_arg;
+	final String externalFunctName = getExternalFunctionName();
+	if (externalFunctName == null) {
+	    return false;
+	}
+	final String className = getClassName(externalFunctName);
+
+        if (_namespaceOfFunct.startsWith(JAVA_EXT_PREFIX) ||
+            _namespaceOfFunct.startsWith(JAVA_EXT_XALAN)) {
+            try {
+                TransletLoader loader = new TransletLoader();
+                final Class clazz = loader.loadClass(className);
+
+                if (clazz == null) {
+                    final ErrorMsg msg =
+                        new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, className);
+                    getParser().reportError(Constants.ERROR, msg);
+                }
+                else {
+                    final String methodName = getMethodName(externalFunctName);
+                    final Method[] methods = clazz.getDeclaredMethods();
+
+                    for (int i = 0; i < methods.length; i++) {
+                        final int mods = methods[i].getModifiers();
+
+                        if (Modifier.isPublic(mods)
+                            && Modifier.isStatic(mods)
+                            && methods[i].getName().equals(methodName))
+                        {
+			    return true;
+                        }
+                    }
+                }
+            }
+            catch (ClassNotFoundException e) {
+                final ErrorMsg msg =
+                    new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, className);
+                getParser().reportError(Constants.ERROR, msg);
+            }
+        }
+        return false;   
+    }
+
+    /**
+     * reports on whether the function specified in the argument to
+     * xslt function 'function-available' was found.
      */
     public boolean getResult() {
-	final Parser parser = getParser();
-	final LiteralExpr arg = (LiteralExpr)argument();
-	return(parser.functionSupported(arg.getValue()));
+        if ((_namespaceOfFunct == null) ||
+           (_namespaceOfFunct.equals(Constants.EMPTYSTRING)))
+        {
+            // no namespace, so the function is an internal xslt function.
+            final Parser parser = getParser();
+            _isFunctionAvailable = parser.functionSupported(_nameOfFunct);
+        }
+ 	return _isFunctionAvailable;
     }
 
+
     /**
      * Calls to 'function-available' are resolved at compile time since 
      * the namespaces declared in the stylsheet are not available at run
@@ -103,7 +253,7 @@ 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..e3dfc05 100644
--- a/src/org/apache/xalan/xsltc/compiler/FunctionCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/FunctionCall.java
@@ -86,8 +86,8 @@ 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 JAVA_EXT_PREFIX = TRANSLET_URI + "/java";
+    protected final static String JAVA_EXT_XALAN =
 	"http://xml.apache.org/xslt/java";
 
     // External Java function's class/method/signature
@@ -170,6 +170,7 @@ class FunctionCall extends Expression {
     public FunctionCall(QName fname, Vector arguments) {
 	_fname = fname;
 	_arguments = arguments;
+	_type = null;
     }
 
     public FunctionCall(QName fname) {
@@ -192,11 +193,27 @@ class FunctionCall extends Expression {
 	}
     }
 
+    public String getClassNameFromUri(String uri) 
+	throws TypeCheckError
+    {
+	final int length = 
+	    uri.startsWith(JAVA_EXT_PREFIX) ? JAVA_EXT_PREFIX.length() + 1 :
+	    uri.startsWith(JAVA_EXT_XALAN) ? JAVA_EXT_XALAN.length() + 1 : 0;
+
+	if (length == 0) {
+	    throw new TypeCheckError(this);
+	}
+	return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING;
+    }
+
     /**
      * Type check a function call. Since different type conversions apply,
      * type checking is different for standard and external (Java) functions.
      */
-    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
+    public Type typeCheck(SymbolTable stable) 
+	throws TypeCheckError 
+    {
+	if (_type != null) return _type;
 
 	final String namespace = _fname.getNamespace();
 	final String local = _fname.getLocalPart();
@@ -207,33 +224,37 @@ class FunctionCall extends Expression {
 	}
 	// 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);
 		}
-		unresolvedExternal = true;
-		return _type = Type.Void;
+		if (_className.length() > 0) {
+		    return typeCheckExternal(stable);
+		}
+	    } 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;
 	}
     }
 
diff --git a/src/org/apache/xalan/xsltc/compiler/LiteralElement.java b/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
index fffa79b..a041344 100644
--- a/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
+++ b/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
@@ -77,10 +77,11 @@ import org.apache.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 +120,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 +140,7 @@ final class LiteralElement extends Instruction {
 		if (old != null) {
 		    if (old.equals(uri))
 			return;
-		    else
+		    else 
 			prefix = stable.generateNamespacePrefix();
 		}
 	    }
@@ -207,7 +208,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 +255,24 @@ 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);
 
 	// Process all attributes and register all namespaces they use
 	final int count = _attributes.getLength();
 	for (int i = 0; i < count; i++) {
-
 	    final QName qname = parser.getQName(_attributes.getQName(i));
 	    final String uri = qname.getNamespace();
 	    final String val = _attributes.getValue(i);
@@ -290,12 +291,15 @@ 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 +315,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 +325,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 +346,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 +358,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/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..486a35d 100644
--- a/src/org/apache/xalan/xsltc/compiler/Parser.java
+++ b/src/org/apache/xalan/xsltc/compiler/Parser.java
@@ -265,6 +265,10 @@ public 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 +279,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);
@@ -1072,7 +1076,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);
     }
 
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..fa2d816 100644
--- a/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
+++ b/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
@@ -284,7 +284,6 @@ public final class Stylesheet extends SyntaxTreeNode {
 	super.addPrefixMapping(prefix, uri);
     }
 
-
     /**
      * Store extension URIs
      */
@@ -308,8 +307,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);
@@ -878,6 +879,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 +909,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..cd6f4d1 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);
     }
 
     /**
diff --git a/src/org/apache/xalan/xsltc/compiler/XslAttribute.java b/src/org/apache/xalan/xsltc/compiler/XslAttribute.java
index f6e8b6e..445eab0 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);
 	}
 	// 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)
+	    if (namespace != null) {
 		_namespace = new AttributeValueTemplate(namespace, parser);
+	    }
 	}
 	
 	// 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..8f79435 100644
--- a/src/org/apache/xalan/xsltc/compiler/XslElement.java
+++ b/src/org/apache/xalan/xsltc/compiler/XslElement.java
@@ -88,6 +88,10 @@ final class XslElement extends Instruction {
 	displayContents(indent + IndentIncrement);
     }
 
+    public boolean declaresDefaultNS() {
+	return (_namespace != null && _prefix == EMPTYSTRING);
+    }
+
     /**
      * Parses the element's contents. Special care taken for namespaces.
      * TODO: The namespace attribute that specifies the namespace to use
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/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/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..a4ceb85 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,6 +137,9 @@ 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;
 
@@ -1053,6 +1057,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];
 		    }
@@ -1980,6 +1985,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 +2168,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 +2203,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 +2632,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 +2660,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 +2727,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 +2934,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 +2993,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 +3115,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 +3208,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 +3227,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 +3264,29 @@ 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);
 	    }
+
+	    // 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 +3323,9 @@ public final class DOMImpl implements DOM, Externalizable {
 	    }
 	    System.arraycopy(ch, start, _text, _currentOffset, length);
 	    _currentOffset += length;
+
+	    _disableEscaping = !_escaping;	
+
 	}
 
 	/**
@@ -3295,7 +3341,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 +3420,56 @@ 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;
+		    }
 		}
 	    }
 
 	    // 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 +3563,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 +3649,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 +3723,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/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..b800d89 100644
--- a/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java
+++ b/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java
@@ -427,7 +427,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");
 	
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..4e7a27e 100644
--- a/src/org/apache/xalan/xsltc/runtime/TextOutput.java
+++ b/src/org/apache/xalan/xsltc/runtime/TextOutput.java
@@ -72,10 +72,11 @@ import 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
@@ -100,8 +101,6 @@ public final class TextOutput implements TransletOutputHandler {
     // Contains all elements that should be output as CDATA sections
     private Hashtable _cdata = null;
 
-    private static final String XML_PREFIX = "xml";
-
     private static final char[] AMP      = "&amp;".toCharArray();
     private static final char[] LT       = "&lt;".toCharArray();
     private static final char[] GT       = "&gt;".toCharArray();
@@ -124,15 +123,15 @@ 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;
@@ -252,8 +251,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 +263,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) {
@@ -467,9 +449,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) {
 
@@ -670,6 +650,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 +669,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 +701,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 +755,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 +811,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 +925,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 +937,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 +1005,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 +1022,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 +1039,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..0252cc3 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();
 
@@ -161,6 +159,7 @@ 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;
diff --git a/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java b/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java
index e1c099c..26cde36 100644
--- a/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java
@@ -59,6 +59,7 @@
  * @author Morten Jorgensen
  * @author G. Todd Millerj
  * @author Jochen Cordes <Jo...@t-online.de>
+ * @author Santiago Pericas-Geertsen 
  *
  */
 
@@ -176,8 +177,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());
 			}
 		    }
 		);
diff --git a/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java b/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
index 2f2cc9b..a652020 100644
--- a/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
@@ -527,7 +527,9 @@ public 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..e6eb0ce 100644
--- a/src/org/apache/xalan/xsltc/trax/TransformerImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TransformerImpl.java
@@ -211,7 +211,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 +409,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 +431,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
@@ -708,7 +720,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))
@@ -756,13 +769,14 @@ public final class TransformerImpl extends Transformer
     private Properties createOutputProperties() {
 	
 	// Level3: Return the default property value
+ 	// bug # 6751 fixed by removing setProperty lines for 
+  	//  OutputKeys.(DOCTYPE_PUBLIC|DOCTYPE_SYSTEM|CDATA_SECTION_ELEMENTS)
+  	//  instead of setting them to "" (EMPTY_STRING). Fix contributed
+  	//  by Derek Sayeau.   
 	Properties third = new Properties();
 	third.setProperty(OutputKeys.ENCODING, "UTF-8");
 	third.setProperty(OutputKeys.METHOD, XML_STRING);
 	third.setProperty(OutputKeys.INDENT, NO_STRING);
-	third.setProperty(OutputKeys.DOCTYPE_PUBLIC, EMPTY_STRING);
-	third.setProperty(OutputKeys.DOCTYPE_SYSTEM, EMPTY_STRING);
-	third.setProperty(OutputKeys.CDATA_SECTION_ELEMENTS, EMPTY_STRING);
 	third.setProperty(OutputKeys.MEDIA_TYPE, "text/xml");
 	third.setProperty(OutputKeys.OMIT_XML_DECLARATION, NO_STRING);
 	third.setProperty(OutputKeys.STANDALONE, NO_STRING);
diff --git a/src/trax/trax.properties b/src/trax/trax.properties
deleted file mode 100644
index e593c39..0000000
--- a/src/trax/trax.properties
+++ /dev/null
@@ -1,11 +0,0 @@
-# $Revision$ $Date$
-#
-# Note: This properties file is provided for illustrative purposes
-#       only and is not part of the interface definition.
-#       This properties file is located in the implementation JAR
-#       and different implementations will specify different
-#       implementation classes and output methods.
-#
-
-# The TRaX Stylesheet processor
-trax.processor.xslt=org.apache.xalan.processor.StylesheetProcessor


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