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 <[email protected]>
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 <[email protected]>
+ * @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: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to