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

git-svn-id: https://svn.apache.org/repos/asf/xalan/java/tags/jaxp-ri-1_2_0-fcs-07@336566 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/build.xml b/build.xml
index 0e09c0f..0378c20 100644
--- a/build.xml
+++ b/build.xml
@@ -361,7 +361,19 @@
     </javac>
   </target>
 
-  <target name="xsltc.jar" depends="xsltc.compile"
+  <target name="xsltc.fcompile" 
+    description="Compile just the XSLTC classes w/o JLex, JCUP" >
+    <echo message="Compiling remaining XSLTC classes"/>
+    <javac srcdir="${src.dir}" 
+           destdir="${build.classes}"
+           includes="${xsltc.reldir}/**/*.java"
+           debug="${build.debug}">
+      <classpath refid="xsltc.class.path" />
+      <bootclasspath refid="xslt.boot.class.path" />
+    </javac>
+  </target>
+
+  <target name="xsltc.unbundledjar" depends="xsltc.compile"
     description="Jar just the xsltc.jar file" >
     <!-- Copy over the manifest, with filtering (for version number) -->
     <filter token="impl.version" value="${impl.version}"/>
@@ -374,7 +386,7 @@
   </target>
 
 
-  <target name="xsltc.bundledjar" depends="xsltc.compile"
+  <target name="xsltc.jar" depends="xsltc.compile"
      description="Jar xsltc, BCEL,JLex,java_cup,runtime and jakarta regexp">
     <!-- make a tmp directory to work in -->
     <delete dir="${build.dir}/xsltctmp" includeEmptyDirs="true" quiet="true"/>
@@ -449,11 +461,14 @@
         includeEmptyDirs="true" quiet="true"/>
 
     <!-- create new META-INF dir w/ transformer factory default -->
+    <!-- GTM: comment this out so that bundled xsltc.jar does not have
+	 service provider default until further notice 2/20/2002
     <mkdir dir="${build.dir}/xsltctmp/META-INF"/>
     <mkdir dir="${build.dir}/xsltctmp/META-INF/services"/>
     <copy todir="${build.dir}/xsltctmp/META-INF/services"
       file="${src.dir}/${xsltc.reldir}/javax.xml.transform.TransformerFactory"
     />
+    -->
 
     <!-- Copy over the manifest, with filtering (for version number) -->
     <filter token="impl.version" value="${impl.version}"/>
diff --git a/src/org/apache/xalan/serialize/SerializerToXML.java b/src/org/apache/xalan/serialize/SerializerToXML.java
index f9705d8..5d38068 100644
--- a/src/org/apache/xalan/serialize/SerializerToXML.java
+++ b/src/org/apache/xalan/serialize/SerializerToXML.java
@@ -323,6 +323,9 @@
   /** Indicate whether running in Debug mode */
   private static final boolean DEBUG = false;
 
+  /** This flag is set while receiving events from the external DTD */
+  private boolean m_inExternalDTD = false;
+
   /**
    * Default constructor.
    */
@@ -1864,6 +1867,8 @@
    */
   public void startEntity(String name) throws org.xml.sax.SAXException
   {
+    if (name.equals("[dtd]"))
+      m_inExternalDTD = true;	
     m_inEntityRef = true;
   }
 
@@ -1876,7 +1881,9 @@
    */
   public void endEntity(String name) throws org.xml.sax.SAXException
   {
-    m_inEntityRef = false;
+    if (name.equals("[dtd]")) 
+      m_inExternalDTD = false;
+     m_inEntityRef = false;
   }
 
   /**
@@ -1925,7 +1932,10 @@
    */
   public void elementDecl(String name, String model) throws SAXException
   {
-    try
+    // Do not inline external DTD
+    if (m_inExternalDTD) return; 
+
+     try
     {
       final Writer writer = m_writer;
       if (m_inDoctype)
@@ -1975,6 +1985,8 @@
           String eName, String aName, String type, String valueDefault, String value)
             throws SAXException
   {
+    // Do not inline external DTD
+    if (m_inExternalDTD) return; 
 
     try
     {
@@ -1987,26 +1999,19 @@
         m_inDoctype = false;
       }
   
-      if (!eName.equals(m_elemName))
-      {
-        writer.write("<!ATTLIST ");
-        writer.write(eName);
-        writer.write(" ");
+      writer.write("<!ATTLIST ");
+      writer.write(eName);
+      writer.write(" ");
   
-        m_elemName = eName;
-      }
-      else
-      {
-        m_pos -= 3;
-  
-        writer.write(m_lineSep, 0, m_lineSepLen);
-      }
   
       writer.write(aName);
       writer.write(" ");
       writer.write(type);
-      writer.write(" ");
-      writer.write(valueDefault);
+      if (valueDefault != null)
+      {
+         writer.write(" ");
+         writer.write(valueDefault);
+      }
   
       //m_writer.write(" ");
       //m_writer.write(value);
@@ -2035,6 +2040,8 @@
   public void internalEntityDecl(String name, String value)
           throws SAXException
   {
+    // Do not inline external DTD
+    if (m_inExternalDTD) return; 
 
     try
     {
diff --git a/src/org/apache/xalan/xsltc/DOM.java b/src/org/apache/xalan/xsltc/DOM.java
index 040e74e..97e1d47 100644
--- a/src/org/apache/xalan/xsltc/DOM.java
+++ b/src/org/apache/xalan/xsltc/DOM.java
@@ -132,4 +132,6 @@
     public void setupMapping(String[] names, String[] namespaces);
     public boolean isElement(final int node);
     public boolean isAttribute(final int node);
+    public String lookupNamespace(int node, String prefix)
+	throws TransletException;
 }
diff --git a/src/org/apache/xalan/xsltc/TransletOutputHandler.java b/src/org/apache/xalan/xsltc/TransletOutputHandler.java
index f53fa11..59a5150 100644
--- a/src/org/apache/xalan/xsltc/TransletOutputHandler.java
+++ b/src/org/apache/xalan/xsltc/TransletOutputHandler.java
@@ -73,6 +73,7 @@
     public void endDocument() throws TransletException;
     public void startElement(String elementName) throws TransletException;
     public void endElement(String elementName) throws TransletException;
+    public void characters(String characters) throws TransletException;
     public void characters(char[] characters, int offset, int length)
 	throws TransletException;
     public void attribute(String attributeName, String attributeValue)
@@ -86,5 +87,10 @@
     public void omitHeader(boolean value);
     public boolean setEscaping(boolean escape) throws TransletException;
     public void setCdataElements(Hashtable elements);
+    public void setDoctype(String system, String pub);
+    public void setMediaType(String mediaType);
+    public void setStandalone(String standalone);
+    public void setVersion(String version);
     public void close();
+
 }
diff --git a/src/org/apache/xalan/xsltc/cmdline/Compile.java b/src/org/apache/xalan/xsltc/cmdline/Compile.java
index c7598a2..89d317e 100644
--- a/src/org/apache/xalan/xsltc/cmdline/Compile.java
+++ b/src/org/apache/xalan/xsltc/cmdline/Compile.java
@@ -80,6 +80,12 @@
 
 public final class Compile {
 
+    // Versioning numbers  for the compiler -v option output
+    private static int VERSION_MAJOR = 1;
+    private static int VERSION_MINOR = 1;
+    private static int VERSION_DELTA = 0;
+ 
+
     // This variable should be set to false to prevent any methods in this 
     // class from calling System.exit(). As this is a command-line tool,
     // calling System.exit() is normally OK, but we also want to allow for
@@ -87,7 +93,11 @@
     private static boolean _allowExit = true;
 
     public static void printUsage() {
-	System.err.println(new ErrorMsg(ErrorMsg.COMPILE_USAGE_STR));
+        StringBuffer vers = new StringBuffer("XSLTC version " + 
+	    VERSION_MAJOR + "." + VERSION_MINOR + 
+	    ((VERSION_DELTA > 0) ? ("."+VERSION_DELTA) : ("")));
+	System.err.println(vers + "\n" + 
+		new ErrorMsg(ErrorMsg.COMPILE_USAGE_STR));
 	if (_allowExit) System.exit(-1);
     }
 
@@ -103,8 +113,7 @@
 	    boolean inputIsURL = false;
 	    boolean useStdIn = false;
 	    boolean classNameSet = false;
-
-	    final GetOpt getopt = new GetOpt(args, "o:d:j:p:uxhsi");
+	    final GetOpt getopt = new GetOpt(args, "o:d:j:p:uxhsinv");
 	    if (args.length < 1) printUsage();
 
 	    final XSLTC xsltc = new XSLTC();
@@ -138,6 +147,11 @@
 		case 's':
 		    _allowExit = false;
 		    break;
+		case 'n':
+		    xsltc.setTemplateInlining(false);
+		    break;
+		case 'v':
+		    // fall through to case h
 		case 'h':
 		default:
 		    printUsage();
diff --git a/src/org/apache/xalan/xsltc/cmdline/Transform.java b/src/org/apache/xalan/xsltc/cmdline/Transform.java
index 55ac4e2..57b6430 100644
--- a/src/org/apache/xalan/xsltc/cmdline/Transform.java
+++ b/src/org/apache/xalan/xsltc/cmdline/Transform.java
@@ -92,8 +92,13 @@
 import org.apache.xalan.xsltc.dom.DTDMonitor;
 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
 
+import org.apache.xalan.xsltc.runtime.output.*;
+
 final public class Transform {
 
+    // Temporary
+    static private boolean _useOldOutputSystem = false;
+
     private TransletOutputHandler _handler;
 
     private String  _fileName;
@@ -102,15 +107,17 @@
     private boolean _isJarFileSpecified = false;
     private Vector  _params = null;
     private boolean _uri, _debug;
+    private int     _iterations;
 
     private static boolean _allowExit = true;
 
     public Transform(String className, String fileName,
-		     boolean uri, boolean debug) {
+		     boolean uri, boolean debug, int iterations) {
 	_fileName = fileName;
 	_className = className;
 	_uri = uri;
 	_debug = debug;
+	_iterations = iterations;
     }
 
     public void setParameters(Vector params) {
@@ -196,18 +203,31 @@
 	    }
 
 	    // Transform the document
-	    String encoding = _translet._encoding;
+	    TransletOutputHandlerFactory tohFactory = 
+		TransletOutputHandlerFactory.newInstance();
+	    tohFactory.setOutputType(TransletOutputHandlerFactory.STREAM);
+	    tohFactory.setEncoding(_translet._encoding);
+	    tohFactory.setOutputMethod(_translet._method);
 
-	    // Create our default SAX/DTD handler
-	    DefaultSAXOutputHandler saxHandler =
-		new DefaultSAXOutputHandler(System.out, encoding);
-	    // Create a translet output handler and plug in the SAX/DTD handler
-	    TextOutput textOutput =
-		new TextOutput((ContentHandler)saxHandler,
-			       (LexicalHandler)saxHandler, encoding);
+	    if (_iterations == -1) {
+		translet.transform(dom, _useOldOutputSystem ?
+					tohFactory.getOldTransletOutputHandler() :
+					tohFactory.getTransletOutputHandler());
+	    }
+	    else if (_iterations > 0) {
+		long mm = System.currentTimeMillis();
+		for (int i = 0; i < _iterations; i++) {
+		    translet.transform(dom, _useOldOutputSystem ?
+					    tohFactory.getOldTransletOutputHandler() :
+					    tohFactory.getTransletOutputHandler());
+		}
+		mm = System.currentTimeMillis() - mm;
 
-	    // Transform and pass output to the translet output handler
-	    translet.transform(dom, textOutput);
+		System.err.println("\n<!--");
+		System.err.println("  transform  = " + (mm / _iterations) + " ms");
+		System.err.println("  throughput = " + (1000.0 / (mm / _iterations)) + " tps");
+		System.err.println("-->");
+	    }
 	}
 	catch (TransletException e) {
 	    if (_debug) e.printStackTrace();
@@ -279,6 +299,7 @@
 	try {
 	    if (args.length > 0) {
 		int i;
+		int iterations = -1;
 		boolean uri = false, debug = false;
 		boolean isJarFileSpecified = false;
 		String  jarFile = null;
@@ -298,6 +319,17 @@
 			isJarFileSpecified = true;	
 			jarFile = args[++i];
 		    }
+		    else if (args[i].equals("-e")) {
+			_useOldOutputSystem = true;
+		    }
+		    else if (args[i].equals("-n")) {
+			try {
+			    iterations = Integer.parseInt(args[++i]);
+			}
+			catch (NumberFormatException e) {
+			    // ignore
+			}
+		    }
 		    else {
 			printUsage();
 		    }
@@ -307,7 +339,8 @@
 		if (args.length - i < 2) printUsage();
 
 		// Get document file and class name
-		Transform handler = new Transform(args[i+1],args[i],uri,debug);
+		Transform handler = new Transform(args[i+1], args[i], uri,
+		    debug, iterations);
 		handler.setJarFileInputSrc(isJarFileSpecified,	jarFile);
 
 		// Parse stylesheet parameters
diff --git a/src/org/apache/xalan/xsltc/compiler/AbsolutePathPattern.java b/src/org/apache/xalan/xsltc/compiler/AbsolutePathPattern.java
index 665b0ad..cf03c43 100644
--- a/src/org/apache/xalan/xsltc/compiler/AbsolutePathPattern.java
+++ b/src/org/apache/xalan/xsltc/compiler/AbsolutePathPattern.java
@@ -123,31 +123,44 @@
 	    else {
 		_left.translate(classGen, methodGen);
 	    }
-	    _trueList.append(_left._trueList);
-	    _falseList.append(_left._falseList);
 	}
+
 	final int getParent = cpg.addInterfaceMethodref(DOM_INTF,
 							GET_PARENT,
 							GET_PARENT_SIG);
 	final int getType = cpg.addInterfaceMethodref(DOM_INTF,
 						      "getType", "(I)I");
-	il.append(methodGen.loadDOM());
+
+	InstructionHandle begin = il.append(methodGen.loadDOM());
 	il.append(SWAP);
 	il.append(new INVOKEINTERFACE(getParent, 2));
-	if (_left instanceof AncestorPattern) {
+	if (_left instanceof AncestorPattern) {	
 	    il.append(methodGen.loadDOM());
 	    il.append(SWAP);
 	}
 	il.append(new INVOKEINTERFACE(getType, 2));
 	il.append(new PUSH(cpg, DOM.ROOT));
 	
-	// long jump: _falseList.add(il.append(new IF_ICMPNE(null)));
 	final BranchHandle skip = il.append(new IF_ICMPEQ(null));
 	_falseList.add(il.append(new GOTO_W(null)));
 	skip.setTarget(il.append(NOP));
+
+	if (_left != null) {
+	    _left.backPatchTrueList(begin);
+	    
+	    /*
+	     * If _left is an ancestor pattern, backpatch this pattern's false
+	     * list to the loop that searches for more ancestors.
+	     */
+	    if (_left instanceof AncestorPattern) {
+		final AncestorPattern ancestor = (AncestorPattern) _left;
+		_falseList.backPatch(ancestor.getLoopHandle());		// clears list
+	    }
+	    _falseList.append(_left._falseList);
+	}
     }
 	
     public String toString() {
-	return "absolutePathPattern(" + (_left!=null ? _left.toString() : ")");
+	return "absolutePathPattern(" + (_left != null ? _left.toString() : ")");
     }
 }
diff --git a/src/org/apache/xalan/xsltc/compiler/AncestorPattern.java b/src/org/apache/xalan/xsltc/compiler/AncestorPattern.java
index f99b678..9fe38ae 100644
--- a/src/org/apache/xalan/xsltc/compiler/AncestorPattern.java
+++ b/src/org/apache/xalan/xsltc/compiler/AncestorPattern.java
@@ -69,8 +69,10 @@
 import org.apache.xalan.xsltc.compiler.util.*;
 
 final class AncestorPattern extends RelativePathPattern {
+
     private final Pattern _left;	// may be null
     private final RelativePathPattern _right;
+    private InstructionHandle _loop;
 		
     public AncestorPattern(RelativePathPattern right) {
 	this(null, right);
@@ -84,6 +86,10 @@
 	}
     }
 	
+    public InstructionHandle getLoopHandle() {
+	return _loop;
+    }
+
     public void setParser(Parser parser) {
 	super.setParser(parser);
 	if (_left != null) {
@@ -106,17 +112,23 @@
     }
 	
     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
-	if (_left != null) _left.typeCheck(stable);
+	if (_left != null) {
+	    _left.typeCheck(stable);
+	}
 	return _right.typeCheck(stable);
     }
 
     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
-	InstructionHandle loop, eloop;
+	InstructionHandle parent;
 	final ConstantPoolGen cpg = classGen.getConstantPool();
 	final InstructionList il = methodGen.getInstructionList();
+
+	/* 
+	 * The scope of this local var must be the entire method since
+	 * a another pattern may decide to jump back into the loop
+	 */
 	final LocalVariableGen local =
-	    methodGen.addLocalVariable2("app", 
-					Util.getJCRefType(NODE_SIG),
+	    methodGen.addLocalVariable2("app", Util.getJCRefType(NODE_SIG),
 					il.getEnd());
 
 	final org.apache.bcel.generic.Instruction loadLocal =
@@ -133,13 +145,18 @@
 	}
 	else {
 	    _right.translate(classGen, methodGen);
+
+	    if (_right instanceof AncestorPattern) {
+		il.append(methodGen.loadDOM());
+		il.append(SWAP);
+	    }
 	}
 
 	if (_left != null) {
 	    final int getParent = cpg.addInterfaceMethodref(DOM_INTF,
 							    GET_PARENT,
 							    GET_PARENT_SIG);
-	    loop = il.append(new INVOKEINTERFACE(getParent, 2));
+	    parent = il.append(new INVOKEINTERFACE(getParent, 2));
 	    
 	    il.append(DUP);
 	    il.append(storeLocal);
@@ -148,11 +165,10 @@
 
 	    _left.translate(classGen, methodGen);
 
-
 	    final SyntaxTreeNode p = getParent();
-	    if ((p == null) || 
-		(p instanceof Instruction) ||
-		(p instanceof TopLevelElement)) {
+	    if (p == null || p instanceof Instruction ||
+		p instanceof TopLevelElement) 
+	    {
 		// do nothing
 	    }
 	    else {
@@ -160,19 +176,27 @@
 	    }
 
 	    final BranchHandle exit = il.append(new GOTO(null));
-	    eloop = il.append(methodGen.loadDOM());
+	    _loop = il.append(methodGen.loadDOM());
 	    il.append(loadLocal);
-	    local.setEnd(eloop);
-	    il.append(new GOTO(loop));
+	    local.setEnd(_loop);
+	    il.append(new GOTO(parent));
 	    exit.setTarget(il.append(NOP));
-	    _left.backPatchFalseList(eloop);
+	    _left.backPatchFalseList(_loop);
 
 	    _trueList.append(_left._trueList);	
 	}
 	else {
 	    il.append(POP2);
 	}
-	methodGen.removeLocalVariable(local);
+	
+	/* 
+	 * If _right is an ancestor pattern, backpatch this pattern's false
+	 * list to the loop that searches for more ancestors.
+	 */
+	if (_right instanceof AncestorPattern) {
+	    final AncestorPattern ancestor = (AncestorPattern) _right;
+	    _falseList.backPatch(ancestor.getLoopHandle());    // clears list
+	}
 
 	_trueList.append(_right._trueList);
 	_falseList.append(_right._falseList);
diff --git a/src/org/apache/xalan/xsltc/compiler/ApplyImports.java b/src/org/apache/xalan/xsltc/compiler/ApplyImports.java
index 852b0bc..5d41236 100644
--- a/src/org/apache/xalan/xsltc/compiler/ApplyImports.java
+++ b/src/org/apache/xalan/xsltc/compiler/ApplyImports.java
@@ -136,7 +136,7 @@
 	// Indicate to the top-level stylesheet that all templates must be
 	// compiled into separate methods.
 	Stylesheet stylesheet = getStylesheet();
-	stylesheet.compileTemplatesAsMethods();
+	stylesheet.setTemplateInlining(false);
 
 	// Get the mode we are currently in (might not be any)
 	Template template = getTemplate();
diff --git a/src/org/apache/xalan/xsltc/compiler/ApplyTemplates.java b/src/org/apache/xalan/xsltc/compiler/ApplyTemplates.java
index b0143cb..746f0cd 100644
--- a/src/org/apache/xalan/xsltc/compiler/ApplyTemplates.java
+++ b/src/org/apache/xalan/xsltc/compiler/ApplyTemplates.java
@@ -106,7 +106,7 @@
 	}
 	
 	if (mode.length() > 0) {
-	    _modeName = parser.getQName(mode);
+	    _modeName = parser.getQNameIgnoreDefaultNs(mode);
 	}
 	
 	// instantiate Mode if needed, cache (apply temp) function name
@@ -139,6 +139,7 @@
      * some template in the stylesheet uses parameters. 
      */
     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
+	boolean setStartNodeCalled = false;
 	final Stylesheet stylesheet = classGen.getStylesheet();
 	final ConstantPoolGen cpg = classGen.getConstantPool();
 	final InstructionList il = methodGen.getInstructionList();
@@ -165,6 +166,7 @@
 	    translateContents(classGen, methodGen);
 	}
 
+
 	il.append(classGen.loadTranslet());
 
 	// The 'select' expression is a result-tree
@@ -192,6 +194,7 @@
 							     NODE_ITERATOR_SIG);
 		il.append(methodGen.loadCurrentNode());
 		il.append(new INVOKEINTERFACE(setStartNode,2));
+		setStartNodeCalled = true;	
 	    }
 	    else {
 		if (_select == null)
@@ -201,7 +204,7 @@
 	    }
 	}
 
-	if (_select != null) {
+	if (_select != null && !setStartNodeCalled) {
 	    _select.startResetIterator(classGen, methodGen);
 	}
 
diff --git a/src/org/apache/xalan/xsltc/compiler/AttributeSet.java b/src/org/apache/xalan/xsltc/compiler/AttributeSet.java
index b484604..6bbba08 100644
--- a/src/org/apache/xalan/xsltc/compiler/AttributeSet.java
+++ b/src/org/apache/xalan/xsltc/compiler/AttributeSet.java
@@ -84,6 +84,7 @@
     // Element contents
     private QName            _name;
     private UseAttributeSets _useSets;
+    private AttributeSet     _mergeSet;
     private String           _method;
     private boolean          _ignore = false;
     
@@ -119,7 +120,7 @@
     public void parseContents(Parser parser) {
 	
 	// Get this attribute set's name
-	_name = parser.getQName(getAttribute("name"));
+	_name = parser.getQNameIgnoreDefaultNs(getAttribute("name"));
 	if ((_name == null) || (_name.equals(EMPTYSTRING))) {
 	    ErrorMsg msg = new ErrorMsg(ErrorMsg.UNNAMED_ATTRIBSET_ERR, this);
 	    parser.reportError(Constants.ERROR, msg);
@@ -161,15 +162,10 @@
 
 	if (_ignore) return (Type.Void);
 
-	final AttributeSet other = stable.addAttributeSet(this);
-	if (other != null) {
-	    _method = other.getMethodName();
-	    merge(other);
-	    other.ignore();
-	}
-	else {
-	    _method = AttributeSetPrefix + getXSLTC().nextAttributeSetSerial();
-	}
+        // _mergeSet Point to any previous definition of this attribute set
+	_mergeSet = stable.addAttributeSet(this);
+
+	_method = AttributeSetPrefix + getXSLTC().nextAttributeSetSerial();
 
 	if (_useSets != null) _useSets.typeCheck(stable);
 	typeCheckContents(stable);
@@ -177,26 +173,6 @@
     }
 
     /**
-     * Merge this attribute set with some other one
-     */
-    private void merge(AttributeSet other) {
-	// Both attribute sets may inherit from other sets...
-	if (_useSets == null)
-	    _useSets = other._useSets;
-	else
-	    _useSets.addAttributeSets(other.getAttribute("use-attribute-sets"));
-
-	// Merge the contents of the two attribute sets...
-	final Enumeration attributes = other.elements();
-	while (attributes.hasMoreElements()) {
-	    SyntaxTreeNode element = (SyntaxTreeNode)attributes.nextElement();
-	    if (element instanceof XslAttribute) {
-		setFirstElement((XslAttribute)element);
-	    }
-	}
-    }
-
-    /**
      * Compile a method that outputs the attributes in this set
      */
     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
@@ -206,6 +182,21 @@
 	// Create a new method generator for an attribute set method
 	methodGen = new AttributeSetMethodGenerator(_method, classGen);
 
+        // Generate a reference to previous attribute-set definitions with the
+        // same name first.  Those later in the stylesheet take precedence.
+        if (_mergeSet != null) {
+            final ConstantPoolGen cpg = classGen.getConstantPool();
+            final InstructionList il = methodGen.getInstructionList();
+            final String methodName = _mergeSet.getMethodName();
+
+            il.append(classGen.loadTranslet());
+            il.append(methodGen.loadHandler());
+            il.append(methodGen.loadIterator());
+            final int method = cpg.addMethodref(classGen.getClassName(),
+                                                methodName, ATTR_SET_SIG);
+            il.append(new INVOKESPECIAL(method));
+        }
+
 	// Translate other used attribute sets first, as local attributes
 	// take precedence (last attributes overrides first)
 	if (_useSets != null) _useSets.translate(classGen, methodGen);
diff --git a/src/org/apache/xalan/xsltc/compiler/AttributeValue.java b/src/org/apache/xalan/xsltc/compiler/AttributeValue.java
index 64c0340..8f33670 100644
--- a/src/org/apache/xalan/xsltc/compiler/AttributeValue.java
+++ b/src/org/apache/xalan/xsltc/compiler/AttributeValue.java
@@ -71,16 +71,16 @@
 
 	AttributeValue result;
 	if (text.indexOf('{') != -1) {
-	    result = new AttributeValueTemplate(text, parser);
+	    result = new AttributeValueTemplate(text, parser, parent);
 	}
 	else if (text.indexOf('}') != -1) {
-	    result = new AttributeValueTemplate(text, parser);
+	    result = new AttributeValueTemplate(text, parser, parent);
 	}
 	else {
 	    result = new SimpleAttributeValue(text);
 	    result.setParser(parser);
+	    result.setParent(parent);
 	}
-	result.setParent(parent);
 	return result;
     }
 }
diff --git a/src/org/apache/xalan/xsltc/compiler/AttributeValueTemplate.java b/src/org/apache/xalan/xsltc/compiler/AttributeValueTemplate.java
index 49f2e20..00d981d 100644
--- a/src/org/apache/xalan/xsltc/compiler/AttributeValueTemplate.java
+++ b/src/org/apache/xalan/xsltc/compiler/AttributeValueTemplate.java
@@ -72,10 +72,14 @@
 
 final class AttributeValueTemplate extends AttributeValue {
 
-    public AttributeValueTemplate(String value, Parser parser) {
+    public AttributeValueTemplate(String value, Parser parser, 
+	SyntaxTreeNode parent) 
+    {
+	setParent(parent);
 	setParser(parser);
-	if (check(value, parser))
+	if (check(value, parser)) {
 	    parseAVTemplate(0, value, parser);
+	}
     }
 
     private void parseAVTemplate(final int start, String text, Parser parser) {
diff --git a/src/org/apache/xalan/xsltc/compiler/CallTemplate.java b/src/org/apache/xalan/xsltc/compiler/CallTemplate.java
index 84b1e4d..00ff83e 100644
--- a/src/org/apache/xalan/xsltc/compiler/CallTemplate.java
+++ b/src/org/apache/xalan/xsltc/compiler/CallTemplate.java
@@ -87,7 +87,7 @@
     }
 
     public void parseContents(Parser parser) {
-	_name = parser.getQName(getAttribute("name"));
+	_name = parser.getQNameIgnoreDefaultNs(getAttribute("name"));
 	parseChildren(parser);
     }
 		
diff --git a/src/org/apache/xalan/xsltc/compiler/CastExpr.java b/src/org/apache/xalan/xsltc/compiler/CastExpr.java
index cec15f5..8063340 100644
--- a/src/org/apache/xalan/xsltc/compiler/CastExpr.java
+++ b/src/org/apache/xalan/xsltc/compiler/CastExpr.java
@@ -88,25 +88,16 @@
 
 	InternalTypeMap.put(Type.Real, Type.Real);
 	InternalTypeMap.put(Type.Real, Type.Int);
-	InternalTypeMap.put(Type.Real, Type.Lng);
 	InternalTypeMap.put(Type.Real, Type.Boolean);
 	InternalTypeMap.put(Type.Real, Type.String);
 	InternalTypeMap.put(Type.Real, Type.Reference);
 
 	InternalTypeMap.put(Type.Int, Type.Int);
 	InternalTypeMap.put(Type.Int, Type.Real);
-	InternalTypeMap.put(Type.Int, Type.Lng);
 	InternalTypeMap.put(Type.Int, Type.Boolean);
 	InternalTypeMap.put(Type.Int, Type.String);
 	InternalTypeMap.put(Type.Int, Type.Reference);
 
-	// GTM, bug 3592 fix. 
-	InternalTypeMap.put(Type.Lng, Type.Int);
-	InternalTypeMap.put(Type.Lng, Type.Real);
-	InternalTypeMap.put(Type.Lng, Type.Boolean);
-	InternalTypeMap.put(Type.Lng, Type.String);
-	InternalTypeMap.put(Type.Lng, Type.Reference);
-
 	InternalTypeMap.put(Type.String, Type.String);
 	InternalTypeMap.put(Type.String, Type.Boolean);
 	InternalTypeMap.put(Type.String, Type.Real);
@@ -140,6 +131,7 @@
 	InternalTypeMap.put(Type.Reference, Type.String);
 	InternalTypeMap.put(Type.Reference, Type.Node);
 	InternalTypeMap.put(Type.Reference, Type.NodeSet);
+	InternalTypeMap.put(Type.Reference, Type.ResultTree);
 
 	InternalTypeMap.put(Type.Void, Type.String);
     }
diff --git a/src/org/apache/xalan/xsltc/compiler/Constants.java b/src/org/apache/xalan/xsltc/compiler/Constants.java
index 6772185..12258b1 100644
--- a/src/org/apache/xalan/xsltc/compiler/Constants.java
+++ b/src/org/apache/xalan/xsltc/compiler/Constants.java
@@ -127,6 +127,8 @@
 	= org.apache.bcel.Constants.ACC_PRIVATE;
     public static final int ACC_PROTECTED 
 	= org.apache.bcel.Constants.ACC_PROTECTED;
+    public static final int ACC_STATIC 
+	= org.apache.bcel.Constants.ACC_STATIC;
 
     public static final String STRING_SIG         
 	= "Ljava/lang/String;";
@@ -147,6 +149,8 @@
 	= "int";
     public static final String NODE_ITERATOR      
 	= "org.apache.xalan.xsltc.NodeIterator";
+    public static final String NODE_ITERATOR_BASE
+	= "org.apache.xalan.xsltc.dom.NodeIteratorBase";
     public static final String SORT_ITERATOR      
 	= "org.apache.xalan.xsltc.dom.SortingIterator";
     public static final String SORT_ITERATOR_SIG     
@@ -169,10 +173,6 @@
 	= "org/apache/xalan/xsltc/TransletOutputHandler";
     public static final String OUTPUT_HANDLER_SIG
 	= "Lorg/apache/xalan/xsltc/TransletOutputHandler;";
-    public static final String TEXT_OUTPUT
-	= "org/apache/xalan/xsltc/runtime/TextOutput";
-    public static final String TEXT_OUTPUT_SIG
-	= "Lorg/apache/xalan/xsltc/runtime/TextOutput;";
     public static final String FILTER_INTERFACE   
 	= "org.apache.xalan.xsltc.dom.Filter";
     public static final String FILTER_INTERFACE_SIG   
@@ -286,8 +286,6 @@
 	= "java.lang.Double";
     public static final String INTEGER_CLASS      
 	= "java.lang.Integer";
-    public static final String LONG_CLASS      
-	= "java.lang.Long";
     public static final String RUNTIME_NODE_CLASS 
 	= "org.apache.xalan.xsltc.runtime.Node";
     public static final String MATH_CLASS         
@@ -301,10 +299,6 @@
 	= "intValue";
     public static final String INT_VALUE_SIG      
 	= "()I";
-    public static final String LONG_VALUE          
-	= "longValue";
-    public static final String LONG_VALUE_SIG      
-	= "()J";
     public static final String DOUBLE_VALUE       
 	= "doubleValue";
     public static final String DOUBLE_VALUE_SIG   
@@ -486,6 +480,10 @@
     public static final int POSITION_INDEX = 2;
     public static final int LAST_INDEX     = 3;
 
+    public static final String XMLNS_PREFIX = "xmlns";
+    public static final String XMLNS_STRING = "xmlns:";
+    public static final String XMLNS_URI 
+	= "http://www.w3.org/2000/xmlns/";
     public static final String XSLT_URI
 	= "http://www.w3.org/1999/XSL/Transform";
     public static final String XHTML_URI
diff --git a/src/org/apache/xalan/xsltc/compiler/DecimalFormatting.java b/src/org/apache/xalan/xsltc/compiler/DecimalFormatting.java
index 874e031..c4fa876 100644
--- a/src/org/apache/xalan/xsltc/compiler/DecimalFormatting.java
+++ b/src/org/apache/xalan/xsltc/compiler/DecimalFormatting.java
@@ -84,7 +84,7 @@
     private static final String DFS_CLASS = "java.text.DecimalFormatSymbols";
     private static final String DFS_SIG   = "Ljava/text/DecimalFormatSymbols;";
 
-    private String _name = null;
+    private QName _name = null;
 
     /**
      * No type check needed for the <xsl:decimal-formatting/> element
@@ -98,14 +98,20 @@
      */
     public void parseContents(Parser parser) {
 	// Get the name of these decimal formatting symbols
-	if ((_name = getAttribute("name")) == null) _name = EMPTYSTRING;
+	_name = parser.getQNameIgnoreDefaultNs(getAttribute("name"));
+	if (_name == null) {
+	    _name = parser.getQNameIgnoreDefaultNs(EMPTYSTRING);
+	}
 
 	// Check if a set of symbols has already been registered under this name
 	SymbolTable stable = parser.getSymbolTable();
-	if (stable.getDecimalFormatting(_name) != null)
-	    reportWarning(this, parser, ErrorMsg.SYMBOLS_REDEF_ERR,_name.toString());
-	else
+	if (stable.getDecimalFormatting(_name) != null) {
+	    reportWarning(this, parser, ErrorMsg.SYMBOLS_REDEF_ERR,
+		_name.toString());
+	}
+	else {
 	    stable.addDecimalFormatting(_name, this);
+	}
     }
 
     /**
@@ -122,7 +128,7 @@
 
 	// Push the format name on the stack for call to addDecimalFormat()
 	il.append(classGen.loadTranslet());
-	il.append(new PUSH(cpg, _name));
+	il.append(new PUSH(cpg, _name.toString()));
 
 	// Manufacture a DecimalFormatSymbols on the stack
 	// for call to addDecimalFormat()
diff --git a/src/org/apache/xalan/xsltc/compiler/DocumentCall.java b/src/org/apache/xalan/xsltc/compiler/DocumentCall.java
index 0817a06..8ff7f49 100644
--- a/src/org/apache/xalan/xsltc/compiler/DocumentCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/DocumentCall.java
@@ -120,7 +120,15 @@
 	// Parse the second argument - the document URI base
 	if (ac == 2) {
 	    _base = argument(1);
-	    if (!_base.typeCheck(stable).identicalTo(Type.NodeSet)) {
+	    final Type baseType = _base.typeCheck(stable);
+	    
+	    if (baseType.identicalTo(Type.Node)) {
+		_base = new CastExpr(_base, Type.NodeSet);
+	    }
+	    else if (baseType.identicalTo(Type.NodeSet)) {
+		// falls through
+	    }
+	    else {
 		ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
 		throw new TypeCheckError(msg);
 	    }
diff --git a/src/org/apache/xalan/xsltc/compiler/ElementAvailableCall.java b/src/org/apache/xalan/xsltc/compiler/ElementAvailableCall.java
index 97e3f3c..55d0e73 100644
--- a/src/org/apache/xalan/xsltc/compiler/ElementAvailableCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/ElementAvailableCall.java
@@ -88,13 +88,30 @@
     }
 
     /**
+     * Returns an object representing the compile-time evaluation 
+     * of an expression. We are only using this for function-available
+     * and element-available at this time.
+     */
+    public Object evaluateAtCompileTime() {
+	return getResult() ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    /**
      * Returns the result that this function will return
      */
     public boolean getResult() {
-	final Parser parser = getParser();
-	final LiteralExpr arg = (LiteralExpr)argument();
-	final QName qname = parser.getQName(arg.getValue());
-	return(parser.elementSupported(qname));
+	try {
+	    final LiteralExpr arg = (LiteralExpr) argument();
+	    final String qname = arg.getValue();
+	    final int index = qname.indexOf(':');
+	    final String localName = (index > 0) ? 
+		qname.substring(index + 1) : qname;
+	    return getParser().elementSupported(arg.getNamespace(), 
+					        localName);
+	}
+	catch (ClassCastException e) {
+	    return false;
+	}
     }
 
     /**
diff --git a/src/org/apache/xalan/xsltc/compiler/EqualityExpr.java b/src/org/apache/xalan/xsltc/compiler/EqualityExpr.java
index 4b8bb9b..6af9494 100644
--- a/src/org/apache/xalan/xsltc/compiler/EqualityExpr.java
+++ b/src/org/apache/xalan/xsltc/compiler/EqualityExpr.java
@@ -101,10 +101,7 @@
     }
 
     public boolean getOp() {
-	if (_op == Operators.NE)
-	    return false;
-	else
-	    return true;
+	return (_op != Operators.NE);
     }
 
     /**
diff --git a/src/org/apache/xalan/xsltc/compiler/Expression.java b/src/org/apache/xalan/xsltc/compiler/Expression.java
index 3da80c6..6b58c8f 100644
--- a/src/org/apache/xalan/xsltc/compiler/Expression.java
+++ b/src/org/apache/xalan/xsltc/compiler/Expression.java
@@ -103,7 +103,7 @@
     public abstract String toString();
 
     public boolean hasPositionCall() {
-	return true;
+	return false;		// default should be 'false' for StepPattern
     }
 
     public boolean hasLastCall() {
@@ -111,6 +111,15 @@
     }
 		
     /**
+     * Returns an object representing the compile-time evaluation 
+     * of an expression. We are only using this for function-available
+     * and element-available at this time.
+     */
+    public Object evaluateAtCompileTime() {
+	return null;
+    }
+
+    /**
      * Type check all the children of this node.
      */
     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
diff --git a/src/org/apache/xalan/xsltc/compiler/FilterParentPath.java b/src/org/apache/xalan/xsltc/compiler/FilterParentPath.java
index 1562c60..4f320b7 100644
--- a/src/org/apache/xalan/xsltc/compiler/FilterParentPath.java
+++ b/src/org/apache/xalan/xsltc/compiler/FilterParentPath.java
@@ -149,9 +149,9 @@
 
 	// This is a special case for the //* path with or without predicates
         if (_hasDescendantAxis) {
-	    final int incl = cpg.addMethodref(STEP_ITERATOR_CLASS,
+	    final int incl = cpg.addMethodref(NODE_ITERATOR_BASE,
 					      "includeSelf",
-					      "()"+NODE_ITERATOR_SIG);
+					      "()" + NODE_ITERATOR_SIG);
 	    il.append(new INVOKEVIRTUAL(incl));
 	}
 
diff --git a/src/org/apache/xalan/xsltc/compiler/FormatNumberCall.java b/src/org/apache/xalan/xsltc/compiler/FormatNumberCall.java
index 9558f1a..b4ee8e2 100644
--- a/src/org/apache/xalan/xsltc/compiler/FormatNumberCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/FormatNumberCall.java
@@ -74,6 +74,7 @@
     private Expression _value;
     private Expression _format;
     private Expression _name;
+    private QName      _resolvedQName = null;
 
     public FormatNumberCall(QName fname, Vector arguments) {
 	super(fname, arguments);
@@ -83,9 +84,8 @@
     }
 
     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
-	// The stylesheet element only adds code to instanciate the
-	// default DecimalFormat object if at least one format-number()
-	// call exists in the stylesheet. We must signal this call...
+
+	// Inform stylesheet to instantiate a DecimalFormat object
 	getStylesheet().numberFormattingUsed();
 
 	final Type tvalue = _value.typeCheck(stable);
@@ -97,8 +97,14 @@
 	    _format = new CastExpr(_format, Type.String);
 	}
 	if (argumentCount() == 3) {
-	    final Type tname = _format.typeCheck(stable);
-	    if (tname instanceof StringType == false) {
+	    final Type tname = _name.typeCheck(stable);
+
+	    if (_name instanceof LiteralExpr) {
+		final LiteralExpr literal = (LiteralExpr) _name;
+		_resolvedQName = 
+		    getParser().getQNameIgnoreDefaultNs(literal.getValue());
+	    }
+	    else if (tname instanceof StringType == false) {
 		_name = new CastExpr(_name, Type.String);
 	    }
 	}
@@ -126,6 +132,9 @@
 	if (_name == null) {
 	    il.append(new PUSH(cpg, EMPTYSTRING));
 	}
+	else if (_resolvedQName != null) {
+	    il.append(new PUSH(cpg, _resolvedQName.toString()));
+	}
 	else {
 	    _name.translate(classGen, methodGen);
 	}
diff --git a/src/org/apache/xalan/xsltc/compiler/FunctionAvailableCall.java b/src/org/apache/xalan/xsltc/compiler/FunctionAvailableCall.java
index 1e6aafc..35e0501 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,36 +64,190 @@
 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 Expression _arg; 
+    private String     _nameOfFunct = null; 
+    private String     _namespaceOfFunct = null; 	
+    private boolean    _isFunctionAvailable = false; 
+
+    /**
+     * 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. 
+     */
     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.startsWith(JAVA_EXT_XSLTC) ||
+		 _namespaceOfFunct.startsWith(JAVA_EXT_XALAN))) 
+	    {
+                _isFunctionAvailable = hasMethods();
+            }
+        }
     }
 
     /**
-     * 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) {
+	if (_type != null) {
+	   return _type;
+	}
+	if (_arg instanceof LiteralExpr) {
 	    return _type = 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
+     * Returns an object representing the compile-time evaluation 
+     * of an expression. We are only using this for function-available
+     * and element-available at this time.
+     */
+    public Object evaluateAtCompileTime() {
+	return getResult() ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    /**
+     * (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);
+
+	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 (_nameOfFunct == null) { 
+	    return false;
+	}
+
+        if (_namespaceOfFunct == null ||
+            _namespaceOfFunct.equals(EMPTYSTRING) ||
+	    _namespaceOfFunct.equals(TRANSLET_URI))
+        {
+            final Parser parser = getParser();
+            _isFunctionAvailable = 
+		parser.functionSupported(Util.getLocalName(_nameOfFunct));
+        }
+ 	return _isFunctionAvailable;
     }
 
     /**
@@ -103,7 +257,7 @@
      */
     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
 	final ConstantPoolGen cpg = classGen.getConstantPool();
-	final boolean result = getResult();
-	methodGen.getInstructionList().append(new PUSH(cpg, result));
+	methodGen.getInstructionList().append(new PUSH(cpg, getResult()));
     }
+
 }
diff --git a/src/org/apache/xalan/xsltc/compiler/FunctionCall.java b/src/org/apache/xalan/xsltc/compiler/FunctionCall.java
index 4bf5be5..50f341b 100644
--- a/src/org/apache/xalan/xsltc/compiler/FunctionCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/FunctionCall.java
@@ -86,10 +86,19 @@
     private final static Vector EMPTY_ARG_LIST = new Vector(0);
 
     // Valid namespaces for Java function-call extension
-    private final static String JAVA_EXT_PREFIX = TRANSLET_URI + "/java";
-    private final static String JAVA_EXT_XALAN =
+    protected final static String EXT_XSLTC = 
+	TRANSLET_URI;
+
+    protected final static String JAVA_EXT_XSLTC = 
+	EXT_XSLTC + "/java";
+
+    protected final static String EXT_XALAN =
+	"http://xml.apache.org/xalan";
+
+    protected final static String JAVA_EXT_XALAN =
 	"http://xml.apache.org/xslt/java";
 
+
     // External Java function's class/method/signature
     private String     _className;
     private Method     _chosenMethod;
@@ -112,6 +121,7 @@
      */
     static {
 	try {
+	    final Class objectClass   = Class.forName("java.lang.Object");
 	    final Class stringClass   = Class.forName("java.lang.String");
 	    final Class nodeClass     = Class.forName("org.w3c.dom.Node");
 	    final Class nodeListClass = Class.forName("org.w3c.dom.NodeList");
@@ -147,6 +157,8 @@
 	    _internal2Java.put(Type.ResultTree, nodeClass);
 	    _internal2Java.put(Type.ResultTree, nodeListClass);
 
+	    _internal2Java.put(Type.Reference, objectClass);
+
 	    // Possible conversions between Java and internal types
 	    _java2Internal.put(Boolean.TYPE, Type.Boolean);
 
@@ -160,6 +172,8 @@
 
 	    _java2Internal.put(stringClass, Type.String);
 
+	    _java2Internal.put(objectClass, Type.Reference);
+
 	    // Conversions from org.w3c.dom.Node/NodeList are not supported
 	}
 	catch (ClassNotFoundException e) {
@@ -170,6 +184,7 @@
     public FunctionCall(QName fname, Vector arguments) {
 	_fname = fname;
 	_arguments = arguments;
+	_type = null;
     }
 
     public FunctionCall(QName fname) {
@@ -192,48 +207,71 @@
 	}
     }
 
+    public String getClassNameFromUri(String uri) 
+	throws TypeCheckError
+    {
+	final int length = 
+	    uri.startsWith(JAVA_EXT_XSLTC) ? JAVA_EXT_XSLTC.length() + 1 :
+	    uri.startsWith(JAVA_EXT_XALAN) ? JAVA_EXT_XALAN.length() + 1 : 0;
+
+	if (length == 0) {
+	    throw new TypeCheckError(this);
+	}
+	return (uri.length() > length) ? uri.substring(length) : EMPTYSTRING;
+    }
+
     /**
      * Type check a function call. Since different type conversions apply,
      * type checking is different for standard and external (Java) functions.
      */
-    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
+    public Type typeCheck(SymbolTable stable) 
+	throws TypeCheckError 
+    {
+	if (_type != null) return _type;
 
 	final String namespace = _fname.getNamespace();
 	final String local = _fname.getLocalPart();
 
-	// XPath functions have no namespace
-	if (isStandard()) {
+	if (isExtension()) {
+	    _fname = new QName(null, null, local);
+	    return typeCheckStandard(stable);
+	}
+	else if (isStandard()) {
 	    return typeCheckStandard(stable);
 	}
 	// Handle extension functions (they all have a namespace)
 	else {
-	    final int len = JAVA_EXT_PREFIX.length();
-	    if (namespace.equals(JAVA_EXT_PREFIX) ||
-		namespace.equals(JAVA_EXT_XALAN)) {
-		final int pos = local.indexOf('.');
-		_className = local.substring(0, pos);
-		_fname = new QName(namespace, null, local.substring(pos+1));
-	    }
-	    else if (namespace.length() >= len &&
-		namespace.substring(0, len).equals(JAVA_EXT_PREFIX)) {
-		_className = namespace.substring(len + 1);
-	    }
-	    else {
-		/*
-		 * Warn user if external function could not be resolved.
-		 * Warning will _NOT_ be issued is the call is properly
-		 * wrapped in an <xsl:if> or <xsl:when> element. For details
-		 * see If.parserContents() and When.parserContents()
-		 */
-		final Parser parser = getParser();
-		if (parser != null) {
-		    reportWarning(this, parser, ErrorMsg.FUNCTION_RESOLVE_ERR,
-				  _fname.toString());
+	    try {
+		_className = getClassNameFromUri(namespace);
+
+		final int pos = local.lastIndexOf('.');
+		if (pos > 0) {
+		    _className = _className + local.substring(0, pos);
+		    _fname = new QName(namespace, null, local.substring(pos + 1));
 		}
-		unresolvedExternal = true;
-		return _type = Type.Void;
+		else {
+		    _fname = new QName(namespace, null, local);
+		}
+		if (_className.length() > 0) {
+		    return typeCheckExternal(stable);
+		}
+	    } catch (TypeCheckError e) {
+		// Falls through
 	    }
-	    return typeCheckExternal(stable);
+
+	    /*
+	     * Warn user if external function could not be resolved.
+	     * Warning will _NOT_ be issued is the call is properly
+	     * wrapped in an <xsl:if> or <xsl:when> element. For details
+	     * see If.parserContents() and When.parserContents()
+	     */
+	    final Parser parser = getParser();
+	    if (parser != null) {
+		reportWarning(this, parser, ErrorMsg.FUNCTION_RESOLVE_ERR,
+			      _fname.toString());
+	    }
+	    unresolvedExternal = true;
+	    return _type = Type.Void;
 	}
     }
 
@@ -243,8 +281,7 @@
      * thrown, then catch it and re-throw it with a new "this".
      */
     public Type typeCheckStandard(SymbolTable stable) throws TypeCheckError {
-
-	_fname.clearNamespace(); // HACK!!!
+	_fname.clearNamespace(); 	// HACK!!!
 
 	final int n = _arguments.size();
 	final Vector argsType = typeCheckArgs(stable);
@@ -367,8 +404,8 @@
      * Update true/false-lists.
      */
     public void translateDesynthesized(ClassGenerator classGen,
-				       MethodGenerator methodGen) {
-
+				       MethodGenerator methodGen) 
+    {
 	Type type = Type.Boolean;
 	if (_chosenMethodType != null)
 	    type = _chosenMethodType.resultType();
@@ -393,7 +430,7 @@
 	int index;
 
 	// Translate calls to methods in the BasisLibrary
-	if (isStandard()) {
+	if (isStandard() || isExtension()) {
 	    for (int i = 0; i < n; i++) {
 		final Expression exp = argument(i);
 		exp.translate(classGen, methodGen);
@@ -442,7 +479,7 @@
 		exp.translate(classGen, methodGen);
 		// Convert the argument to its Java type
 		exp.startResetIterator(classGen, methodGen);
-		exp._type.translateTo(classGen, methodGen, paramTypes[i]);
+		exp.getType().translateTo(classGen, methodGen, paramTypes[i]);
 	    }
 
 	    final StringBuffer buffer = new StringBuffer();
@@ -470,10 +507,13 @@
 
     public boolean isStandard() {
 	final String namespace = _fname.getNamespace();
-	if ((namespace == null) || (namespace.equals(Constants.EMPTYSTRING)))
-	    return true;
-	else
-	    return false;
+	return (namespace == null) || (namespace.equals(Constants.EMPTYSTRING));
+    }
+
+    public boolean isExtension() {
+	final String namespace = _fname.getNamespace();
+	return (namespace != null) && (namespace.equals(EXT_XSLTC) 
+	    || namespace.equals(EXT_XALAN));
     }
 
     /**
@@ -485,7 +525,7 @@
 	Vector result = null;
 	final String namespace = _fname.getNamespace();
 
-	if (namespace.startsWith(JAVA_EXT_PREFIX) ||
+	if (namespace.startsWith(JAVA_EXT_XSLTC) ||
 	    namespace.startsWith(JAVA_EXT_XALAN)) {
 	    final int nArgs = _arguments.size();
 	    try {
diff --git a/src/org/apache/xalan/xsltc/compiler/If.java b/src/org/apache/xalan/xsltc/compiler/If.java
index cc115b0..b51d795 100644
--- a/src/org/apache/xalan/xsltc/compiler/If.java
+++ b/src/org/apache/xalan/xsltc/compiler/If.java
@@ -102,17 +102,11 @@
 	    return;
         }
 
-	// We will ignore the contents of this <xsl:if> if we know that the
-	// test will always return 'false'.
-	if (_test instanceof ElementAvailableCall) {
-	    ElementAvailableCall call = (ElementAvailableCall)_test;
-	    _ignore = !call.getResult();
-	    return;
-	}
-	if (_test instanceof FunctionAvailableCall) {
-	    FunctionAvailableCall call = (FunctionAvailableCall)_test;
-	    _ignore = !call.getResult();
-	    return;
+	// Ignore xsl:if when test is false (function-available() and
+	// element-available())
+	Object result = _test.evaluateAtCompileTime();
+	if (result != null && result instanceof Boolean) {
+	    _ignore = !((Boolean) result).booleanValue();
 	}
 
 	parseChildren(parser);
diff --git a/src/org/apache/xalan/xsltc/compiler/Include.java b/src/org/apache/xalan/xsltc/compiler/Include.java
index 9f50727..e2f6728 100644
--- a/src/org/apache/xalan/xsltc/compiler/Include.java
+++ b/src/org/apache/xalan/xsltc/compiler/Include.java
@@ -65,6 +65,7 @@
 package org.apache.xalan.xsltc.compiler;
 
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.net.URL;
 import java.net.MalformedURLException;
 import java.util.Enumeration;
@@ -88,8 +89,8 @@
 
     public void parseContents(final Parser parser) {
 	final Stylesheet context = parser.getCurrentStylesheet();
+	String docToLoad = getAttribute("href");
 	try {
-	    String docToLoad = getAttribute("href");
 	    if (context.checkForLoop(docToLoad)) {
 		final int errno = ErrorMsg.CIRCULAR_INCLUDE_ERR;
 		final ErrorMsg msg = new ErrorMsg(errno, docToLoad, this);
@@ -106,11 +107,28 @@
 		input = loader.loadSource(docToLoad, currLoadedDoc, xsltc);
 	    }
 	    else {
-		File file = new File(currLoadedDoc);
-		if (file.exists()) currLoadedDoc = "file:"+currLoadedDoc;
-		final URL url = new URL(new URL(currLoadedDoc), docToLoad);
-		docToLoad = url.toString();
-		input = new InputSource(docToLoad);
+		// bug 7835, patch by Stefan Kost (s.kost@webmacher.de)
+		if ((currLoadedDoc != null) && (currLoadedDoc.length() > 0)) {
+		    File file = new File(currLoadedDoc);
+		    if (file.exists()) {
+		        currLoadedDoc = "file:" + file.getCanonicalPath();
+		    }
+		    final URL url = new URL(new URL(currLoadedDoc), docToLoad);
+		    docToLoad = url.toString();
+		    input = new InputSource(docToLoad);
+		}
+		else {
+		    File file = new File(System.getProperty("user.dir"),
+			docToLoad);
+		    if (file.exists()) {
+			docToLoad = "file:" + file.getCanonicalPath();
+		    }
+		    else {
+			throw new FileNotFoundException(
+			  "Could not load file " + docToLoad);
+		    }
+		    input = new InputSource(docToLoad);
+		}
 	    }
 
 	    final SyntaxTreeNode root = parser.parse(input);
@@ -122,6 +140,7 @@
 	    _included.setSystemId(docToLoad);
 	    _included.setParentStylesheet(context);
 	    _included.setIncludingStylesheet(context);
+	    _included.setTemplateInlining(context.getTemplateInlining());
 
 	    // An included stylesheet gets the same import precedence
 	    // as the stylesheet that included it.
@@ -145,6 +164,22 @@
 		}
 	    }
 	}
+	catch (FileNotFoundException e) {
+	    // Update systemId in parent stylesheet for error reporting
+	    context.setSystemId(getAttribute("href"));
+
+	    final ErrorMsg msg = 
+		new ErrorMsg(ErrorMsg.FILE_NOT_FOUND_ERR, docToLoad, this);
+	    parser.reportError(Constants.FATAL, msg);
+	}
+	catch (MalformedURLException e) {
+	    // Update systemId in parent stylesheet for error reporting
+	    context.setSystemId(getAttribute("href"));
+
+	    final ErrorMsg msg = 
+		new ErrorMsg(ErrorMsg.FILE_NOT_FOUND_ERR, docToLoad, this);
+	    parser.reportError(Constants.FATAL, msg);
+	}
 	catch (Exception e) {
 	    e.printStackTrace();
 	}
diff --git a/src/org/apache/xalan/xsltc/compiler/Key.java b/src/org/apache/xalan/xsltc/compiler/Key.java
index e4e9d5e..adc8b66 100644
--- a/src/org/apache/xalan/xsltc/compiler/Key.java
+++ b/src/org/apache/xalan/xsltc/compiler/Key.java
@@ -87,7 +87,7 @@
     public void parseContents(Parser parser) {
 
 	// Get the required attributes and parser XPath expressions
-	_name = parser.getQName(getAttribute("name"));
+	_name = parser.getQNameIgnoreDefaultNs(getAttribute("name"));
 	_match = parser.parsePattern(this, "match", null);
 	_use = parser.parseExpression(this, "use", null);
 
@@ -111,12 +111,7 @@
      * @return The key's name (from the <xsl:key> elements 'name' attribute).
      */
     public String getName() {
-	String name;
-	if (_name.getPrefix() == null)
-	    name = _name.getLocalPart();
-	else
-	    name = _name.getPrefix()+":"+_name.getLocalPart();
-	return(name);
+	return _name.toString();
     }
 
     /**
@@ -191,7 +186,8 @@
 
 	// Prepare to call buildKeyIndex(String name, int node, String value);
 	il.append(classGen.loadTranslet());
-	il.append(new PUSH(cpg, getName()));
+	// il.append(new PUSH(cpg, getName()));
+	il.append(new PUSH(cpg, _name.toString()));
 	il.append(new ILOAD(parentNode.getIndex()));
 
 	// Now get the node value and feck it on the parameter stack
diff --git a/src/org/apache/xalan/xsltc/compiler/KeyCall.java b/src/org/apache/xalan/xsltc/compiler/KeyCall.java
index a7f93c1..00e878f 100644
--- a/src/org/apache/xalan/xsltc/compiler/KeyCall.java
+++ b/src/org/apache/xalan/xsltc/compiler/KeyCall.java
@@ -73,6 +73,7 @@
     private Expression _name;      // The name of this key
     private Expression _value;     // The value to look up in the key/index
     private Type       _valueType; // The value's data type
+    private QName      _resolvedQName = null;
 
     /**
      * Get the parameters passed to function:
@@ -117,7 +118,13 @@
 	// and if it is not it must be converted to one using string() rules.
 	if (_name != null) {
 	    final Type nameType = _name.typeCheck(stable); 
-	    if (!(nameType instanceof StringType)) {
+
+	    if (_name instanceof LiteralExpr) {
+		final LiteralExpr literal = (LiteralExpr) _name;
+		_resolvedQName = 
+		    getParser().getQNameIgnoreDefaultNs(literal.getValue());
+	    }
+	    else if (nameType instanceof StringType == false) {
 		_name = new CastExpr(_name, Type.String);
 	    }
 	}
@@ -241,10 +248,15 @@
 
 	    // Initialise the index specified in the first parameter of key()
 	    il.append(classGen.loadTranslet());
-	    if (_name == null) 
+	    if (_name == null) {
 		il.append(new PUSH(cpg,"##id"));
-	    else
+	    }
+	    else if (_resolvedQName != null) {
+		il.append(new PUSH(cpg, _resolvedQName.toString()));
+	    }
+	    else {
 		_name.translate(classGen, methodGen);
+	    }
 
 	    il.append(new INVOKEVIRTUAL(getKeyIndex));
 	    il.append(new ASTORE(searchIndex.getIndex()));
@@ -265,10 +277,12 @@
 	    il.append(methodGen.loadDOM());
 	    il.append(methodGen.loadCurrentNode());
 	    il.append(new INVOKEINTERFACE(getNodeValue, 2));
-	    if (_name == null)
+	    if (_name == null) {
 		il.append(new INVOKEVIRTUAL(lookupId));
-	    else
+	    }
+	    else {
 		il.append(new INVOKEVIRTUAL(lookupKey));
+	    }
 
 	    // Call to returnIndex.merge(searchIndex);
 	    il.append(new INVOKEVIRTUAL(merge));
@@ -295,10 +309,15 @@
 	    // Call getKeyIndex in AbstractTranslet with the name of the key
 	    // to get the index for this key (which is also a node iterator).
 	    il.append(classGen.loadTranslet());
-	    if (_name == null)
+	    if (_name == null) {
 		il.append(new PUSH(cpg,"##id"));
-	    else
+	    }
+	    else if (_resolvedQName != null) {
+		il.append(new PUSH(cpg, _resolvedQName.toString()));
+	    }
+	    else {
 		_name.translate(classGen, methodGen);
+	    }
 	    il.append(new INVOKEVIRTUAL(getKeyIndex));
 
 	    // Now use the value in the second argument to determine what nodes
@@ -318,10 +337,12 @@
 		_value.translate(classGen, methodGen);
 	    }
 
-	    if (_name == null)
+	    if (_name == null) {
 		il.append(new INVOKEVIRTUAL(lookupId));
-	    else
+	    }
+	    else {
 		il.append(new INVOKEVIRTUAL(lookupKey));
+	    }
 	}
     }
 }
diff --git a/src/org/apache/xalan/xsltc/compiler/LiteralElement.java b/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
index fffa79b..e04db84 100644
--- a/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
+++ b/src/org/apache/xalan/xsltc/compiler/LiteralElement.java
@@ -77,10 +77,11 @@
 import org.apache.xalan.xsltc.compiler.util.*;
 
 final class LiteralElement extends Instruction {
+
     private String _name;
-    private Hashtable _accessedPrefixes = null;
-    private LiteralElement _parent;
+    private LiteralElement _literalElemParent;
     private Vector _attributeElements = null;
+    private Hashtable _accessedPrefixes = null;
 
     private final static String XMLNS_STRING = "xmlns";
 
@@ -119,10 +120,10 @@
 				  SymbolTable stable, boolean declared) {
 
 	// Check if the parent has a declaration for this namespace
-	if (_parent != null) {
-	    final String parentUri = _parent.accessedNamespace(prefix);
+	if (_literalElemParent != null) {
+	    final String parentUri = _literalElemParent.accessedNamespace(prefix);
 	    if (parentUri == null) {
-		_parent.registerNamespace(prefix, uri, stable, declared);
+		_literalElemParent.registerNamespace(prefix, uri, stable, declared);
 		return;
 	    }
 	    if (parentUri.equals(uri)) return;
@@ -139,7 +140,7 @@
 		if (old != null) {
 		    if (old.equals(uri))
 			return;
-		    else
+		    else 
 			prefix = stable.generateNamespacePrefix();
 		}
 	    }
@@ -207,7 +208,6 @@
 	_attributeElements.insertElementAt(attribute,0);
     }
 
-
     /**
      * Type-check the contents of this element. The element itself does not
      * need any type checking as it leaves nothign on the JVM's stack.
@@ -255,23 +255,24 @@
      * Registers all namespaces that are used by the element/attributes
      */
     public void parseContents(Parser parser) {
-
 	final SymbolTable stable = parser.getSymbolTable();
 	stable.setCurrentNode(this);
 
 	// Find the closest literal element ancestor (if there is one)
-	SyntaxTreeNode _parent = getParent();
-	while ((_parent != null) && !(_parent instanceof LiteralElement))
-	    _parent = _parent.getParent();
-	if (!(_parent instanceof LiteralElement))
-	    _parent = null;
+	SyntaxTreeNode _literalElemParent = getParent();
+	while (_literalElemParent != null && !(_literalElemParent instanceof LiteralElement)) {
+	    _literalElemParent = _literalElemParent.getParent();
+	}
+
+	if (!(_literalElemParent instanceof LiteralElement)) {
+	    _literalElemParent = null;
+	}
 
 	_name = translateQName(_qname, stable);
 
 	// Process all attributes and register all namespaces they use
 	final int count = _attributes.getLength();
 	for (int i = 0; i < count; i++) {
-
 	    final QName qname = parser.getQName(_attributes.getQName(i));
 	    final String uri = qname.getNamespace();
 	    final String val = _attributes.getValue(i);
@@ -290,12 +291,17 @@
 	    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 (e.g. xmlns:prefix and xmlns)
+		final String prefix = qname.getPrefix();
+		if (prefix != null && prefix.equals(XMLNS_PREFIX) ||
+		    prefix == null && qname.getLocalPart().equals("xmlns") ||
+		    uri != null && uri.equals(XSLT_URI))
+		{
+		    continue;	
+		}
+
+		// Handle all other literal attributes
 		final String name = translateQName(qname, stable);
 		LiteralAttribute attr = new LiteralAttribute(name, val, parser);
 		addAttribute(attr);
@@ -311,9 +317,8 @@
 	    final String prefix = (String)include.nextElement();
 	    if (!prefix.equals("xml")) {
 		final String uri = lookupNamespace(prefix);
-		if ((uri != null) && (!uri.equals(XSLT_URI))) {
-		    if (!stable.isExcludedNamespace(uri))
-			registerNamespace(prefix,uri,stable,true);
+		if (uri != null && !stable.isExcludedNamespace(uri)) {
+		    registerNamespace(prefix, uri, stable, true);
 		}
 	    }
 	}
@@ -322,7 +327,6 @@
 
 	// Process all attributes and register all namespaces they use
 	for (int i = 0; i < count; i++) {
-
 	    final QName qname = parser.getQName(_attributes.getQName(i));
 	    final String val = _attributes.getValue(i);
 
@@ -344,7 +348,9 @@
     /**
      * Compiles code that emits the literal element to the output handler,
      * first the start tag, then namespace declaration, then attributes,
-     * then the element contents, and then the element end tag.
+     * then the element contents, and then the element end tag. Since the
+     * value of an attribute may depend on a variable, variables must be
+     * compiled first.
      */
     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
 
@@ -354,23 +360,52 @@
 	// Compile code to emit element start tag
 	il.append(methodGen.loadHandler());
 	il.append(new PUSH(cpg, _name));
-	il.append(DUP2); // duplicate these 2 args for endElement
+	il.append(DUP2); 		// duplicate these 2 args for endElement
 	il.append(methodGen.startElement());
 
+	// The value of an attribute may depend on a (sibling) variable
+	for (int i = 0; i < elementCount(); i++) {
+	    final SyntaxTreeNode item = (SyntaxTreeNode) elementAt(i);
+	    if (item instanceof Variable) {
+		item.translate(classGen, methodGen);
+		removeElement(item);	// avoid translating it twice
+	    }
+	}
+
 	// Compile code to emit namespace attributes
 	if (_accessedPrefixes != null) {
+	    boolean declaresDefaultNS = false;
 	    Enumeration e = _accessedPrefixes.keys();
+
 	    while (e.hasMoreElements()) {
 		final String prefix = (String)e.nextElement();
 		final String uri = (String)_accessedPrefixes.get(prefix);
-		if ((uri != Constants.EMPTYSTRING) ||
-		    (prefix != Constants.EMPTYSTRING)) {
+
+		if (uri != Constants.EMPTYSTRING || 
+			prefix != Constants.EMPTYSTRING) 
+		{
+		    if (prefix == Constants.EMPTYSTRING) {
+			declaresDefaultNS = true;
+		    }
 		    il.append(methodGen.loadHandler());
 		    il.append(new PUSH(cpg,prefix));
 		    il.append(new PUSH(cpg,uri));
 		    il.append(methodGen.namespace());
 		}
 	    }
+
+	    /* 
+	     * If our XslElement parent redeclares the default NS, and this
+	     * element doesn't, it must be redeclared one more time.
+	     */
+	    if (!declaresDefaultNS && (_parent instanceof XslElement)
+		    && ((XslElement) _parent).declaresDefaultNS()) 
+	    {
+		il.append(methodGen.loadHandler());
+		il.append(new PUSH(cpg, Constants.EMPTYSTRING));
+		il.append(new PUSH(cpg, Constants.EMPTYSTRING));
+		il.append(methodGen.namespace());
+	    }
 	}
 
 	// Output all attributes
diff --git a/src/org/apache/xalan/xsltc/compiler/LiteralExpr.java b/src/org/apache/xalan/xsltc/compiler/LiteralExpr.java
index 93623a9..b169eff 100644
--- a/src/org/apache/xalan/xsltc/compiler/LiteralExpr.java
+++ b/src/org/apache/xalan/xsltc/compiler/LiteralExpr.java
@@ -88,10 +88,7 @@
      */
     public LiteralExpr(String value, String namespace) {
 	_value = value;
-	if (namespace.equals(Constants.EMPTYSTRING))
-	    _namespace = null;
-	else
-	    _namespace = namespace;
+	_namespace = namespace.equals(Constants.EMPTYSTRING) ? null : namespace;
     }
 
     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
diff --git a/src/org/apache/xalan/xsltc/compiler/LogicalExpr.java b/src/org/apache/xalan/xsltc/compiler/LogicalExpr.java
index ff727d0..a0d86a3 100644
--- a/src/org/apache/xalan/xsltc/compiler/LogicalExpr.java
+++ b/src/org/apache/xalan/xsltc/compiler/LogicalExpr.java
@@ -96,9 +96,31 @@
      * needed for context changes in node steps containing multiple predicates.
      */
     public boolean hasPositionCall() {
-	if (_left.hasPositionCall()) return true;
-	if (_right.hasPositionCall()) return true;
-	return false;
+	return (_left.hasPositionCall() || _right.hasPositionCall());
+    }
+
+    /**
+     * Returns an object representing the compile-time evaluation 
+     * of an expression. We are only using this for function-available
+     * and element-available at this time.
+     */
+    public Object evaluateAtCompileTime() {
+	final Object leftb = _left.evaluateAtCompileTime();
+	final Object rightb = _right.evaluateAtCompileTime();
+
+	// Return null if we can't evaluate at compile time
+	if (leftb == null || rightb == null) {
+	    return null;
+	}
+
+	if (_op == AND) {
+	    return (leftb == Boolean.TRUE && rightb == Boolean.TRUE) ?
+		Boolean.TRUE : Boolean.FALSE;
+	}
+	else {
+	    return (leftb == Boolean.TRUE || rightb == Boolean.TRUE) ?
+		Boolean.TRUE : Boolean.FALSE;
+	}
     }
 
     /**
diff --git a/src/org/apache/xalan/xsltc/compiler/Mode.java b/src/org/apache/xalan/xsltc/compiler/Mode.java
index febab4f..c869a79 100644
--- a/src/org/apache/xalan/xsltc/compiler/Mode.java
+++ b/src/org/apache/xalan/xsltc/compiler/Mode.java
@@ -82,21 +82,54 @@
  */
 final class Mode implements Constants {
 
-    private final QName      _name;       // The QName of this mode
-    private final Stylesheet _stylesheet; // The owning stylesheet
-    private final String     _methodName; // The method name for this mode
-    private Vector           _templates;  // All templates in this mode
+    /**
+     * The name of this mode as defined in the stylesheet.
+     */
+    private final QName _name;
 
-    // Pattern/test sequence for pattern with node()-type kernel
-    private Vector    _nodeGroup = null;
-    private TestSeq   _nodeTestSeq = null;
+    /**
+     * A reference to the stylesheet object that owns this mode.
+     */
+    private final Stylesheet _stylesheet; 
 
-    // Pattern/test sequence for pattern with id() or key()-type kernel
-    private Vector    _idxGroup = null;
-    private TestSeq   _idxTestSeq = null;
+    /**
+     * The name of the method in which this mode is compiled.
+     */
+    private final String _methodName;
 
-    // Pattern/test sequence for patterns with any other kernel type
+    /**
+     * A vector of all the templates in this mode.
+     */
+    private Vector _templates; 
+
+    /**
+     * Group for patterns with node()-type kernel.
+     */
+    private Vector _nodeGroup = null;
+
+    /**
+     * Test sequence for patterns with node()-type kernel.
+     */
+    private TestSeq _nodeTestSeq = null;
+
+    /**
+     * Group for patterns with id() or key()-type kernel.
+     */
+    private Vector _idxGroup = null;
+
+    /**
+     * Test sequence for patterns with id() or key()-type kernel.
+     */
+    private TestSeq  _idxTestSeq = null;
+
+    /**
+     * Group for patterns with any other kernel type.
+     */
     private Vector[]  _patternGroups;
+
+    /**
+     * Test sequence for patterns with any other kernel type.
+     */
     private TestSeq[] _testSeq;
 
     private Hashtable _neededTemplates = new Hashtable();
@@ -114,7 +147,8 @@
 
 
     /**
-     * Creates a new Mode
+     * Creates a new Mode.
+     *
      * @param name A textual representation of the mode's QName
      * @param stylesheet The Stylesheet in which the mode occured
      * @param suffix A suffix to append to the method name for this mode
@@ -161,30 +195,30 @@
 	_templates.addElement(template);
     }
 
-    /*
     private Vector quicksort(Vector templates, int p, int r) {
-	while (p < r) {
+	if (p < r) {
 	    final int q = partition(templates, p, r);
 	    quicksort(templates, p, q);
-	    p = q + 1;
+	    quicksort(templates, q + 1, r);
 	}
 	return templates;
     }
     
     private int partition(Vector templates, int p, int r) {
-	final Template x = (Template)templates.elementAt((p + r) >>> 1);
+	final Template x = (Template)templates.elementAt(p);
 	int i = p - 1;
 	int j = r + 1;
 	while (true) {
-	    while (x.compareTo((Template)templates.elementAt(--j)) < 0);
-	    while (x.compareTo((Template)templates.elementAt(++i)) > 0);
-	    if (i < j)
+	    while (x.compareTo((Template)templates.elementAt(--j)) > 0);
+	    while (x.compareTo((Template)templates.elementAt(++i)) < 0);
+	    if (i < j) {
 		templates.set(j, templates.set(i, templates.elementAt(j)));
-	    else
-		return(j);
+	    }
+	    else {
+		return j;
+	    }
 	}
     }
-    */
 
     /**
      * Process all the test patterns in this mode
@@ -192,7 +226,27 @@
     public void processPatterns(Hashtable keys) {
 	_keys = keys;
 
-	//_templates = quicksort(_templates, 0, _templates.size() - 1);
+/*
+System.out.println("Before Sort " + _name);
+for (int i = 0; i < _templates.size(); i++) {
+    System.out.println("name = " + ((Template)_templates.elementAt(i)).getName());
+    System.out.println("pattern = " + ((Template)_templates.elementAt(i)).getPattern());
+    System.out.println("priority = " + ((Template)_templates.elementAt(i)).getPriority());
+    System.out.println("position = " + ((Template)_templates.elementAt(i)).getPosition());
+}
+*/
+
+	_templates = quicksort(_templates, 0, _templates.size() - 1);
+
+/*
+System.out.println("\n After Sort " + _name);
+for (int i = 0; i < _templates.size(); i++) {
+    System.out.println("name = " + ((Template)_templates.elementAt(i)).getName());
+    System.out.println("pattern = " + ((Template)_templates.elementAt(i)).getPattern());
+    System.out.println("priority = " + ((Template)_templates.elementAt(i)).getPriority());
+    System.out.println("position = " + ((Template)_templates.elementAt(i)).getPosition());
+}
+*/
 
 	// Traverse all templates
 	final Enumeration templates = _templates.elements();
@@ -200,15 +254,20 @@
 	    // Get the next template
 	    final Template template = (Template)templates.nextElement();
 
-	    // Add this template to a table of named templates if it has a name.
-	    // If there are multiple templates with the same name, all but one
-	    // (the one with highest priority) will be disabled.
-	    if (template.isNamed() && !template.disabled())
+	    /* 
+	     * Add this template to a table of named templates if it has a name.
+	     * If there are multiple templates with the same name, all but one
+	     * (the one with highest priority) will be disabled.
+	     */
+	    if (template.isNamed() && !template.disabled()) {
 		_namedTemplates.put(template, this);
+	    }
 
 	    // Add this template to a test sequence if it has a pattern
 	    final Pattern pattern = template.getPattern();
-	    if (pattern != null) flattenAlternative(pattern, template, keys);
+	    if (pattern != null) {
+		flattenAlternative(pattern, template, keys);
+	    }
 	}
 	prepareTestSequences();
     }
@@ -261,10 +320,7 @@
 	Vector patterns;
 
 	// Use the vector for id()/key()/node() patterns if no kernel type
-	if (kernelType == -1)
-	    patterns = _nodeGroup;
-	else
-	    patterns = _patternGroups[kernelType];
+	patterns = (kernelType == -1) ? _nodeGroup : _patternGroups[kernelType];
 
 	// Create a new vector if needed and insert the very first pattern
 	if (patterns == null) {
@@ -389,7 +445,8 @@
 
     private void compileTemplates(ClassGenerator classGen,
 				  MethodGenerator methodGen,
-				  InstructionHandle next) {
+				  InstructionHandle next) 
+    {
         Enumeration templates = _namedTemplates.keys();
         while (templates.hasMoreElements()) {
             final Template template = (Template)templates.nextElement();
@@ -563,22 +620,16 @@
     }
 
     /**
-     * Auxillary method to determine if a qname describes an attribute/element
+     * Auxiliary method to determine if a qname describes an attribute/element
      */
     private static boolean isAttributeName(String qname) {
 	final int col = qname.lastIndexOf(':') + 1;
-	if (qname.charAt(col) == '@')
-	    return(true);
-	else
-	    return(false);
+	return (qname.charAt(col) == '@');
     }
 
     private static boolean isNamespaceName(String qname) {
 	final int col = qname.lastIndexOf(':');
-	if ((col > -1) && (qname.charAt(qname.length()-1) == '*'))
-	    return(true);
-	else
-	    return(false);
+	return (col > -1 && qname.charAt(qname.length()-1) == '*');
     }
 
     /**
@@ -588,9 +639,9 @@
     public void compileApplyTemplates(ClassGenerator classGen) {
 	final XSLTC xsltc = classGen.getParser().getXSLTC();
 	final ConstantPoolGen cpg = classGen.getConstantPool();
-	final Vector names      = xsltc.getNamesIndex();
+	final Vector names = xsltc.getNamesIndex();
 
-	// (*) Create the applyTemplates() method
+	// Create the applyTemplates() method
 	final org.apache.bcel.generic.Type[] argTypes =
 	    new org.apache.bcel.generic.Type[3];
 	argTypes[0] = Util.getJCRefType(DOM_INTF_SIG);
@@ -611,20 +662,20 @@
 				classGen.getConstantPool());
 	methodGen.addException("org.apache.xalan.xsltc.TransletException");
 
-	// (*) Create the local variablea
+	// Create a local variable to hold the current node
 	final LocalVariableGen current;
 	current = methodGen.addLocalVariable2("current",
 					      org.apache.bcel.generic.Type.INT,
 					      mainIL.getEnd());
 	_currentIndex = current.getIndex();
 
-	// (*) Create the "body" instruction list that will eventually hold the
-	//     code for the entire method (other ILs will be appended).
+	// Create the "body" instruction list that will eventually hold the
+	// code for the entire method (other ILs will be appended).
 	final InstructionList body = new InstructionList();
 	body.append(NOP);
 
-	// (*) Create an instruction list that contains the default next-node
-	//     iteration
+	// Create an instruction list that contains the default next-node
+	// iteration
 	final InstructionList ilLoop = new InstructionList();
 	ilLoop.append(methodGen.loadIterator());
 	ilLoop.append(methodGen.nextNode());
@@ -635,41 +686,44 @@
 	// by a single IFNE(body.getStart()) instruction - need workaround:
         final BranchHandle ifeq = ilLoop.append(new IFEQ(null));
 	final BranchHandle loop = ilLoop.append(new GOTO_W(null));
-	ifeq.setTarget(ilLoop.append(RETURN)); // applyTemplates() ends here!
+	ifeq.setTarget(ilLoop.append(RETURN)); 	// applyTemplates() ends here!
 	final InstructionHandle ihLoop = ilLoop.getStart();
 
-	// (*) Compile default handling of elements (traverse children)
+	// Compile default handling of elements (traverse children)
 	InstructionList ilRecurse =
 	    compileDefaultRecursion(classGen, methodGen, ihLoop);
 	InstructionHandle ihRecurse = ilRecurse.getStart();
 
-	// (*) Compile default handling of text/attribute nodes (output text)
+	// Compile default handling of text/attribute nodes (output text)
 	InstructionList ilText =
 	    compileDefaultText(classGen, methodGen, ihLoop);
 	InstructionHandle ihText = ilText.getStart();
 
 	// Distinguish attribute/element/namespace tests for further processing
 	final int[] types = new int[DOM.NTYPES + names.size()];
-	for (int i = 0; i < types.length; i++) types[i] = i;
+	for (int i = 0; i < types.length; i++) {
+	    types[i] = i;
+	}
 
+	// Initialize isAttribute[] and isNamespace[] arrays
 	final boolean[] isAttribute = new boolean[types.length];
 	final boolean[] isNamespace = new boolean[types.length];
 	for (int i = 0; i < names.size(); i++) {
 	    final String name = (String)names.elementAt(i);
-	    isAttribute[i+DOM.NTYPES] = isAttributeName(name);
-	    isNamespace[i+DOM.NTYPES] = isNamespaceName(name);
+	    isAttribute[i + DOM.NTYPES] = isAttributeName(name);
+	    isNamespace[i + DOM.NTYPES] = isNamespaceName(name);
 	}
 
-	// (*) Compile all templates - regardless of pattern type
+	// Compile all templates - regardless of pattern type
 	compileTemplates(classGen, methodGen, ihLoop);
 
-	// (*) Handle template with explicit "*" pattern
+	// Handle template with explicit "*" pattern
 	final TestSeq elemTest = _testSeq[DOM.ELEMENT];
 	InstructionHandle ihElem = ihRecurse;
 	if (elemTest != null)
 	    ihElem = elemTest.compile(classGen, methodGen, ihRecurse);
 
-	// (*) Handle template with explicit "@*" pattern
+	// Handle template with explicit "@*" pattern
 	final TestSeq attrTest = _testSeq[DOM.ATTRIBUTE];
 	InstructionHandle ihAttr = ihText;
 	if (attrTest != null)
@@ -685,39 +739,58 @@
 	    loop.setTarget(body.getStart());
 	}
 
-	// (*) If there is a match on node() we need to replace ihElem
-	//     and ihText (default behaviour for elements & text).
+	// If there is a match on node() we need to replace ihElem
+	// and ihText if the priority of node() is higher
 	if (_nodeTestSeq != null) {
-	    double nodePrio = -0.5; //_nodeTestSeq.getPriority();
+
+	    // Compare priorities of node() and "*"
+	    double nodePrio = _nodeTestSeq.getPriority();
 	    int    nodePos  = _nodeTestSeq.getPosition();
 	    double elemPrio = (0 - Double.MAX_VALUE);
 	    int    elemPos  = Integer.MIN_VALUE;
+
 	    if (elemTest != null) {
 		elemPrio = elemTest.getPriority();
 		elemPos  = elemTest.getPosition();
 	    }
-	    if ((elemPrio == Double.NaN) || (elemPrio < nodePrio) ||
-		((elemPrio == nodePrio) && (elemPos < nodePos))) {
+	    if (elemPrio == Double.NaN || elemPrio < nodePrio || 
+		(elemPrio == nodePrio && elemPos < nodePos)) 
+	    {
 		ihElem = _nodeTestSeq.compile(classGen, methodGen, ihLoop);
-		ihText = ihElem;
+	    }
+
+	    // Compare priorities of node() and text()
+	    final TestSeq textTest = _testSeq[DOM.TEXT];
+	    double textPrio = (0 - Double.MAX_VALUE);
+	    int    textPos  = Integer.MIN_VALUE;
+
+	    if (textTest != null) {
+		textPrio = textTest.getPriority();
+		textPos  = textTest.getPosition();
+	    }
+	    if (textPrio == Double.NaN || textPrio < nodePrio ||
+	        (textPrio == nodePrio && textPos < nodePos)) 
+	    {
+		ihText = _nodeTestSeq.compile(classGen, methodGen, ihLoop);
+		_testSeq[DOM.TEXT] = _nodeTestSeq;
 	    }
 	}
 
-	// (*) Handle templates with "ns:*" pattern
+	// Handle templates with "ns:*" pattern
 	InstructionHandle elemNamespaceHandle = ihElem;
 	InstructionList nsElem = compileNamespaces(classGen, methodGen,
 						   isNamespace, isAttribute,
 						   false, ihElem);
 	if (nsElem != null) elemNamespaceHandle = nsElem.getStart();
 
-	// (*) Handle templates with "ns:@*" pattern
+	// Handle templates with "ns:@*" pattern
 	InstructionHandle attrNamespaceHandle = ihAttr;
 	InstructionList nsAttr = compileNamespaces(classGen, methodGen,
 						   isNamespace, isAttribute,
 						   true, ihAttr);
 	if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart();
 
-	// (*) Handle templates with "ns:elem" or "ns:@attr" pattern
+	// Handle templates with "ns:elem" or "ns:@attr" pattern
 	final InstructionHandle[] targets = new InstructionHandle[types.length];
 	for (int i = DOM.NTYPES; i < targets.length; i++) {
 	    final TestSeq testSeq = _testSeq[i];
@@ -902,7 +975,7 @@
 	// Process all patterns from those templates
 	processPatterns(_keys);
 
-	// (*) Create the applyTemplates() method
+	// Create the applyTemplates() method
 	final org.apache.bcel.generic.Type[] argTypes =
 	    new org.apache.bcel.generic.Type[3];
 	argTypes[0] = Util.getJCRefType(DOM_INTF_SIG);
@@ -936,20 +1009,20 @@
 	    return;
 	}
 
-	// (*) Create the local variablea
+	// Create the local variablea
 	final LocalVariableGen current;
 	current = methodGen.addLocalVariable2("current",
 					      org.apache.bcel.generic.Type.INT,
 					      mainIL.getEnd());
 	_currentIndex = current.getIndex();
 
-	// (*) Create the "body" instruction list that will eventually hold the
-	//     code for the entire method (other ILs will be appended).
+	// Create the "body" instruction list that will eventually hold the
+	// code for the entire method (other ILs will be appended).
 	final InstructionList body = new InstructionList();
 	body.append(NOP);
 
-	// (*) Create an instruction list that contains the default next-node
-	//     iteration
+	// Create an instruction list that contains the default next-node
+	// iteration
 	final InstructionList ilLoop = new InstructionList();
 	ilLoop.append(methodGen.loadIterator());
 	ilLoop.append(methodGen.nextNode());
@@ -965,7 +1038,9 @@
 
 	// Distinguish attribute/element/namespace tests for further processing
 	final int[] types = new int[DOM.NTYPES + names.size()];
-	for (int i = 0; i < types.length; i++) types[i] = i;
+	for (int i = 0; i < types.length; i++) {
+	    types[i] = i;
+	}
 
 	final boolean[] isAttribute = new boolean[types.length];
 	final boolean[] isNamespace = new boolean[types.length];
@@ -975,20 +1050,22 @@
 	    isNamespace[i+DOM.NTYPES] = isNamespaceName(name);
 	}
 
-	// (*) Compile all templates - regardless of pattern type
+	// Compile all templates - regardless of pattern type
 	compileTemplateCalls(classGen, methodGen, ihLoop, min, max);
 
-	// (*) Handle template with explicit "*" pattern
+	// Handle template with explicit "*" pattern
 	final TestSeq elemTest = _testSeq[DOM.ELEMENT];
 	InstructionHandle ihElem = ihLoop;
-	if (elemTest != null)
+	if (elemTest != null) {
 	    ihElem = elemTest.compile(classGen, methodGen, ihLoop);
+	}
 
-	// (*) Handle template with explicit "@*" pattern
+	// Handle template with explicit "@*" pattern
 	final TestSeq attrTest = _testSeq[DOM.ATTRIBUTE];
 	InstructionHandle ihAttr = ihLoop;
-	if (attrTest != null)
+	if (attrTest != null) {
 	    ihAttr = attrTest.compile(classGen, methodGen, ihAttr);
+	}
 
 	// Do tests for id() and key() patterns first
 	InstructionList ilKey = null;
@@ -1000,40 +1077,61 @@
 	    loop.setTarget(body.getStart());
 	}
 
-	// (*) If there is a match on node() we need to replace ihElem
-	//     and ihText (default behaviour for elements & text).
+	// If there is a match on node() we need to replace ihElem
+	// and ihText if the priority of node() is higher
 	InstructionHandle ihText = ihLoop;
 	if (_nodeTestSeq != null) {
-	    double nodePrio = -0.5; //_nodeTestSeq.getPriority();
+
+	    // Compare priorities of node() and "*"
+	    double nodePrio = _nodeTestSeq.getPriority();
 	    int    nodePos  = _nodeTestSeq.getPosition();
 	    double elemPrio = (0 - Double.MAX_VALUE);
 	    int    elemPos  = Integer.MIN_VALUE;
+
 	    if (elemTest != null) {
 		elemPrio = elemTest.getPriority();
 		elemPos  = elemTest.getPosition();
 	    }
-	    if ((elemPrio == Double.NaN) || (elemPrio < nodePrio) ||
-		((elemPrio == nodePrio) && (elemPos < nodePos))) {
+
+	    if (elemPrio == Double.NaN || elemPrio < nodePrio || 
+		(elemPrio == nodePrio && elemPos < nodePos)) 
+	    {
 		ihElem = _nodeTestSeq.compile(classGen, methodGen, ihLoop);
-		ihText = ihElem;
+	    }
+
+	    // Compare priorities of node() and text()
+	    final TestSeq textTest = _testSeq[DOM.TEXT];
+	    double textPrio = (0 - Double.MAX_VALUE);
+	    int    textPos  = Integer.MIN_VALUE;
+
+	    if (textTest != null) {
+		textPrio = textTest.getPriority();
+		textPos  = textTest.getPosition();
+	    }
+
+	    if (textPrio == Double.NaN || textPrio < nodePrio ||
+	        (textPrio == nodePrio && textPos < nodePos)) 
+	    {
+		ihText = _nodeTestSeq.compile(classGen, methodGen, ihLoop);
+		_testSeq[DOM.TEXT] = _nodeTestSeq;
 	    }
 	}
 
-	// (*) Handle templates with "ns:*" pattern
+	// Handle templates with "ns:*" pattern
 	InstructionHandle elemNamespaceHandle = ihElem;
 	InstructionList nsElem = compileNamespaces(classGen, methodGen,
 						   isNamespace, isAttribute,
 						   false, ihElem);
 	if (nsElem != null) elemNamespaceHandle = nsElem.getStart();
 
-	// (*) Handle templates with "ns:@*" pattern
+	// Handle templates with "ns:@*" pattern
 	InstructionList nsAttr = compileNamespaces(classGen, methodGen,
 						   isNamespace, isAttribute,
 						   true, ihAttr);
 	InstructionHandle attrNamespaceHandle = ihAttr;
 	if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart();
 
-	// (*) Handle templates with "ns:elem" or "ns:@attr" pattern
+	// Handle templates with "ns:elem" or "ns:@attr" pattern
 	final InstructionHandle[] targets = new InstructionHandle[types.length];
 	for (int i = DOM.NTYPES; i < targets.length; i++) {
 	    final TestSeq testSeq = _testSeq[i];
@@ -1080,12 +1178,14 @@
 	// Match on processing instruction - default: loop
 	InstructionHandle ihPI = ihLoop;
 	if (_nodeTestSeq != null) ihPI = ihElem;
-	if (_testSeq[DOM.PROCESSING_INSTRUCTION] != null)
+	if (_testSeq[DOM.PROCESSING_INSTRUCTION] != null) {
 	    targets[DOM.PROCESSING_INSTRUCTION] =
 		_testSeq[DOM.PROCESSING_INSTRUCTION].
 		compile(classGen, methodGen, ihPI);
-	else
+	}
+	else {
 	    targets[DOM.PROCESSING_INSTRUCTION] = ihPI;
+	}
 	
 	// Match on comments - default: process next node
 	InstructionHandle ihComment = ihLoop;
diff --git a/src/org/apache/xalan/xsltc/compiler/NameBase.java b/src/org/apache/xalan/xsltc/compiler/NameBase.java
index a15f49f..2b5c4d5 100644
--- a/src/org/apache/xalan/xsltc/compiler/NameBase.java
+++ b/src/org/apache/xalan/xsltc/compiler/NameBase.java
@@ -72,7 +72,7 @@
 class NameBase extends FunctionCall {
 
     private Expression _param = null;
-    private Type       _type = Type.Node;
+    private Type       _paramType = Type.Node;
 
     /**
      * Handles calls with no parameter (current node is implicit parameter).
@@ -99,30 +99,29 @@
 	// Check the argument type (if any)
 	switch(argumentCount()) {
 	case 0:
-	    _type = Type.Node;
+	    _paramType = Type.Node;
 	    break;
 	case 1:
-	    _type = _param.typeCheck(stable);
+	    _paramType = _param.typeCheck(stable);
 	    break;
 	default:
 	    throw new TypeCheckError(this);
 	}
 
 	// The argument has to be a node, a node-set or a node reference
-	if ((_type != Type.NodeSet) &&
-	    (_type != Type.Node) &&
-	    (_type != Type.Reference)) {
+	if ((_paramType != Type.NodeSet) &&
+	    (_paramType != Type.Node) &&
+	    (_paramType != Type.Reference)) {
 	    throw new TypeCheckError(this);
 	}
 
-	return Type.String;
+	return (_type = Type.String);
     }
 
     public Type getType() {
-	return Type.String;
+	return _type;
     }
 
-
     /**
      * Translate the code required for getting the node for which the
      * QName, local-name or namespace URI should be extracted.
@@ -139,10 +138,10 @@
 	    il.append(methodGen.loadContextNode());
 	}
 	// Function was called with node parameter
-	else if (_type == Type.Node) {
+	else if (_paramType == Type.Node) {
 	    _param.translate(classGen, methodGen);
 	}
-	else if (_type == Type.Reference) {
+	else if (_paramType == Type.Reference) {
 	    _param.translate(classGen, methodGen);
 	    il.append(new INVOKESTATIC(cpg.addMethodref
 				       (BASIS_LIBRARY_CLASS,
diff --git a/src/org/apache/xalan/xsltc/compiler/Number.java b/src/org/apache/xalan/xsltc/compiler/Number.java
index af99fe4..5435f27 100644
--- a/src/org/apache/xalan/xsltc/compiler/Number.java
+++ b/src/org/apache/xalan/xsltc/compiler/Number.java
@@ -129,23 +129,23 @@
 		}
 	    }
 	    else if (name.equals("format")) {
-		_format = new AttributeValueTemplate(value, parser);
+		_format = new AttributeValueTemplate(value, parser, this);
 		_formatNeeded = true;
 	    }
 	    else if (name.equals("lang")) {
-		_lang = new AttributeValueTemplate(value, parser);
+		_lang = new AttributeValueTemplate(value, parser, this);
 		_formatNeeded = true;
 	    }
 	    else if (name.equals("letter-value")) {
-		_letterValue = new AttributeValueTemplate(value, parser);
+		_letterValue = new AttributeValueTemplate(value, parser, this);
 		_formatNeeded = true;
 	    }
 	    else if (name.equals("grouping-separator")) {
-		_groupingSeparator = new AttributeValueTemplate(value, parser);
+		_groupingSeparator = new AttributeValueTemplate(value, parser, this);
 		_formatNeeded = true;
 	    }
 	    else if (name.equals("grouping-size")) {
-		_groupingSize = new AttributeValueTemplate(value, parser);
+		_groupingSize = new AttributeValueTemplate(value, parser, this);
 		_formatNeeded = true;
 	    }
 	}
diff --git a/src/org/apache/xalan/xsltc/compiler/Output.java b/src/org/apache/xalan/xsltc/compiler/Output.java
index 907b793..0fa71df 100644
--- a/src/org/apache/xalan/xsltc/compiler/Output.java
+++ b/src/org/apache/xalan/xsltc/compiler/Output.java
@@ -65,15 +65,16 @@
 package org.apache.xalan.xsltc.compiler;
 
 import java.util.Vector;
+import java.util.Properties;
 import java.util.Enumeration;
 import java.util.StringTokenizer;
 import java.io.OutputStreamWriter;
+import javax.xml.transform.OutputKeys;
 
 import org.apache.bcel.generic.*;
 import org.apache.bcel.classfile.JavaClass;
 
 import org.apache.xalan.xsltc.compiler.util.*;
-import org.apache.xalan.xsltc.runtime.TextOutput;
 
 final class Output extends TopLevelElement {
 
@@ -97,7 +98,8 @@
 
     // Some global constants
     private final static String STRING_SIG = "Ljava/lang/String;";
-    private final static String ONE_DOT_ZERO_STRING = "1.0";
+    private final static String XML_VERSION = "1.0";
+    private final static String HTML_VERSION = "4.0";
 
     /**
      * Displays the contents of this element (for debugging)
@@ -124,6 +126,7 @@
      * Scans the attribute list for the xsl:output instruction
      */
     public void parseContents(Parser parser) {
+	final Properties outputProperties = new Properties();
 
 	// Ask the parser if it wants this <xsl:output> element
 	parser.setOutput(this);
@@ -133,25 +136,30 @@
 
 	String attrib = null;
 
-	// Get the output XML version - only version "1.0" should be used
+	// Get the output version
 	_version = getAttribute("version");
-	if ((_version == null) || (_version.equals(Constants.EMPTYSTRING))) {
-	    _version = ONE_DOT_ZERO_STRING;
+	if (_version == null || _version.equals(Constants.EMPTYSTRING)) {
+	    _version = null;
 	}
-	if (!_version.equals(ONE_DOT_ZERO_STRING)) {
-	    ErrorMsg msg = new ErrorMsg(ErrorMsg.OUTPUT_VERSION_ERR, this);
-	    parser.reportError(Constants.WARNING, msg);
+	else {
+	    outputProperties.setProperty(OutputKeys.VERSION, _version);
 	}
 
 	// Get the output method - "xml", "html", "text" or <qname>
 	_method = getAttribute("method");
-	if (_method.equals(Constants.EMPTYSTRING)) _method = null;
-	if (_method != null) _method = _method.toLowerCase();
+	if (_method.equals(Constants.EMPTYSTRING)) {
+	    _method = null;
+	}
+	if (_method != null) {
+	    _method = _method.toLowerCase();
+	    outputProperties.setProperty(OutputKeys.METHOD, _method);
+	}
 
 	// Get the output encoding - any value accepted here
 	_encoding = getAttribute("encoding");
-	if (_encoding.equals(Constants.EMPTYSTRING))
+	if (_encoding.equals(Constants.EMPTYSTRING)) {
 	    _encoding = null;
+	}
 	else {
 	    try {
 		OutputStreamWriter writer =
@@ -162,42 +170,104 @@
 					    _encoding, this);
 		parser.reportError(Constants.WARNING, msg);
 	    }
+	    outputProperties.setProperty(OutputKeys.ENCODING, _encoding);
 	}
 
 	// Should the XML header be omitted - translate to true/false
 	attrib = getAttribute("omit-xml-declaration");
-	if ((attrib != null) && (attrib.equals("yes"))) _omitHeader = true;
+	if (attrib != null && !attrib.equals(Constants.EMPTYSTRING)) {
+	    if (attrib.equals("yes")) {
+		_omitHeader = true;
+	    }
+	    outputProperties.setProperty(OutputKeys.OMIT_XML_DECLARATION, attrib);
+	}
 
 	// Add 'standalone' decaration to output - use text as is
 	_standalone = getAttribute("standalone");
-	if (_standalone.equals(Constants.EMPTYSTRING)) _standalone = null;
+	if (_standalone.equals(Constants.EMPTYSTRING)) {
+	    _standalone = null;
+	}
+	else {
+	    outputProperties.setProperty(OutputKeys.STANDALONE, _standalone);
+	}
 
 	// Get system/public identifiers for output DOCTYPE declaration
 	_doctypeSystem = getAttribute("doctype-system");
-	if (_doctypeSystem.equals(Constants.EMPTYSTRING)) _doctypeSystem = null;
+	if (_doctypeSystem.equals(Constants.EMPTYSTRING)) {
+	    _doctypeSystem = null;
+	}
+	else {
+	    outputProperties.setProperty(OutputKeys.DOCTYPE_SYSTEM, _doctypeSystem);
+	}
+
+
 	_doctypePublic = getAttribute("doctype-public");
-	if (_doctypePublic.equals(Constants.EMPTYSTRING)) _doctypePublic = null;
+	if (_doctypePublic.equals(Constants.EMPTYSTRING)) {
+	    _doctypePublic = null;
+	}
+	else {
+	    outputProperties.setProperty(OutputKeys.DOCTYPE_PUBLIC, _doctypePublic);
+	}
 
 	// Names the elements of whose text contents should be output as CDATA
 	_cdata = getAttribute("cdata-section-elements");
-	if ((_cdata != null) && (_cdata.equals(Constants.EMPTYSTRING)))
+	if (_cdata != null && _cdata.equals(Constants.EMPTYSTRING)) {
 	    _cdata = null;
+	}
+	else {
+	    StringBuffer expandedNames = new StringBuffer();
+	    StringTokenizer tokens = new StringTokenizer(_cdata);
+
+	    // Make sure to store names in expanded form
+	    while (tokens.hasMoreTokens()) {
+		expandedNames.append(parser.getQName(tokens.nextToken()).toString())
+			     .append(' ');
+	    }
+	    _cdata = expandedNames.toString();
+
+	    outputProperties.setProperty(OutputKeys.CDATA_SECTION_ELEMENTS, _cdata);
+	}
 
 	// Get the indent setting - only has effect for xml and html output
 	attrib = getAttribute("indent");
-	if ((attrib != null) && (!attrib.equals(EMPTYSTRING))) {
-	    if (attrib.equals("yes")) _indent = true;
+	if (attrib != null && !attrib.equals(EMPTYSTRING)) {
+	    if (attrib.equals("yes")) {
+		_indent = true;
+	    }
+	    outputProperties.setProperty(OutputKeys.INDENT, attrib);
 	}
-	else if ((_method != null) && (_method.equals("html"))) {
+	else if (_method != null && _method.equals("html")) {
 	    _indent = true;
 	}
 
-	// Get the MIME type for the output file - we don't do anythign with it,
-	// but our client may use it to specify a data transport type, etc.
+	// Get the MIME type for the output file
 	_mediaType = getAttribute("media-type");
-	if (_mediaType.equals(Constants.EMPTYSTRING)) _mediaType = null;
+	if (_mediaType.equals(Constants.EMPTYSTRING)) {
+	    _mediaType = null;
+	}
+	else {
+	    outputProperties.setProperty(OutputKeys.MEDIA_TYPE, _mediaType);
+	}
 
-	// parseChildren(parser); - the element is always empty
+	// Implied properties
+	if (_method != null) {
+	    if (_method.equals("html")) {
+		if (_version == null) {
+		    _version = HTML_VERSION;
+		}
+		if (_mediaType == null) {
+		    _mediaType = "text/html";
+		}
+	    }
+	    else if (_method.equals("text")) {
+		if (_mediaType == null) {
+		    _mediaType = "text/plain";
+		}
+	    }
+	}
+
+	// Set output properties in current stylesheet
+	parser.getCurrentStylesheet().setOutputProperties(outputProperties);
     }
 
     /**
@@ -216,7 +286,7 @@
         il.append(classGen.loadTranslet());
 
 	// Only update _version field if set and different from default
-	if ((_version != null) && (!_version.equals(ONE_DOT_ZERO_STRING))) {
+	if ((_version != null) && (!_version.equals(XML_VERSION))) {
 	    field = cpg.addFieldref(TRANSLET_CLASS, "_version", STRING_SIG);
 	    il.append(DUP);
 	    il.append(new PUSH(cpg, _version));
@@ -274,7 +344,7 @@
 	}
 
 	// Compile code to set output indentation on/off
-	if (_indent ) {
+	if (_indent) {
 	    field = cpg.addFieldref(TRANSLET_CLASS, "_indent", "Z");
 	    il.append(DUP);
 	    il.append(new PUSH(cpg, _indent));
@@ -286,6 +356,7 @@
 	    int index = cpg.addMethodref(TRANSLET_CLASS,
 					 "addCdataElement",
 					 "(Ljava/lang/String;)V");
+
 	    StringTokenizer tokens = new StringTokenizer(_cdata);
 	    while (tokens.hasMoreTokens()) {
 		il.append(DUP);
diff --git a/src/org/apache/xalan/xsltc/compiler/ParentLocationPath.java b/src/org/apache/xalan/xsltc/compiler/ParentLocationPath.java
index adca196..cb52df0 100644
--- a/src/org/apache/xalan/xsltc/compiler/ParentLocationPath.java
+++ b/src/org/apache/xalan/xsltc/compiler/ParentLocationPath.java
@@ -216,14 +216,15 @@
 	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.PRECEDING        && step == Axis.PARENT)) {
-		final int incl = cpg.addMethodref(STEP_ITERATOR_CLASS,
+		final int incl = cpg.addMethodref(NODE_ITERATOR_BASE,
 						  "includeSelf",
-						  "()"+NODE_ITERATOR_SIG);
+						  "()" + NODE_ITERATOR_SIG);
 		il.append(new INVOKEVIRTUAL(incl));
 	    }
 	}
diff --git a/src/org/apache/xalan/xsltc/compiler/ParentPattern.java b/src/org/apache/xalan/xsltc/compiler/ParentPattern.java
index 78f2053..4d92fbc 100644
--- a/src/org/apache/xalan/xsltc/compiler/ParentPattern.java
+++ b/src/org/apache/xalan/xsltc/compiler/ParentPattern.java
@@ -117,8 +117,6 @@
 	    il.append(SWAP);
 	}
 	else if (_right instanceof StepPattern) {
-	    //!!! check this
-
 	    il.append(DUP);
 	    il.append(storeLocal);
 	    
@@ -129,6 +127,11 @@
 	}
 	else {
 	    _right.translate(classGen, methodGen);
+
+	    if (_right instanceof AncestorPattern) {
+		il.append(methodGen.loadDOM());
+		il.append(SWAP);
+	    }
 	}
 
 	final int getParent = cpg.addInterfaceMethodref(DOM_INTF,
@@ -137,9 +140,9 @@
 	il.append(new INVOKEINTERFACE(getParent, 2));
 
 	final SyntaxTreeNode p = getParent();
-	if ((p == null) ||
-	    (p instanceof Instruction) ||
-	    (p instanceof TopLevelElement)) {
+	if (p == null || p instanceof Instruction || 
+	    p instanceof TopLevelElement) 
+	{
 	    _left.translate(classGen, methodGen);
 	}
 	else {
@@ -154,6 +157,15 @@
 
 	methodGen.removeLocalVariable(local);
 	
+	/*
+	 * If _right is an ancestor pattern, backpatch _left false
+	 * list to the loop that searches for more ancestors.
+	 */
+	if (_right instanceof AncestorPattern) {
+	    final AncestorPattern ancestor = (AncestorPattern) _right;
+	    _left.backPatchFalseList(ancestor.getLoopHandle());    // clears list
+	}
+
 	_trueList.append(_right._trueList.append(_left._trueList));
 	_falseList.append(_right._falseList.append(_left._falseList));
     }
diff --git a/src/org/apache/xalan/xsltc/compiler/Parser.java b/src/org/apache/xalan/xsltc/compiler/Parser.java
index c4b2fd6..e6412d9 100644
--- a/src/org/apache/xalan/xsltc/compiler/Parser.java
+++ b/src/org/apache/xalan/xsltc/compiler/Parser.java
@@ -70,6 +70,7 @@
 import java.net.URL;
 import java.util.Vector;
 import java.util.Hashtable;
+import java.util.Properties;
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.StringTokenizer;
@@ -99,6 +100,7 @@
     private Vector _warnings;         // Contains all compilation errors
 
     private Hashtable   _instructionClasses; // Maps instructions to classes
+    private Hashtable   _instructionAttrs;;  // reqd and opt attrs 
     private Hashtable   _qNames;
     private Hashtable   _namespaces;
     private QName       _useAttributeSets;
@@ -126,6 +128,7 @@
 	_qNames              = new Hashtable(512);
 	_namespaces          = new Hashtable();
 	_instructionClasses  = new Hashtable();
+	_instructionAttrs    = new Hashtable();
 	_variableScope       = new Hashtable();
 	_template            = null;
 	_errors              = new Vector();
@@ -136,6 +139,7 @@
 	_currentImportPrecedence = 1;
 	
 	initStdClasses();
+	initInstructionAttrs();
 	initExtClasses();
 	initSymbolTable();
 	
@@ -166,6 +170,10 @@
 	return _output;
     }
 
+    public Properties getOutputProperties() {
+	return getTopLevelStylesheet().getOutputProperties();
+    }
+
     public void addVariable(Variable var) {
 	addVariableOrParam(var);
     }
@@ -252,19 +260,34 @@
 	    String namespace = null;
 	    
 	    // Get the namespace uri from the symbol table
-	    if (prefix.equals("xmlns") == false) {
+	    if (prefix.equals(XMLNS_PREFIX) == false) {
 		namespace = _symbolTable.lookupNamespace(prefix);
 		if (namespace == null) namespace = EMPTYSTRING;
 	    }
 	    return getQName(namespace, prefix, localname);
 	}
 	else {
-	    final String uri = _symbolTable.lookupNamespace(EMPTYSTRING);
+	    final String uri = stringRep.equals(XMLNS_PREFIX) ? null
+		: _symbolTable.lookupNamespace(EMPTYSTRING);
 	    return getQName(uri, null, stringRep);
 	}
     }
     
     public QName getQName(final String stringRep) {
+	return getQName(stringRep, true, false);    
+    }
+
+    public QName getQNameIgnoreDefaultNs(final String stringRep) {
+	return getQName(stringRep, true, true);
+    }
+
+    public QName getQName(final String stringRep, boolean reportError) {
+	return getQName(stringRep, reportError, false);
+    }
+
+    private QName getQName(final String stringRep, boolean reportError,
+	boolean ignoreDefaultNs) 
+    {
 	// parse and retrieve namespace
 	final int colon = stringRep.lastIndexOf(':');
 	if (colon != -1) {
@@ -273,9 +296,9 @@
 	    String namespace = null;
 	    
 	    // Get the namespace uri from the symbol table
-	    if (prefix.equals("xmlns") == false) {
+	    if (prefix.equals(XMLNS_PREFIX) == 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);
@@ -285,13 +308,17 @@
 	    return getQName(namespace, prefix, localname);
 	}
 	else {
-	    final String defURI = _symbolTable.lookupNamespace(EMPTYSTRING);
+	    if (stringRep.equals(XMLNS_PREFIX)) {
+		ignoreDefaultNs = true;
+	    }
+	    final String defURI = ignoreDefaultNs ? null 
+				  : _symbolTable.lookupNamespace(EMPTYSTRING);
 	    return getQName(defURI, null, stringRep);
 	}
     }
 
     public QName getQName(String namespace, String prefix, String localname) {
-	if (namespace == null) {
+	if (namespace == null || namespace.equals(EMPTYSTRING)) {
 	    QName name = (QName)_qNames.get(localname);
 	    if (name == null) {
 		name = new QName(null, prefix, localname);
@@ -356,7 +383,11 @@
 		stylesheet.setSimplified();
 		stylesheet.addElement(element);
 		stylesheet.setAttributes(element.getAttributes());
-		element.addPrefixMapping(EMPTYSTRING, EMPTYSTRING);
+
+		// Map the default NS if not already defined
+		if (element.lookupNamespace(EMPTYSTRING) == null) {
+		    element.addPrefixMapping(EMPTYSTRING, EMPTYSTRING);
+		}
 	    }
 	    stylesheet.setParser(this);
 	    return stylesheet;
@@ -567,6 +598,70 @@
 	return(external);
     }
 
+    private void initAttrTable(String elementName, String[] attrs) {
+	_instructionAttrs.put(getQName(XSLT_URI, XSL, elementName),
+				attrs);
+    }
+
+    private void initInstructionAttrs() {
+	initAttrTable("template", 
+	    new String[] {"match", "name", "priority", "mode"});
+	initAttrTable("stylesheet", 
+	    new String[] {"id", "version", "extension-element-prefixes",
+		"exclude-result-prefixes"});
+	initAttrTable("transform",
+	    new String[] {"id", "version", "extension-element-prefixes",
+		"exclude-result-prefixes"});
+	initAttrTable("text", new String[] {"disable-output-escaping"}); 
+	initAttrTable("if", new String[] {"test"}); 
+	initAttrTable("choose", new String[] {}); 
+	initAttrTable("when", new String[] {"test"}); 
+	initAttrTable("otherwise", new String[] {}); 
+	initAttrTable("for-each", new String[] {"select"}); 
+	initAttrTable("message", new String[] {"terminate"}); 
+	initAttrTable("number", 
+	    new String[] {"level", "count", "from", "value", "format", "lang",
+		"letter-value", "grouping-separator", "grouping-size"});
+		initAttrTable("comment", new String[] {}); 
+	initAttrTable("copy", new String[] {"use-attribute-sets"}); 
+	initAttrTable("copy-of", new String[] {"select"}); 
+	initAttrTable("param", new String[] {"name", "select"}); 
+	initAttrTable("with-param", new String[] {"name", "select"}); 
+	initAttrTable("variable", new String[] {"name", "select"}); 
+	initAttrTable("output", 
+	    new String[] {"method", "version", "encoding", 
+		"omit-xml-declaration", "standalone", "doctype-public",
+		"doctype-system", "cdata-section-elements", "indent",
+		"media-type"}); 
+	initAttrTable("sort", 
+	   new String[] {"select", "order", "case-order", "lang", "data-type"});
+	initAttrTable("key", new String[] {"name", "match", "use"}); 
+	initAttrTable("fallback", new String[] {}); 
+	initAttrTable("attribute", new String[] {"name", "namespace"}); 
+	initAttrTable("attribute-set", 
+	    new String[] {"name", "use-attribute-sets"}); 
+	initAttrTable("value-of", 
+	    new String[] {"select", "disable-output-escaping"}); 
+	initAttrTable("element", 
+	    new String[] {"name", "namespace", "use-attribute-sets"}); 
+	initAttrTable("call-template", new String[] {"name"}); 
+	initAttrTable("apply-templates", new String[] {"select", "mode"}); 
+	initAttrTable("apply-imports", new String[] {}); 
+	initAttrTable("decimal-format", 
+	    new String[] {"name", "decimal-separator", "grouping-separator",
+		"infinity", "minus-sign", "NaN", "percent", "per-mille",
+		"zero-digit", "digit", "pattern-separator"}); 
+	initAttrTable("import", new String[] {"href"}); 
+	initAttrTable("include", new String[] {"href"}); 
+	initAttrTable("strip-space", new String[] {"elements"}); 
+	initAttrTable("preserve-space", new String[] {"elements"}); 
+	initAttrTable("processing-instruction", new String[] {"name"}); 
+	initAttrTable("namespace-alias", 
+	   new String[] {"stylesheet-prefix", "result-prefix"}); 
+    }
+
+
+
     /**
      * Initialize the _instructionClasses Hashtable, which maps XSL element
      * names to Java classes in this package.
@@ -614,8 +709,8 @@
 				COMPILER_PACKAGE + '.' + className);
     }
 
-    public boolean elementSupported(QName qname) {
-	return(_instructionClasses.get(qname) != null);
+    public boolean elementSupported(String namespace, String localName) {
+	return(_instructionClasses.get(getQName(namespace, XSL, localName)) != null);
     }
 
     public boolean functionSupported(String fname) {
@@ -645,7 +740,6 @@
 	MethodType R_D  = new MethodType(Type.Real, Type.NodeSet);
 	MethodType R_O  = new MethodType(Type.Real, Type.Reference);
 	MethodType I_I  = new MethodType(Type.Int, Type.Int);
-	MethodType J_J  = new MethodType(Type.Lng, Type.Lng);  //GTM,bug 3592
  	MethodType D_O  = new MethodType(Type.NodeSet, Type.Reference);
 	MethodType D_V  = new MethodType(Type.NodeSet, Type.Void);
 	MethodType D_S  = new MethodType(Type.NodeSet, Type.String);
@@ -660,6 +754,7 @@
 	MethodType B_V  = new MethodType(Type.Boolean, Type.Void);
 	MethodType B_B  = new MethodType(Type.Boolean, Type.Boolean);
 	MethodType B_S  = new MethodType(Type.Boolean, Type.String);
+	MethodType D_T  = new MethodType(Type.NodeSet, Type.ResultTree);
 	MethodType R_RR = new MethodType(Type.Real, Type.Real, Type.Real);
 	MethodType I_II = new MethodType(Type.Int, Type.Int, Type.Int);
 	MethodType B_RR = new MethodType(Type.Boolean, Type.Real, Type.Real);
@@ -744,6 +839,9 @@
 	_symbolTable.addPrimop("normalize-space", S_S);
 	_symbolTable.addPrimop("system-property", S_S);
 
+	// Extensions
+	_symbolTable.addPrimop("nodeset", D_T);
+
 	// Operators +, -, *, /, % defined on real types.
 	_symbolTable.addPrimop("+", R_RR);	
 	_symbolTable.addPrimop("-", R_RR);	
@@ -782,7 +880,6 @@
 	// Unary minus.
 	_symbolTable.addPrimop("u-", R_R);	
 	_symbolTable.addPrimop("u-", I_I);	
-	_symbolTable.addPrimop("u-", J_J);  // GTM,bug 3592	
     }
 
     public SymbolTable getSymbolTable() {
@@ -814,10 +911,15 @@
      * until we have received all child elements of an unsupported element to
      * see if any <xsl:fallback> elements exist.
      */
-    public SyntaxTreeNode makeInstance(String uri, String prefix, String local){
+
+    private boolean versionIsOne = true;
+
+    public SyntaxTreeNode makeInstance(String uri, String prefix, 
+	String local, Attributes attributes)
+    {
+	SyntaxTreeNode node = null;
 	QName  qname = getQName(uri, prefix, local);
 	String className = (String)_instructionClasses.get(qname);
-	SyntaxTreeNode node = null;
 
 	if (className != null) {
 	    try {
@@ -825,11 +927,13 @@
 		node = (SyntaxTreeNode)clazz.newInstance();
 		node.setQName(qname);
 		node.setParser(this);
-		if (_locator != null)
+		if (_locator != null) {
 		    node.setLineNumber(_locator.getLineNumber());
+		}
 		if (node instanceof Stylesheet) {
 		    _xsltc.setStylesheet((Stylesheet)node);
 		}
+		checkForSuperfluousAttributes(node, attributes);
 	    }
 	    catch (ClassNotFoundException e) {
 		ErrorMsg err = new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR, node);
@@ -884,6 +988,46 @@
     }
 
     /**
+     * checks the list of attributes against a list of allowed attributes
+     * for a particular element node.
+     */
+    private void checkForSuperfluousAttributes(SyntaxTreeNode node, 
+	Attributes attrs)
+    {
+	QName qname = node.getQName();
+	boolean isStylesheet = (node instanceof Stylesheet); 
+        String[] legal = (String[]) _instructionAttrs.get(qname);
+	if (versionIsOne && legal != null) {
+	    int j;
+	    final int n = attrs.getLength();
+
+	    for (int i = 0; i < n; i++) {
+	        final String attrQName = attrs.getQName(i);
+
+	        if (isStylesheet && attrQName.equals("version")) {
+	            versionIsOne = attrs.getValue(i).equals("1.0");
+	        }
+
+	        if (attrQName.startsWith("xml") || 
+		    attrQName.indexOf(':') > 0) continue;
+
+	        for (j = 0; j < legal.length; j++) {
+	            if (attrQName.equalsIgnoreCase(legal[j])) {
+		        break;
+		    }	
+	        }
+	        if (j == legal.length) {
+	            final ErrorMsg err = 
+		        new ErrorMsg(ErrorMsg.ILLEGAL_ATTRIBUTE_ERR, 
+				attrQName, node);
+		    reportError(WARNING, err);
+	        }
+	    }
+        }	
+    }
+
+
+    /**
      * Parse an XPath expression:
      *  @parent - XSL element where the expression occured
      *  @exp    - textual representation of the expression
@@ -944,7 +1088,7 @@
 
 	try {
 	    _xpathParser.setScanner(new XPathLexer(new StringReader(text)));
-	    Symbol result = _xpathParser.parse(line);
+	    Symbol result = _xpathParser.parse(expression, line);
 	    if (result != null) {
 		final SyntaxTreeNode node = (SyntaxTreeNode)result.value;
 		if (node != null) {
@@ -957,14 +1101,12 @@
 	    reportError(ERROR, new ErrorMsg(ErrorMsg.XPATH_PARSER_ERR,
 					    expression, parent));
 	}
-	catch (ClassCastException e) {
+	catch (Exception e) {
+	    if (_xsltc.debug()) e.printStackTrace();
 	    reportError(ERROR, new ErrorMsg(ErrorMsg.XPATH_PARSER_ERR,
 					    expression, parent));
 	}
-	catch (Exception e) {
-	    if (_xsltc.debug()) e.printStackTrace();
-	    // Intentional fall through
-	}
+
 	// Return a dummy pattern (which is an expression)
 	SyntaxTreeNode.Dummy.setParser(this);
         return SyntaxTreeNode.Dummy; 
@@ -1072,7 +1214,9 @@
      *       This has to be passed on to the symbol table!
      */
     public void startPrefixMapping(String prefix, String uri) {
-	if (_prefixMapping == null) _prefixMapping = new Hashtable();
+	if (_prefixMapping == null) {
+	    _prefixMapping = new Hashtable();
+	}
 	_prefixMapping.put(prefix, uri);
     }
 
@@ -1091,13 +1235,10 @@
 			     String qname, Attributes attributes) 
 	throws SAXException {
 	final int col = qname.lastIndexOf(':');
-	final String prefix;
-	if (col == -1)
-	    prefix = null;
-	else
-	    prefix = qname.substring(0, col);
+	final String prefix = (col == -1) ? null : qname.substring(0, col);
 
-	SyntaxTreeNode element = makeInstance(uri, prefix, localname);
+	SyntaxTreeNode element = makeInstance(uri, prefix, 
+					localname, attributes);
 	if (element == null) {
 	    ErrorMsg err = new ErrorMsg(ErrorMsg.ELEMENT_PARSE_ERR,
 					prefix+':'+localname);
diff --git a/src/org/apache/xalan/xsltc/compiler/Predicate.java b/src/org/apache/xalan/xsltc/compiler/Predicate.java
index 0d6c217..f57b23c 100644
--- a/src/org/apache/xalan/xsltc/compiler/Predicate.java
+++ b/src/org/apache/xalan/xsltc/compiler/Predicate.java
@@ -208,8 +208,8 @@
 
 		    if (fexp instanceof KeyCall)
 			_canOptimize = false;
-		    //else if (fexp instanceof VariableRefBase)
-		    //    _canOptimize = false;
+		    else if (fexp instanceof VariableRefBase)
+		        _canOptimize = false;
 		    else if (fexp instanceof ParentLocationPath)
 			_canOptimize = false;
 		    else if (fexp instanceof UnionPathExpr)
diff --git a/src/org/apache/xalan/xsltc/compiler/ProcessingInstruction.java b/src/org/apache/xalan/xsltc/compiler/ProcessingInstruction.java
index 91e40a4..fa2a188 100644
--- a/src/org/apache/xalan/xsltc/compiler/ProcessingInstruction.java
+++ b/src/org/apache/xalan/xsltc/compiler/ProcessingInstruction.java
@@ -109,13 +109,13 @@
 
 	// get String out of the handler
 	il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_VALUE_HANDLER,
-						     "getValue",
-						     "()"+STRING_SIG)));
+						     "getValueOfPI",
+						     "()" + STRING_SIG)));
 	// call "processingInstruction"
 	final int processingInstruction =
 	    cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
 				      "processingInstruction", 
-				      "("+STRING_SIG+STRING_SIG+")V");
+				      "(" + STRING_SIG + STRING_SIG + ")V");
 	il.append(new INVOKEINTERFACE(processingInstruction, 3));
 	// Restore old handler base from stack
 	il.append(methodGen.storeHandler());
diff --git a/src/org/apache/xalan/xsltc/compiler/QName.java b/src/org/apache/xalan/xsltc/compiler/QName.java
index 6eace10..1c1b1b0 100644
--- a/src/org/apache/xalan/xsltc/compiler/QName.java
+++ b/src/org/apache/xalan/xsltc/compiler/QName.java
@@ -75,24 +75,14 @@
 	_namespace = namespace;
 	_prefix    = prefix;
 	_localname = localname;
-	if ((namespace != null) && (!namespace.equals(Constants.EMPTYSTRING))) {
-	    _stringRep = namespace+':'+localname;
-	}
-	else {
-	    _stringRep = localname;
-	}
+
+	_stringRep = 
+	    (namespace != null && !namespace.equals(Constants.EMPTYSTRING)) ?
+	    (namespace + ':' + localname) : localname;
 
 	_hashCode  = _stringRep.hashCode() + 19; // cached for speed
     }
 
-    public void clearDefaultNamespace() {
-	if ((_prefix == null) || (_prefix.equals(Constants.EMPTYSTRING))) {
-	    _namespace = null;
-	    _stringRep = _localname;
-	    _hashCode  = _stringRep.hashCode() + 19; // cached for speed
-	}
-    }
-
     public void clearNamespace() {
 	_namespace = Constants.EMPTYSTRING;
     }
@@ -106,7 +96,7 @@
     }
 
     public boolean equals(Object other) {
-	return this == other;
+	return (this == other);
     }
 
     public String getLocalPart() {
@@ -126,6 +116,7 @@
     }
 
     public String dump() {
-	return(new String("QName: "+_namespace+"("+_prefix+"):"+_localname));
+	return new String("QName: " + _namespace + "(" + _prefix + "):" 
+	    + _localname);
     }
 }
diff --git a/src/org/apache/xalan/xsltc/compiler/Sort.java b/src/org/apache/xalan/xsltc/compiler/Sort.java
index 383b1df..4269f8a 100644
--- a/src/org/apache/xalan/xsltc/compiler/Sort.java
+++ b/src/org/apache/xalan/xsltc/compiler/Sort.java
@@ -349,7 +349,7 @@
 	// Class initializer - void NodeSortRecord.<clinit>();
 	final InstructionList il = new InstructionList();
 	final CompareGenerator classInit =
-	    new CompareGenerator(ACC_PUBLIC | ACC_FINAL,
+	    new CompareGenerator(ACC_PUBLIC | ACC_STATIC,
 				 org.apache.bcel.generic.Type.VOID, 
 				 new org.apache.bcel.generic.Type[] { },
 				 new String[] { },
diff --git a/src/org/apache/xalan/xsltc/compiler/Step.java b/src/org/apache/xalan/xsltc/compiler/Step.java
index 4d54224..265fe42 100644
--- a/src/org/apache/xalan/xsltc/compiler/Step.java
+++ b/src/org/apache/xalan/xsltc/compiler/Step.java
@@ -74,23 +74,28 @@
 
 final class Step extends RelativeLocationPath {
 
-    // This step's axis as defined in class Axis.
+    /**
+     * This step's axis as defined in class Axis.
+     */
     private int _axis;
 
-    // A vector of predicates (filters) defined on this step - may be null
+    /**
+     * A vector of predicates (filters) defined on this step - may be null
+     */
     private Vector _predicates;
 
-    // Some simple predicates can be handled by this class (and not by the
-    // Predicate class) and will be removed from the above vector as they are
-    // handled. We use this boolean to remember if we did have any predicates.
+    /**
+     * Some simple predicates can be handled by this class (and not by the
+     * Predicate class) and will be removed from the above vector as they are
+     * handled. We use this boolean to remember if we did have any predicates.
+     */
     private boolean _hadPredicates = false;
 
-    // Type of the node test.
+    /**
+     * Type of the node test.
+     */
     private int _nodeType;
 
-    /**
-     * Constructor
-     */
     public Step(int axis, int nodeType, Vector predicates) {
 	_axis = axis;
 	_nodeType = nodeType;
@@ -156,16 +161,12 @@
      * an element like <xsl:for-each> or <xsl:apply-templates>.
      */
     private boolean hasParentPattern() {
-	SyntaxTreeNode parent = getParent();
-	if ((parent instanceof ParentPattern) ||
-	    (parent instanceof ParentLocationPath) ||
-	    (parent instanceof UnionPathExpr) ||
-	    (parent instanceof FilterParentPath))
-	    return(true);
-	else
-	    return(false);
+	final SyntaxTreeNode parent = getParent();
+	return (parent instanceof ParentPattern ||
+		parent instanceof ParentLocationPath ||
+		parent instanceof UnionPathExpr ||
+		parent instanceof FilterParentPath);
     }
-
     
     /**
      * Returns 'true' if this step has any predicates
@@ -214,24 +215,10 @@
 
 	// Special case for '.' 
 	if (isAbbreviatedDot()) {
-	    if (hasParentPattern())
-		_type = Type.NodeSet;
-	    else
-		_type = Type.Node;
-	}
-	// Special case for '..'
-	else if (isAbbreviatedDDot()) {
-	    _type = Type.NodeSet;
+	    _type =  (hasParentPattern()) ? Type.NodeSet : Type.Node;
 	}
 	else {
-	    // Special case for '@attr' with no parent or predicates
-	    if ((_axis == Axis.ATTRIBUTE) && (_nodeType!=NodeTest.ATTRIBUTE) &&
-		(!hasParentPattern()) && (!_hadPredicates) && (!isPredicate())) {
-		_type = Type.Node;
-	    }
-	    else {
-		_type = Type.NodeSet;
-	    }
+	    _type = Type.NodeSet;
 	}
 
 	// Type check all predicates (expressions applied to the step)
@@ -259,11 +246,8 @@
 	if ((_axis == Axis.ANCESTOR)  || (_axis == Axis.ANCESTORORSELF) ||
 	    (_axis == Axis.PRECEDING) || (_axis == Axis.PRECEDINGSIBLING)) {
 
-	    // Do not reverse nodes if we have a parent step that will reverse
-	    // the nodes for us.
-	    if (hasParentPattern()) return false;
-	    if (hasPredicates()) return false;
-	    if (_hadPredicates) return false;
+	    // Do not reverse nodes if we had predicates
+	    // if (_hadPredicates) return false;
 	    
 	    // Check if this step occured under an <xsl:apply-templates> element
 	    SyntaxTreeNode parent = this;
@@ -276,11 +260,11 @@
 		if (parent instanceof ApplyTemplates) return true;
 		if (parent instanceof ForEach) return true;
 		if (parent instanceof FilterParentPath) return true;
+		if (parent instanceof FilterExpr) return true;
+		if (parent instanceof WithParam) return true;
+		if (parent instanceof ValueOf) return true;
 
-		// No not order node set if descendant of these elements:
-		if (parent instanceof ValueOf) return false;
-
-	    } while (parent != null);
+	    } while (parent != null && parent instanceof Instruction == false);
 	}
 	return false;
     }
@@ -298,30 +282,23 @@
 
 	if (hasPredicates()) {
 	    translatePredicates(classGen, methodGen);
+
+	    // If needed, create a reverse iterator after compiling preds
+	    if (_predicates.size() == 0) {
+		orderIterator(classGen, methodGen);
+	    }
 	}
 	else {
 	    // If it is an attribute but not '@*' or '@attr' with a parent
 	    if ((_axis == Axis.ATTRIBUTE) &&
 		(_nodeType != NodeTest.ATTRIBUTE) && (!hasParentPattern())) {
-		int node = cpg.addInterfaceMethodref(DOM_INTF,
-						     "getAttributeNode",
-						     "(II)I");
 		int iter = cpg.addInterfaceMethodref(DOM_INTF,
 						     "getTypedAxisIterator",
 						     "(II)"+NODE_ITERATOR_SIG);
-		if (_type instanceof NodeType) {
-		    il.append(methodGen.loadDOM());
-		    il.append(new PUSH(cpg, _nodeType));
-		    il.append(methodGen.loadContextNode());
-		    il.append(new INVOKEINTERFACE(node, 3));
-		}
-		// If it is the case '@attr[P_1]...[P_k]'
-		else if (_type instanceof NodeSetType) {
-		    il.append(methodGen.loadDOM());
-		    il.append(new PUSH(cpg, Axis.ATTRIBUTE));
-		    il.append(new PUSH(cpg, _nodeType));
-		    il.append(new INVOKEINTERFACE(iter, 3));
-		}
+		il.append(methodGen.loadDOM());
+		il.append(new PUSH(cpg, Axis.ATTRIBUTE));
+		il.append(new PUSH(cpg, _nodeType));
+		il.append(new INVOKEINTERFACE(iter, 3));
 		return;
 	    }
 
@@ -403,9 +380,14 @@
 		il.append(new PUSH(cpg, _axis));
 		il.append(new PUSH(cpg, _nodeType));
 		il.append(new INVOKEINTERFACE(ty, 3));
-		orderIterator(classGen, methodGen);
+
 		break;
 	    }
+
+	    // If needed, create a reverse iterator
+	    if (!_hadPredicates) {
+		orderIterator(classGen, methodGen);
+	    }
 	}
     }
 
@@ -508,22 +490,6 @@
 		    il.append(new CHECKCAST(cpg.addClass(className)));
 		}
 		il.append(new INVOKESPECIAL(idx));
-
-		// Determine if the node set should be generated using the
-		// natural order of the node set or document order.
-		// See CurrentNodeListIterator's constructor(s) for details.
-		SyntaxTreeNode parent = getParent();
-		while (!(parent instanceof Template)) {
-		    if (parent == null) break;
-		    if (parent instanceof ApplyTemplates) {
-			idx = cpg.addMethodref(CURRENT_NODE_LIST_ITERATOR,
-					       "forceNaturalOrder",
-					       "()"+NODE_ITERATOR_SIG);
-			il.append(new INVOKEVIRTUAL(idx));
-			break;
-		    }
-		    parent = parent.getParent();
-		}
 	    }
 	}
     }
diff --git a/src/org/apache/xalan/xsltc/compiler/StepPattern.java b/src/org/apache/xalan/xsltc/compiler/StepPattern.java
index 78243a3..5078287 100644
--- a/src/org/apache/xalan/xsltc/compiler/StepPattern.java
+++ b/src/org/apache/xalan/xsltc/compiler/StepPattern.java
@@ -133,14 +133,11 @@
 	else {
 	    switch(_nodeType) {
 	    case -1:
-		return(-0.25);
+		return -0.5;	// node()
 	    case 0:
-		return(0.0);
+		return 0.0;
 	    default:
-		if (_nodeType >= NodeTest.GTYPE)
-		    return(0.0);
-		else
-		    return(-0.5);
+		return (_nodeType >= NodeTest.GTYPE) ? 0.0 : -0.5;
 	    }
 	}
     }
@@ -162,10 +159,12 @@
     private int analyzeCases() {
 	boolean noContext = true;
 	final int n = _predicates.size();
+
 	for (int i = 0; i < n && noContext; i++) {
 	    final Predicate pred = (Predicate)_predicates.elementAt(i);
-	    final Expression exp = pred.getExpr();
-	    if (exp.hasPositionCall()) noContext = false;
+	    if (pred.getExpr().hasPositionCall()) {
+		noContext = false;
+	    }
 	}
 
 	if (noContext) {
diff --git a/src/org/apache/xalan/xsltc/compiler/Stylesheet.java b/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
index 15b0522..4d79fe4 100644
--- a/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
+++ b/src/org/apache/xalan/xsltc/compiler/Stylesheet.java
@@ -66,6 +66,7 @@
 
 import java.util.Vector;
 import java.util.Hashtable;
+import java.util.Properties;
 import java.util.Enumeration;
 import java.util.StringTokenizer;
 import java.util.Iterator;
@@ -117,6 +118,7 @@
     private int _importPrecedence = 1;
     private Mode _defaultMode;
     private boolean _multiDocument = false;
+    private boolean _callsNodeset = false;
 
     // All named key elements (needed by Key/IdPattern)
     private Hashtable _keys = new Hashtable();
@@ -127,16 +129,22 @@
 
     private SourceLoader _loader = null;
 
-    private boolean _compileTemplatesAsMethods;
+    private boolean _templateInlining = true;
 
     private boolean _forwardReference = false;
 
+    private Properties _outputProperties = null;
+
     public void setForwardReference() {
 	_forwardReference = true;
     }
 
-    public void compileTemplatesAsMethods() {
-	_compileTemplatesAsMethods = true;
+    public boolean getTemplateInlining() {
+	return _templateInlining;
+    }
+
+    public void setTemplateInlining(boolean flag) {
+	_templateInlining = flag;
     }
 
     public boolean isSimplified() {
@@ -147,6 +155,21 @@
 	_simplified = true;
     }
     
+    public void setOutputProperty(String key, String value) {
+	if (_outputProperties == null) {
+	    _outputProperties = new Properties();
+	}
+	_outputProperties.setProperty(key, value);
+    }
+
+    public void setOutputProperties(Properties props) {
+	_outputProperties = props;
+    }
+
+    public Properties getOutputProperties() {
+	return _outputProperties;
+    }
+
     public void setMultiDocument(boolean flag) {	
 	_multiDocument = flag;
     }
@@ -155,6 +178,15 @@
 	return _multiDocument;
     }
 
+    public void setCallsNodeset(boolean flag) {
+	if (flag) setMultiDocument(flag);
+	_callsNodeset = flag;
+    }
+
+    public boolean callsNodeset() {
+	return _callsNodeset;
+    }
+
     public void numberFormattingUsed() {
 	_numberFormattingUsed = true;
     }
@@ -194,8 +226,9 @@
 
     public boolean checkForLoop(String systemId) {
 	// Return true if this stylesheet includes/imports itself
-	if (_systemId.equals(systemId))
+	if (_systemId != null && _systemId.equals(systemId)) {
 	    return true;
+	}
 	// Then check with any stylesheets that included/imported this one
 	if (_parentStylesheet != null) 
 	    return _parentStylesheet.checkForLoop(systemId);
@@ -284,7 +317,6 @@
 	super.addPrefixMapping(prefix, uri);
     }
 
-
     /**
      * Store extension URIs
      */
@@ -308,8 +340,10 @@
     public void excludeExtensionPrefixes(Parser parser) {
 	final SymbolTable stable = parser.getSymbolTable();
     	final String excludePrefixes = getAttribute("exclude-result-prefixes");
-	final String extensionPrefixes = 
-	    getAttribute("extension-element-prefixes");
+	final String extensionPrefixes = getAttribute("extension-element-prefixes");
+	
+	// Exclude XSLT uri 
+	stable.excludeURI(Constants.XSLT_URI);
 	stable.excludeNamespaces(excludePrefixes);
 	stable.excludeNamespaces(extensionPrefixes);
 	extensionURI(extensionPrefixes, stable);
@@ -399,9 +433,10 @@
 		parser.getSymbolTable().setCurrentNode(child);
 		child.parseContents(parser);
 	    }
+
 	    // All template code should be compiled as methods if the
 	    // <xsl:apply-imports/> element was ever used in this stylesheet
-	    if (_compileTemplatesAsMethods && (child instanceof Template)) {
+	    if (!_templateInlining && (child instanceof Template)) {
 		Template template = (Template)child;
 		String name = "template$dot$"+template.getPosition();
 		template.setName(parser.getQName(name));
@@ -692,23 +727,45 @@
 	return("("+DOM_INTF_SIG+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V");
     }
 
-
+    /**
+     * This method returns a vector with variables in the order in 
+     * which they are to be compiled. The order is determined by the 
+     * dependencies between them and the order in which they were defined 
+     * in the stylesheet. The first step is to close the input vector under
+     * the dependence relation (this is usually needed when variables are
+     * defined inside other variables in a RTF).
+     */
     private Vector resolveReferences(Vector input) {
+
+	// Make sure that the vector 'input' is closed
+	for (int i = 0; i < input.size(); i++) {
+	    final VariableBase var = (VariableBase) input.elementAt(i);
+	    final Vector dep  = var.getDependencies();
+	    final int depSize = (dep != null) ? dep.size() : 0;
+
+	    for (int j = 0; j < depSize; j++) {
+		final VariableBase depVar = (VariableBase) dep.elementAt(j);
+		if (!input.contains(depVar)) {
+		    input.addElement(depVar);
+		}
+	    }
+	}
+
+	/* DEBUG CODE - INGORE
+	for (int i = 0; i < input.size(); i++) {
+	    final VariableBase var = (VariableBase) input.elementAt(i);
+	    System.out.println("var = " + var);
+	}
+	System.out.println("=================================");
+	*/
+
 	Vector result = new Vector();
-
-	int zeroDep = 0;
-
 	while (input.size() > 0) {
 	    boolean changed = false;
 	    for (int i = 0; i < input.size(); ) {
 		final VariableBase var = (VariableBase)input.elementAt(i);
 		final Vector dep = var.getDependencies();
-		if (dep == null) {
-		    result.insertElementAt(var, zeroDep++);
-		    input.remove(i);
-		    changed = true;
-		}
-		else if (result.containsAll(dep)) {
+		if (dep == null || result.containsAll(dep)) {
 		    result.addElement(var);
 		    input.remove(i);
 		    changed = true;
@@ -717,6 +774,7 @@
 		    i++;
 		}
 	    }
+
 	    // If nothing was changed in this pass then we have a circular ref
 	    if (!changed) {
 		ErrorMsg err = new ErrorMsg(ErrorMsg.CIRCULAR_VARIABLE_ERR,
@@ -725,7 +783,16 @@
 		return(result);
 	    }
 	}
-	return(result);
+
+	/* DEBUG CODE - INGORE
+	System.out.println("=================================");
+	for (int i = 0; i < result.size(); i++) {
+	    final VariableBase var = (VariableBase) result.elementAt(i);
+	    System.out.println("var = " + var);
+	}
+	*/
+
+	return result;
     }
 
     /**
@@ -878,6 +945,18 @@
 					   "("+OUTPUT_HANDLER_SIG+")V");
 	il.append(new INVOKEVIRTUAL(index));
 
+	// Compile buildKeys -- TODO: omit if not needed
+	final String keySig = compileBuildKeys(classGen);
+	final int    keyIdx = cpg.addMethodref(getClassName(),
+					       "buildKeys", keySig);
+	il.append(classGen.loadTranslet());     // The 'this' pointer
+	il.append(classGen.loadTranslet());
+	il.append(new GETFIELD(domField));      // The DOM reference
+	il.append(transf.loadIterator());       // Not really used, but...
+	il.append(transf.loadHandler());        // The output handler
+	il.append(new PUSH(cpg, DOM.ROOTNODE)); // Start with the root node
+	il.append(new INVOKEVIRTUAL(keyIdx));
+
 	// Look for top-level elements that need handling
 	final Enumeration toplevel = elements();
 	if ((_globals.size() > 0) || (toplevel.hasMoreElements())) {
@@ -896,17 +975,6 @@
 	    il.append(new INVOKEVIRTUAL(topLevelIdx));
 	}
 	
-	final String keySig = compileBuildKeys(classGen);
-	final int    keyIdx = cpg.addMethodref(getClassName(),
-					       "buildKeys", keySig);
-	il.append(classGen.loadTranslet());     // The 'this' pointer
-	il.append(classGen.loadTranslet());
-	il.append(new GETFIELD(domField));      // The DOM reference
-	il.append(transf.loadIterator());       // Not really used, but...
-	il.append(transf.loadHandler());        // The output handler
-	il.append(new PUSH(cpg, DOM.ROOTNODE)); // Start with the root node
-	il.append(new INVOKEVIRTUAL(keyIdx));
-
 	// start document
 	il.append(transf.loadHandler());
 	il.append(transf.startDocument());
diff --git a/src/org/apache/xalan/xsltc/compiler/SymbolTable.java b/src/org/apache/xalan/xsltc/compiler/SymbolTable.java
index cf5c576..4575744 100644
--- a/src/org/apache/xalan/xsltc/compiler/SymbolTable.java
+++ b/src/org/apache/xalan/xsltc/compiler/SymbolTable.java
@@ -85,12 +85,12 @@
     private Hashtable _excludedURI = null;
     private Hashtable _decimalFormats = null;
 
-    public DecimalFormatting getDecimalFormatting(String name) {
+    public DecimalFormatting getDecimalFormatting(QName name) {
 	if (_decimalFormats == null) return null;
 	return((DecimalFormatting)_decimalFormats.get(name));
     }
 
-    public void addDecimalFormatting(String name, DecimalFormatting symbols) {
+    public void addDecimalFormatting(QName name, DecimalFormatting symbols) {
 	if (_decimalFormats == null) _decimalFormats = new Hashtable();
 	_decimalFormats.put(name, symbols);
     }
@@ -105,14 +105,12 @@
 
     public Template addTemplate(Template template) {
 	final QName name = template.getName();
-	name.clearDefaultNamespace();
 	if (_templates == null) _templates = new Hashtable();
 	return (Template)_templates.put(name, template);
     }
 	
     public Template lookupTemplate(QName name) {
 	if (_templates == null) return null;
-	name.clearDefaultNamespace();
 	return (Template)_templates.get(name);
     }
 
@@ -262,11 +260,10 @@
      * Check if a namespace should not be declared in the output (unless used)
      */
     public boolean isExcludedNamespace(String uri) {
-	if (uri == null) return false;
-	if (_excludedURI == null) return false;
-	final Integer refcnt = (Integer)_excludedURI.get(uri);
-	if (refcnt == null) return false;
-	if (refcnt.intValue() > 0) return true;
+	if (uri != null && _excludedURI != null) {
+	    final Integer refcnt = (Integer)_excludedURI.get(uri);
+	    return (refcnt != null && refcnt.intValue() > 0);
+	}
 	return false;
     }
 
diff --git a/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java b/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java
index 26f6c13..322781c 100644
--- a/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java
+++ b/src/org/apache/xalan/xsltc/compiler/SyntaxTreeNode.java
@@ -193,18 +193,16 @@
      * @return The value of the attribute of name 'qname'.
      */
     protected String getAttribute(String qname) {
-	if (_attributes == null)
-	    return(Constants.EMPTYSTRING);
+	if (_attributes == null) {
+	    return EMPTYSTRING;
+	}
 	final String value = _attributes.getValue(qname);
-	if (value == null)
-	    return(Constants.EMPTYSTRING);
-	else
-	    return(value);
+	return (value == null || value.equals(EMPTYSTRING)) ? 
+	    EMPTYSTRING : value;
     }
 
     protected boolean hasAttribute(String qname) {
-	if (_attributes == null) return false;
-	return (_attributes.getValue(qname) != null);
+	return (_attributes != null && _attributes.getValue(qname) != null);
     }
 
     /**
@@ -554,10 +552,11 @@
      * @param methodGen BCEL Java method generator
      */
     protected void compileResultTree(ClassGenerator classGen,
-				     MethodGenerator methodGen) {
-
+				     MethodGenerator methodGen) 
+    {
 	final ConstantPoolGen cpg = classGen.getConstantPool();
 	final InstructionList il = methodGen.getInstructionList();
+	final Stylesheet stylesheet = classGen.getStylesheet();
 
 	// Save the current handler base on the stack
 	il.append(methodGen.loadHandler());
@@ -602,13 +601,42 @@
 	    il.append(new NEW(cpg.addClass(DOM_ADAPTER_CLASS)));
 	    il.append(new DUP_X1());
 	    il.append(SWAP);
-	    // Give the DOM adapter an empty type mapping to start with.
-	    // Type mapping is expensive and will only be done when casting
-	    // a result tree fragment to a node-set.
-	    il.append(new ICONST(0));
-	    il.append(new ANEWARRAY(cpg.addClass(STRING)));
-	    il.append(DUP);
-	    il.append(new INVOKESPECIAL(index)); // leave DOMAdapter on stack
+
+	    /*
+	     * Give the DOM adapter an empty type mapping if the nodeset
+	     * extension function is never called.
+	     */
+	    if (!stylesheet.callsNodeset()) {
+		il.append(new ICONST(0));
+		il.append(new ANEWARRAY(cpg.addClass(STRING)));
+		il.append(DUP);
+		il.append(new INVOKESPECIAL(index));
+	    }
+	    else {
+		// Push name arrays on the stack
+		il.append(ALOAD_0);
+		il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
+					   NAMES_INDEX,
+					   NAMES_INDEX_SIG))); 
+		il.append(ALOAD_0);
+		il.append(new GETFIELD(cpg.addFieldref(TRANSLET_CLASS,
+					   NAMESPACE_INDEX,
+					   NAMESPACE_INDEX_SIG)));
+
+		// Initialized DOM adapter
+		il.append(new INVOKESPECIAL(index));
+
+		// Add DOM adapter to MultiDOM class by calling addDOMAdapter()
+		il.append(DUP);
+		il.append(methodGen.loadDOM());
+		il.append(new CHECKCAST(cpg.addClass(classGen.getDOMClass())));
+		il.append(SWAP);
+		index = cpg.addMethodref(MULTI_DOM_CLASS,
+					 "addDOMAdapter",
+					 "(" + DOM_ADAPTER_SIG + ")I");
+		il.append(new INVOKEVIRTUAL(index));
+		il.append(POP);		// ignore mask returned by addDOMAdapter
+	    }
 	}
 
 	// Restore old handler base from stack
diff --git a/src/org/apache/xalan/xsltc/compiler/Template.java b/src/org/apache/xalan/xsltc/compiler/Template.java
index 6191e9e..07b6186 100644
--- a/src/org/apache/xalan/xsltc/compiler/Template.java
+++ b/src/org/apache/xalan/xsltc/compiler/Template.java
@@ -245,11 +245,11 @@
 	_stylesheet = super.getStylesheet();
 
 	if (name.length() > 0) {
-	    _name = parser.getQName(name);
+	    _name = parser.getQNameIgnoreDefaultNs(name);
 	}
 	
 	if (mode.length() > 0) {
-	    _mode = parser.getQName(mode);
+	    _mode = parser.getQNameIgnoreDefaultNs(mode);
 	}
 	
 	if (match.length() > 0) {
diff --git a/src/org/apache/xalan/xsltc/compiler/TestSeq.java b/src/org/apache/xalan/xsltc/compiler/TestSeq.java
index 2f4b644..0ea54cb 100644
--- a/src/org/apache/xalan/xsltc/compiler/TestSeq.java
+++ b/src/org/apache/xalan/xsltc/compiler/TestSeq.java
@@ -73,18 +73,18 @@
 import org.apache.bcel.generic.*;
 import org.apache.xalan.xsltc.compiler.util.*;
 
+/**
+ * A test sequence is a sequence of patterns that
+ *
+ *  (1) occured in templates in the same mode
+ *  (2) share the same kernel node type (such as A/B and C/C/B).
+ *
+ * A test sequence may have a default template, which will be run if
+ * none of the patterns do not match. This template is always a template
+ * that matches solely on the shared kernel node type.
+ */
 final class TestSeq {
 
-    /*
-     * A test sequence is a sequence of patterns that
-     *
-     *  (1) occured in templates in the same mode
-     *  (2) share the same kernel node type (such as A/B and C/C/B).
-     *
-     * A test sequence may have a default template, which will be run if
-     * none of the patterns do not match. This template is always a template
-     * that matches solely on the shared kernel node type.
-     */
     private Vector   _patterns = null; // all patterns
     private Mode     _mode     = null; // the shared mode
     private Template _default  = null; // the default template
@@ -107,6 +107,7 @@
     public double getPriority() {
 	double prio = (0 - Double.MAX_VALUE);
 	final int count = _patterns.size();
+
 	for (int i = 0; i < count; i++) {
 	    final Pattern pattern = (Pattern)_patterns.elementAt(i);
 	    final Template template = pattern.getTemplate();
@@ -127,6 +128,7 @@
     public int getPosition() {
 	int pos = Integer.MIN_VALUE;
 	final int count = _patterns.size();
+
 	for (int i = 0; i < count; i++) {
 	    final Pattern pattern = (Pattern)_patterns.elementAt(i);
 	    final Template template = pattern.getTemplate();
@@ -144,7 +146,7 @@
      * Reduce the patterns in this test sequence to exclude the shared
      * kernel node type. After the switch() in the translet's applyTemplates()
      * we already know that we have a hit for the kernel node type, we only
-     * have the check the rest of the pattens.
+     * have the check the rest of the pattern.
      */
     public void reduce() {
 	final Vector newPatterns = new Vector();
diff --git a/src/org/apache/xalan/xsltc/compiler/Text.java b/src/org/apache/xalan/xsltc/compiler/Text.java
index aa07fe9..93b1689 100644
--- a/src/org/apache/xalan/xsltc/compiler/Text.java
+++ b/src/org/apache/xalan/xsltc/compiler/Text.java
@@ -126,7 +126,12 @@
 	parseChildren(parser);
 
 	if (_text == null) {
-	    _ignore = true;
+	    if (_textElement) {
+		_text = EMPTYSTRING;
+	    }
+	    else {
+		_ignore = true;
+	    }
 	}
 	else if (_textElement) {
 	    if (_text.length() == 0) _ignore = true;
@@ -162,35 +167,27 @@
 	    // Turn off character escaping if so is wanted.
 	    final int esc = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
 						      "setEscaping", "(Z)Z");
-	    // set escaping value in output handler 
-	    if (_escaping) {
-		il.append(methodGen.loadHandler());
-		il.append(new PUSH(cpg,true));
-		il.append(new INVOKEINTERFACE(esc, 2));
-	    } else {
+	    if (!_escaping) {
 		il.append(methodGen.loadHandler());
 		il.append(new PUSH(cpg, false));
 		il.append(new INVOKEINTERFACE(esc, 2));
 	    }
 
-	    final int toCharArr = cpg.addMethodref("java/lang/String",
-						  "toCharArray", "()[C");
 	    final int characters = cpg.addInterfaceMethodref(OUTPUT_HANDLER,
 							     "characters",
-							     "([CII)V");
+							     "(" + STRING_SIG + ")V");
 	    il.append(methodGen.loadHandler());
 	    il.append(new PUSH(cpg, _text));
-	    il.append(new INVOKEVIRTUAL(toCharArr));
-	    il.append(new ICONST(0));
-	    il.append(new PUSH(cpg, _text.length()));
-	    il.append(new INVOKEINTERFACE(characters, 4));
+	    il.append(new INVOKEINTERFACE(characters, 2));
 
 	    // Restore character escaping setting to whatever it was.
 	    // Note: setEscaping(bool) returns the original (old) value
-	    il.append(methodGen.loadHandler());
-	    il.append(SWAP);
-	    il.append(new INVOKEINTERFACE(esc, 2));
-	    il.append(POP);
+	    if (!_escaping) {
+		il.append(methodGen.loadHandler());
+		il.append(SWAP);
+		il.append(new INVOKEINTERFACE(esc, 2));
+		il.append(POP);
+	    }
 	}
 	translateContents(classGen, methodGen);
     }
diff --git a/src/org/apache/xalan/xsltc/compiler/UnresolvedRef.java b/src/org/apache/xalan/xsltc/compiler/UnresolvedRef.java
index 276a87b..baa8cc6 100644
--- a/src/org/apache/xalan/xsltc/compiler/UnresolvedRef.java
+++ b/src/org/apache/xalan/xsltc/compiler/UnresolvedRef.java
@@ -119,10 +119,10 @@
 	    ErrorMsg err = new ErrorMsg(ErrorMsg.CIRCULAR_VARIABLE_ERR,
 					name, this);
 	}
-	if ((_ref = resolve(getParser(), stable)) != null)
-	    return(_ref.typeCheck(stable));
-	else
-	    throw new TypeCheckError(reportError());
+	if ((_ref = resolve(getParser(), stable)) != null) {
+	    return (_type = _ref.typeCheck(stable));
+	}
+	throw new TypeCheckError(reportError());
     }
 
     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
@@ -131,4 +131,9 @@
 	else
 	    reportError();
     }
+
+    public String toString() {
+	return "unresolved-ref()";
+    }
+
 }
diff --git a/src/org/apache/xalan/xsltc/compiler/UseAttributeSets.java b/src/org/apache/xalan/xsltc/compiler/UseAttributeSets.java
index abe1e59..42c1a64 100644
--- a/src/org/apache/xalan/xsltc/compiler/UseAttributeSets.java
+++ b/src/org/apache/xalan/xsltc/compiler/UseAttributeSets.java
@@ -99,7 +99,8 @@
 	if ((setNames != null) && (!setNames.equals(Constants.EMPTYSTRING))) {
 	    final StringTokenizer tokens = new StringTokenizer(setNames);
 	    while (tokens.hasMoreTokens()) {
-		final QName qname = getParser().getQName(tokens.nextToken());
+		final QName qname = 
+		    getParser().getQNameIgnoreDefaultNs(tokens.nextToken());
 		_sets.add(qname);
 	    }
 	}
diff --git a/src/org/apache/xalan/xsltc/compiler/VariableBase.java b/src/org/apache/xalan/xsltc/compiler/VariableBase.java
index 5a8bd04..e10c511 100644
--- a/src/org/apache/xalan/xsltc/compiler/VariableBase.java
+++ b/src/org/apache/xalan/xsltc/compiler/VariableBase.java
@@ -125,8 +125,12 @@
      *
      */
     public void addDependency(VariableBase other) {
-	if (_dependencies == null) _dependencies = new Vector();
-	_dependencies.addElement(other);
+	if (_dependencies == null) {
+	    _dependencies = new Vector();
+	}
+	if (!_dependencies.contains(other)) {
+	    _dependencies.addElement(other);
+	}
     }
 
     /**
@@ -227,7 +231,6 @@
      */
     public void setName(QName name) {
 	_name = name;
-	_name.clearDefaultNamespace();
 	_variable = Util.escape(name.getLocalPart());
     }
 
@@ -247,7 +250,7 @@
 	if (name == null) name = EMPTYSTRING;
 
 	if (name.length() > 0)
-	    setName(parser.getQName(name));
+	    setName(parser.getQNameIgnoreDefaultNs(name));
         else
 	    reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "name");
 
@@ -260,6 +263,10 @@
 	select = getAttribute("select");
 	if (select.length() > 0) {
 	    _select = getParser().parseExpression(this, "select", null);
+	    if (_select.isDummy()) {
+		reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "select");
+		return;
+	    }
 	}
 
 	// Children must be parsed first -> static scoping
diff --git a/src/org/apache/xalan/xsltc/compiler/When.java b/src/org/apache/xalan/xsltc/compiler/When.java
index 825a1e3..d2e4250 100644
--- a/src/org/apache/xalan/xsltc/compiler/When.java
+++ b/src/org/apache/xalan/xsltc/compiler/When.java
@@ -90,13 +90,12 @@
 
     public void parseContents(Parser parser) {
 	_test = parser.parseExpression(this, "test", null);
-	if (_test instanceof ElementAvailableCall) {
-	    ElementAvailableCall call = (ElementAvailableCall)_test;
-	    _ignore = !call.getResult();
-	}
-	if (_test instanceof FunctionAvailableCall) {
-	    FunctionAvailableCall call = (FunctionAvailableCall)_test;
-	    _ignore = !call.getResult();
+
+	// Ignore xsl:if when test is false (function-available() and
+	// element-available())
+	Object result = _test.evaluateAtCompileTime();
+	if (result != null && result instanceof Boolean) {
+	    _ignore = !((Boolean) result).booleanValue();
 	}
 
 	parseChildren(parser);
diff --git a/src/org/apache/xalan/xsltc/compiler/XSLTC.java b/src/org/apache/xalan/xsltc/compiler/XSLTC.java
index 4baf1ed..988f6c7 100644
--- a/src/org/apache/xalan/xsltc/compiler/XSLTC.java
+++ b/src/org/apache/xalan/xsltc/compiler/XSLTC.java
@@ -67,9 +67,10 @@
 package org.apache.xalan.xsltc.compiler;
 
 import java.io.*;
+import java.util.Set;
 import java.util.Vector;
 import java.util.Hashtable;
-import java.util.Set;
+import java.util.Properties;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Enumeration;
@@ -139,7 +140,9 @@
     private int     _outputType = FILE_OUTPUT; // by default
 
     private Vector  _classes;
+    private boolean _callsNodeset = false;
     private boolean _multiDocument = false;
+    private boolean _templateInlining = true;
 
     /**
      * XSLTC compiler constructor
@@ -163,6 +166,13 @@
     }
 
     /**
+     * Only for user by the internal TrAX implementation.
+     */
+    public Properties getOutputProperties() {
+	return _parser.getOutputProperties();
+    }
+
+    /**
      * Initializes the compiler to compile a new stylesheet
      */
     public void init() {
@@ -207,6 +217,16 @@
     }
 
     /**
+     * Set a flag indicating if templates are to be inlined or not. The
+     * default is to do inlining, but this causes problems when the
+     * stylesheets have a large number of templates (e.g. branch targets
+     * exceeding 64K or a length of a method exceeding 64K).
+     */
+    public void setTemplateInlining(boolean templateInlining) {
+	_templateInlining = templateInlining;
+    }
+
+    /**
      * Set the parameters to use to locate the correct <?xml-stylesheet ...?>
      * processing instruction in the case where the input document to the
      * compiler (and parser) is an XML document.
@@ -311,12 +331,15 @@
 		_stylesheet.setSourceLoader(_loader);
 		_stylesheet.setSystemId(systemId);
 		_stylesheet.setParentStylesheet(null);
+		_stylesheet.setTemplateInlining(_templateInlining);
 		_parser.setCurrentStylesheet(_stylesheet);
+
 		// Create AST under the Stylesheet element (parse & type-check)
 		_parser.createAST(_stylesheet);
 	    }
 	    // Generate the bytecodes and output the translet class(es)
 	    if ((!_parser.errorsFound()) && (_stylesheet != null)) {
+		_stylesheet.setCallsNodeset(_callsNodeset);
 		_stylesheet.setMultiDocument(_multiDocument);
 		_stylesheet.translate();
 	    }
@@ -435,7 +458,6 @@
 	_parser.printWarnings();
     }
 
-
     /**
      * This method is called by the XPathParser when it encounters a call
      * to the document() function. Affects the DOM used by the translet.
@@ -449,6 +471,19 @@
     }
 
     /**
+     * This method is called by the XPathParser when it encounters a call
+     * to the nodeset() extension function. Implies multi document.
+     */
+    protected void setCallsNodeset(boolean flag) {
+	if (flag) setMultiDocument(flag);
+	_callsNodeset = flag;
+    }
+
+    public boolean callsNodeset() {
+	return _callsNodeset;
+    }
+
+    /**
      * Set the class name for the generated translet. This class name is
      * overridden if multiple stylesheets are compiled in one go using the
      * compile(Vector urls) method.
@@ -653,7 +688,10 @@
 	try {
 	    switch (_outputType) {
 	    case FILE_OUTPUT:
-		clazz.dump(getOutputFile(clazz.getClassName()));
+		clazz.dump(
+		    new BufferedOutputStream(
+			new FileOutputStream(
+			    getOutputFile(clazz.getClassName()))));
 		break;
 	    case JAR_OUTPUT:
 		_classes.addElement(clazz);	 
@@ -685,7 +723,7 @@
 	// create the manifest
 	final Manifest manifest = new Manifest();
 	final java.util.jar.Attributes atrs = manifest.getMainAttributes();
-	atrs.put(java.util.jar.Attributes.Name.MANIFEST_VERSION,"1.0");
+	atrs.put(java.util.jar.Attributes.Name.MANIFEST_VERSION,"1.1");
 
 	final Map map = manifest.getEntries();
 	// create manifest
diff --git a/src/org/apache/xalan/xsltc/compiler/XslAttribute.java b/src/org/apache/xalan/xsltc/compiler/XslAttribute.java
index f6e8b6e..96f64f9 100644
--- a/src/org/apache/xalan/xsltc/compiler/XslAttribute.java
+++ b/src/org/apache/xalan/xsltc/compiler/XslAttribute.java
@@ -73,10 +73,9 @@
 
 final class XslAttribute extends Instruction {
 
-    // Attribute contents
-    private AttributeValue _name; // name treated as AVT (7.1.3)
-    private AttributeValueTemplate _namespace = null;
     private String _prefix;
+    private AttributeValue _name; 	// name treated as AVT (7.1.3)
+    private AttributeValueTemplate _namespace = null;
     private boolean _ignore = false;
 
     /**
@@ -99,15 +98,15 @@
      * Parses the attribute's contents. Special care taken for namespaces.
      */
     public void parseContents(Parser parser) {
-
-	final SymbolTable stable = parser.getSymbolTable();
-	String namespace = getAttribute("namespace");
-	String name = getAttribute("name");
-	QName qname = parser.getQName(name);
-	final String prefix = qname.getPrefix();
 	boolean generated = false;
+	final SymbolTable stable = parser.getSymbolTable();
 
-	if ((prefix != null) && (prefix.equals("xmlns"))) {
+	String name = getAttribute("name");
+	String namespace = getAttribute("namespace");
+	QName qname = parser.getQName(name, false);
+	final String prefix = qname.getPrefix();
+
+	if ((prefix != null) && (prefix.equals(XMLNS_PREFIX))) {
 	    reportError(this, parser, ErrorMsg.ILLEGAL_ATTR_NAME_ERR, name);
 	    return;
 	}
@@ -118,11 +117,13 @@
 	for (int i = 0; i < parent.elementCount(); i++) {
 	    SyntaxTreeNode item = (SyntaxTreeNode)siblings.elementAt(i);
 	    if (item == this) break;
+
 	    // These three objects result in one or more attribute output
 	    if (item instanceof XslAttribute) continue;
 	    if (item instanceof UseAttributeSets) continue;
 	    if (item instanceof LiteralAttribute) continue;
 	    if (item instanceof Text) continue;
+
 	    // These objects _can_ result in one or more attribute
 	    // The output handler will generate an error if not (at runtime)
 	    if (item instanceof If) continue;
@@ -134,24 +135,23 @@
 	}
 
 	// Get namespace from namespace attribute?
-	if ((namespace != null) && (namespace != Constants.EMPTYSTRING)) {
-	    // Prefix could be in symbol table
+	if (namespace != null && namespace != Constants.EMPTYSTRING) {
 	    _prefix = lookupPrefix(namespace);
-	    _namespace = new AttributeValueTemplate(namespace, parser);
+	    _namespace = new AttributeValueTemplate(namespace, parser, this);
 	}
 	// Get namespace from prefix in name attribute?
-	else if ((prefix != null) && (prefix != Constants.EMPTYSTRING)) {
+	else if (prefix != null && prefix != Constants.EMPTYSTRING) {
 	    _prefix = prefix;
 	    namespace = lookupNamespace(prefix);
-	    if (namespace != null)
-		_namespace = new AttributeValueTemplate(namespace, parser);
+	    if (namespace != null) {
+		_namespace = new AttributeValueTemplate(namespace, parser, this);
+	    }
 	}
 	
 	// Common handling for namespaces:
 	if (_namespace != null) {
-
 	    // Generate prefix if we have none
-	    if (_prefix == null) {
+	    if (_prefix == null || _prefix == Constants.EMPTYSTRING) {
 		if (prefix != null) {
 		    _prefix = prefix;
 		}
@@ -160,25 +160,25 @@
 		    generated = true;
 		}
 	    }
-
-	    if (_prefix == Constants.EMPTYSTRING) {
-		name = qname.getLocalPart();
+	    else if (prefix != null && !prefix.equals(_prefix)) {
+		_prefix = prefix;
 	    }
-	    else {
-		name = _prefix+":"+qname.getLocalPart();
-		// PROBLEM:
-		// The namespace URI must be passed to the parent element,
-		// but we don't yet know what the actual URI is (as we only
-		// know it as an attribute value template). New design needed.
-		if ((parent instanceof LiteralElement) && (!generated)) {
-		    ((LiteralElement)parent).registerNamespace(_prefix,
-							       namespace,
-							       stable,false);
-		}
+
+	    name = _prefix + ":" + qname.getLocalPart();
+
+	    /*
+	     * TODO: The namespace URI must be passed to the parent 
+	     * element but we don't yet know what the actual URI is 
+	     * (as we only know it as an attribute value template). 
+	     */
+	    if ((parent instanceof LiteralElement) && (!generated)) {
+		((LiteralElement)parent).registerNamespace(_prefix,
+							   namespace,
+							   stable, false);
 	    }
 	}
 
-	if (name.equals("xmlns")) {
+	if (name.equals(XMLNS_PREFIX)) {
 	    reportError(this, parser, ErrorMsg.ILLEGAL_ATTR_NAME_ERR, name);
 	    return;
 	}
@@ -191,15 +191,14 @@
 	parseChildren(parser);
     }
 	
-    /**
-     *
-     */
     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
-	if (_ignore) return(Type.Void);
-	_name.typeCheck(stable);
-	if (_namespace != null)
-	    _namespace.typeCheck(stable);
-	typeCheckContents(stable);
+	if (!_ignore) {
+	    _name.typeCheck(stable);
+	    if (_namespace != null) {
+		_namespace.typeCheck(stable);
+	    }
+	    typeCheckContents(stable);
+	}
 	return Type.Void;
     }
 
diff --git a/src/org/apache/xalan/xsltc/compiler/XslElement.java b/src/org/apache/xalan/xsltc/compiler/XslElement.java
index 84d7d38..6f3df54 100644
--- a/src/org/apache/xalan/xsltc/compiler/XslElement.java
+++ b/src/org/apache/xalan/xsltc/compiler/XslElement.java
@@ -74,10 +74,11 @@
 
 final class XslElement extends Instruction {
 
-    private AttributeValue _name; // name treated as AVT (7.1.3)
-    private AttributeValueTemplate _namespace = null;
     private String  _prefix;
     private boolean _ignore = false;
+    private boolean _isLiteralName = true;
+    private AttributeValueTemplate _name; 
+    private AttributeValueTemplate _namespace;
 
     /**
      * Displays the contents of the element
@@ -89,87 +90,124 @@
     }
 
     /**
-     * Parses the element's contents. Special care taken for namespaces.
-     * TODO: The namespace attribute that specifies the namespace to use
-     * for the element is an attribute value template and not a string
-     * constant. This means that we do not know what namespace is used
-     * before runtime. This causes a problem with the way output namespaces
-     * are handled at compile-time. We use a shortcut in this method to get
-     * around the problem by treating the namaspace attribute as a constant.
-     *          (Yes, I know this is a hack, bad, bad, bad.)
+     * This method is now deprecated. The new implemation of this class
+     * never declares the default NS.
      */
-    public void parseContents(Parser parser) {
+    public boolean declaresDefaultNS() {
+	return false;
+    }
 
+    /**
+     * Checks if <param>str</param> is a literal (i.e. not an AVT) or not.
+     */
+    private boolean isLiteral(String str) {
+	final int length = str.length();
+	for (int i = 0; i < length; i++) {
+	    if (str.charAt(i) == '{' && str.charAt(i + 1) != '{') {
+		return false;
+	    }
+	}
+	return true;
+    }
+
+    /**
+     * Simple check to determine if qname is legal. If it returns false
+     * then <param>str</param> is illegal; if it returns true then 
+     * <param>str</param> may or may not be legal.
+     */
+    private boolean isLegalName(String str) {
+	if (str.indexOf(' ') > -1) {
+	    return false;
+	}
+	final int colon = str.indexOf(':');
+	if (colon == 0 || colon == str.length() - 1) {
+	    return false;
+	}
+	final char first = str.charAt(0);
+	if (!Character.isLetter(first) && first != '_') {
+	    return false;
+	}
+	return true;
+    }
+
+    public void parseContents(Parser parser) {
 	final SymbolTable stable = parser.getSymbolTable();
 
-	// Get the "name" attribute of the <xsl:element> element
+	// Handle the 'name' attribute
 	String name = getAttribute("name");
-	if ((name == null) || (name.equals(EMPTYSTRING))) {
+	if (name == EMPTYSTRING) {
 	    ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ELEM_NAME_ERR,
 					name, this);
 	    parser.reportError(WARNING, msg);
-	    _ignore = true; // Ignore the element if the QName is invalid
+	    parseChildren(parser);
+	    _ignore = true; 	// Ignore the element if the QName is invalid
 	    return;
 	}
 
-	// Try to construct a QName and then get the prefix and local part
-	QName  qname  = parser.getQNameSafe(name);
-	String prefix = qname.getPrefix();
-	String local  = qname.getLocalPart();
-
-	// First try to get the namespace URI from the "namespace" attribute
+	// Get namespace attribute
 	String namespace = getAttribute("namespace");
-	// Then try to get it from the "name" attribute QName prefix
-	if (!hasAttribute("namespace")) {
-	    // We are supposed to use the default namespace URI if the QName
-	    // from the "name" attribute is not prefixed, so check that first
-	    if (prefix == null) prefix = EMPTYSTRING;
-	    // Then look up the URI that is in scope for the prefix
-	    namespace = lookupNamespace(prefix); 
 
-	    // Signal error if the prefix does not map to any namespace URI 
-	    if (namespace == null) {
-		ErrorMsg err = new ErrorMsg(ErrorMsg.NAMESPACE_UNDEF_ERR,
-					    prefix, this);
-		parser.reportError(WARNING, err);
+	// Optimize compilation when name is known at compile time
+	_isLiteralName = isLiteral(name);
+	if (_isLiteralName) {
+	    if (!isLegalName(name)) {
+		ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ELEM_NAME_ERR,
+					    name, this);
+		parser.reportError(WARNING, msg);
 		parseChildren(parser);
-		_ignore = true; // Ignore the element if prefix is undeclared
+		_ignore = true; 	// Ignore the element if the QName is invalid
 		return;
 	    }
-	    _namespace = new AttributeValueTemplate(namespace, parser);
-	    _prefix = prefix;
+
+	    final QName qname = parser.getQNameSafe(name);
+	    String prefix = qname.getPrefix();
+	    String local = qname.getLocalPart();
+	    
+	    if (prefix == null) {
+		prefix = EMPTYSTRING;
+	    }
+
+	    if (!hasAttribute("namespace")) {
+		namespace = lookupNamespace(prefix); 
+		if (namespace == null) {
+		    ErrorMsg err = new ErrorMsg(ErrorMsg.NAMESPACE_UNDEF_ERR,
+						prefix, this);
+		    parser.reportError(WARNING, err);
+		    parseChildren(parser);
+		    _ignore = true; 	// Ignore the element if prefix is undeclared
+		    return;
+		}
+		_prefix = prefix;
+		_namespace = (namespace == EMPTYSTRING) ? null :
+			     new AttributeValueTemplate(namespace, parser, this);
+	    }
+	    else {
+		if (prefix == EMPTYSTRING) {
+		    if (isLiteral(namespace)) {
+			prefix = lookupPrefix(namespace);
+			if (prefix == null) {
+			    prefix = stable.generateNamespacePrefix();
+			}
+		    }
+
+		    // Prepend prefix to local name
+		    final StringBuffer newName = new StringBuffer(prefix);
+		    if (prefix != EMPTYSTRING) {
+			newName.append(':');
+		    }
+		    name = newName.append(local).toString();
+		}
+		_prefix = prefix;
+		_namespace = new AttributeValueTemplate(namespace, parser, this);
+	    }
 	}
-	// Check if this element belongs in a specific namespace
 	else {
-	    // Get the namespace requested by the xsl:element
-	    _namespace = new AttributeValueTemplate(namespace, parser);
-	    // Get the current prefix for that namespace (if any)
-	    _prefix = lookupPrefix(namespace);
-	    // Is it the default namespace?
-	    if ((_prefix = prefix) == null) _prefix = EMPTYSTRING;
-
-	    // Construct final element QName
-	    if (_prefix == EMPTYSTRING)
-		name = qname.getLocalPart();
-	    else
-		name = _prefix+":"+qname.getLocalPart();
+	    _namespace = (namespace == EMPTYSTRING) ? null :
+			 new AttributeValueTemplate(namespace, parser, this);
 	}
 
-	_name = AttributeValue.create(this, name, parser);
+	_name = new AttributeValueTemplate(name, parser, this);
 
-	// Next check that the local part of the QName is legal (no whitespace)
-	if (_name instanceof SimpleAttributeValue) {
-	    if (local.equals(EMPTYSTRING) || (local.indexOf(' ') > -1)) {
-		ErrorMsg err = new ErrorMsg(ErrorMsg.ILLEGAL_ELEM_NAME_ERR,
-					    local, this);
-		parser.reportError(WARNING, err);
-		parseChildren(parser);
-		_ignore = true; // Ignore the element if local part is invalid
-		return;
-	    }
-	}
-
-	// Handle the 'use-attribute-sets' attribute
 	final String useSets = getAttribute("use-attribute-sets");
 	if (useSets.length() > 0) {
 	    setFirstElement(new UseAttributeSets(useSets, parser));
@@ -184,34 +222,30 @@
     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
 	if (!_ignore) {
 	    _name.typeCheck(stable);
-	    if (_namespace != null)
+	    if (_namespace != null) {
 		_namespace.typeCheck(stable);
+	    }
 	}
 	typeCheckContents(stable);
 	return Type.Void;
     }
 
     /**
-     * Compiles code that emits the element with the necessary namespace
-     * definitions. The element itself is ignored if the element definition
-     * was in any way erronous, but the child nodes are still processed.
-     * See the overriden translateContents() method as well.
+     * This method is called when the name of the element is known at compile time.
+     * In this case, there is no need to inspect the element name at runtime to
+     * determine if a prefix exists, needs to be generated, etc.
      */
-    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
+    public void translateLiteral(ClassGenerator classGen, MethodGenerator methodGen) {
 	final ConstantPoolGen cpg = classGen.getConstantPool();
 	final InstructionList il = methodGen.getInstructionList();
 
-	// Ignore this element if not correctly declared
 	if (!_ignore) {
-	    // Compile code that emits the element start tag
 	    il.append(methodGen.loadHandler());
 	    _name.translate(classGen, methodGen);
-	    il.append(DUP2);	// duplicate these 2 args for endElement
+	    il.append(DUP2);
 	    il.append(methodGen.startElement());
 
-	    // Compile code that emits any needed namespace declaration
 	    if (_namespace != null) {
-		// public void attribute(final String name, final String value)
 		il.append(methodGen.loadHandler());
 		il.append(new PUSH(cpg, _prefix));
 		_namespace.translate(classGen,methodGen);
@@ -219,12 +253,94 @@
 	    }
 	}
 
-	// Compile code that emits the element attributes and contents
 	translateContents(classGen, methodGen);
 
-	// Ignore this element if not correctly declared
 	if (!_ignore) {
-	    // Compile code that emits the element end tag
+	    il.append(methodGen.endElement());
+	}
+    }
+
+    /**
+     * At runtime the compilation of xsl:element results in code that: (i)
+     * evaluates the avt for the name, (ii) checks for a prefix in the name
+     * (iii) generates a new prefix and create a new qname when necessary
+     * (iv) calls startElement() on the handler (v) looks up a uri in the XML
+     * when the prefix is not known at compile time (vi) calls namespace() 
+     * on the handler (vii) evaluates the contents (viii) calls endElement().
+     */
+    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
+	LocalVariableGen local = null;
+	final ConstantPoolGen cpg = classGen.getConstantPool();
+	final InstructionList il = methodGen.getInstructionList();
+
+	// Optimize translation if element name is a literal
+	if (_isLiteralName) {
+	    translateLiteral(classGen, methodGen);
+	    return;
+	}
+
+	if (!_ignore) {
+	    il.append(methodGen.loadHandler());
+	    _name.translate(classGen, methodGen);
+
+	    // Call BasisLibrary.getPrefix() and store result in local variable
+	    il.append(DUP);
+	    final int getPrefix = cpg.addMethodref(BASIS_LIBRARY_CLASS, "getPrefix",
+					      "(" + STRING_SIG + ")" + STRING_SIG);
+	    il.append(new INVOKESTATIC(getPrefix));
+	    il.append(DUP);
+	    local = methodGen.addLocalVariable("prefix", 
+					       org.apache.bcel.generic.Type.STRING,
+					       il.getEnd(), null);
+	    il.append(new ASTORE(local.getIndex()));
+
+	    // If prefix is null then generate a prefix at runtime
+	    final BranchHandle ifNotNull = il.append(new IFNONNULL(null));
+	    if (_namespace != null) {
+		final int generatePrefix = cpg.addMethodref(BASIS_LIBRARY_CLASS, 
+							    "generatePrefix", 
+							    "()" + STRING_SIG);
+		il.append(new INVOKESTATIC(generatePrefix));
+		il.append(DUP);
+		il.append(new ASTORE(local.getIndex()));
+
+		// Prepend newly generated prefix to the name
+		final int makeQName = cpg.addMethodref(BASIS_LIBRARY_CLASS, "makeQName", 
+				       "(" + STRING_SIG + STRING_SIG + ")" + STRING_SIG);
+		il.append(new INVOKESTATIC(makeQName));
+	    }
+	    ifNotNull.setTarget(il.append(DUP2));
+	    il.append(methodGen.startElement());
+
+	    if (_namespace != null) {
+		il.append(methodGen.loadHandler());
+		il.append(new ALOAD(local.getIndex()));
+		_namespace.translate(classGen, methodGen);
+		il.append(methodGen.namespace());
+	    }
+	    else {
+		// If prefix not known at compile time, call DOM.lookupNamespace()
+		il.append(new ALOAD(local.getIndex()));
+		final BranchHandle ifNull = il.append(new IFNULL(null));
+		il.append(methodGen.loadHandler());
+		il.append(new ALOAD(local.getIndex()));
+
+		il.append(methodGen.loadDOM());
+		il.append(methodGen.loadCurrentNode());
+		il.append(new ALOAD(local.getIndex()));
+
+		final int lookupNamespace = cpg.addInterfaceMethodref(DOM_INTF, 
+					"lookupNamespace", 
+				        "(I" + STRING_SIG + ")" + STRING_SIG);
+		il.append(new INVOKEINTERFACE(lookupNamespace, 3));
+		il.append(methodGen.namespace());
+		ifNull.setTarget(il.append(NOP));
+	    }
+	}
+
+	translateContents(classGen, methodGen);
+
+	if (!_ignore) {
 	    il.append(methodGen.endElement());
 	}
     }
@@ -239,7 +355,7 @@
 	for (int i = 0; i < n; i++) {
 	    final SyntaxTreeNode item =
 		(SyntaxTreeNode)getContents().elementAt(i);
-	    if ((_ignore) && (item instanceof XslAttribute)) continue;
+	    if (_ignore && item instanceof XslAttribute) continue;
 	    item.translate(classGen, methodGen);
 	}
     }
diff --git a/src/org/apache/xalan/xsltc/compiler/util/ErrorMessages.java b/src/org/apache/xalan/xsltc/compiler/util/ErrorMessages.java
index 5c5b243..455349d 100644
--- a/src/org/apache/xalan/xsltc/compiler/util/ErrorMessages.java
+++ b/src/org/apache/xalan/xsltc/compiler/util/ErrorMessages.java
@@ -218,38 +218,54 @@
 
 	// COMPILE_STDIN_ERR
 	"The -i option must be used with the -o option.",
+
 	// COMPILE_USAGE_STR
-	"Usage:\n" + 
-	"   xsltc [-o <output>] [-d <directory>] [-j <jarfile>]\n"+
-	"         [-p <package name>] [-x] [-s] [-u] <stylesheet>|-i\n\n"+
-	"   Where <output> is the name to give the the generated translet.\n"+
-	"         <stylesheet> is one or more stylesheet file names, or if\n"+
-	"         the -u options is specified, one or more stylesheet URLs.\n"+
-	"         <directory> is the output directory.\n"+
-	"         <jarfile> is the name of a JAR-file to put all classes in.\n"+
-	"         <package-name> is used to prefix all class names.\n\n"+
-	"   Notes:\n"+
-	"         The -i options forces the compiler to read from stdin\n"+
-	"         The -o option is ignored if compiling multiple stylesheets\n"+
-	"         The -x option switches on debug messages.\n"+
-	"         The -s option disables calling System.exit.",
+	"SYNOPSIS\n" +
+	"   java org.apache.xalan.xsltc.cmdline.Compile [-o <output>]\n" +
+	"      [-d <directory>] [-j <jarfile>] [-p <package>]\n" +
+	"      [-n] [-x] [-s] [-u] [-v] [-h] { <stylesheet> | -i }\n\n" +
+	"OPTIONS\n" +
+	"   -o <output>    assigns the name <output> to the generated\n" +
+	"                  translet. By default the translet name\n" +
+	"                  is taken from the <stylesheet> name. This option\n"+
+	"                  is ignored if compiling multiple stylesheets.\n" +
+	"   -d <directory> specifies a destination directory for translet\n" +
+	"   -j <jarfile>   packages translet classes into a jar file of the\n"+
+ 	"                  name specified as <jarfile>\n"+
+	"   -p <package>   specifies a package name prefix for all generated\n"+
+	"                  translet classes.\n" +
+	"   -n             disables template inlining to reduce method\n" +
+	"                  length.\n"+
+	"   -x             turns on additional debugging message output\n" +
+	"   -s             disables calling System.exit\n" +
+	"   -u             interprets <stylesheet> arguments as URLs\n" +
+	"   -i             forces compiler to read stylesheet from stdin\n" +
+	"   -v             prints the version of the compiler\n" +
+	"   -h             prints this usage statement\n",  
+ 
 	// TRANSFORM_USAGE_STR
-	"Usage: \n" +
-	"   xslt  [-j <jarfile>] {-u <document_url> | <document>} <class>\n"+
-	"         [<name1>=<value1> ...]\n\n" +
-	"   Where <document> is the xml document to be transformed, or\n" +
-	"         <document_url> is a url for the xml document,\n" +
-	"         <class> is the translet class which is either in\n" +
-	"         user's CLASSPATH or in the <jarfile> specified \n" +
-	"         with the -j option.\n" +
-	"   Notes:\n"+
-	"         The -x option switches on debug messages.\n"+
-	"         The -s option disables calling System.exit.",
+	"SYNOPSIS \n" +
+	"   java org.apache.xalan.xsltc.cmdline.Transform [-j <jarfile>]\n"+
+        "      [-x] [-s] [-n <iterations>] {-u <document_url> | <document>}\n" +  
+        "      <class> [<param1>=<value1> ...]\n\n" +
+        "   uses the translet <class> to transform an XML document \n"+
+	"   specified as <document>. The translet <class> is either in\n"+
+	"   the user's CLASSPATH or in the optionally specified <jarfile>.\n"+
+	"OPTIONS\n" +
+	"   -j <jarfile>    specifies a jarfile from which to load translet\n"+
+	"   -x              turns on additional debugging message output\n" +
+	"   -s              disables calling System.exit\n" +
+	"   -n <iterations> runs the transformation <iterations> times and\n" +
+	"                   displays profiling information\n" +
+	"   -u <document_url> specifies XML input document as a URL\n", 
+
 
 	// STRAY_SORT_ERR
 	"<xsl:sort> can only be used within <xsl:for-each> or <xsl:apply-templates>.",
 	// UNSUPPORTED_ENCODING
-	"Output encoding ''{0}'' is not supported on this JVM."
+	"Output encoding ''{0}'' is not supported on this JVM.",
+	// SYNTAX_ERR
+	"Syntax error in ''{0}''."
     };
 
     private static Vector _keys;
diff --git a/src/org/apache/xalan/xsltc/compiler/util/ErrorMessages_no.java b/src/org/apache/xalan/xsltc/compiler/util/ErrorMessages_no.java
index 648cd7c..2a481a6 100644
--- a/src/org/apache/xalan/xsltc/compiler/util/ErrorMessages_no.java
+++ b/src/org/apache/xalan/xsltc/compiler/util/ErrorMessages_no.java
@@ -249,7 +249,9 @@
 	// STRAY_SORT_ERR
 	"<xsl:sort> kan bare brukes under <xsl:for-each> eller <xsl:apply-templates>.",
 	// UNSUPPORTED_ENCODING
-	"Karaktersett ''{0}'' er ikke st\u00f8ttet av denne JVM."
+	"Karaktersett ''{0}'' er ikke st\u00f8ttet av denne JVM.",
+	// SYNTAX_ERR
+	"Syntax error in ''{0}''."  // TODO: How do you say "syntax error" in norwegian?
     };
 
     public Object handleGetObject(String key) {
diff --git a/src/org/apache/xalan/xsltc/compiler/util/ErrorMsg.java b/src/org/apache/xalan/xsltc/compiler/util/ErrorMsg.java
index 4351a64..4a97c42 100644
--- a/src/org/apache/xalan/xsltc/compiler/util/ErrorMsg.java
+++ b/src/org/apache/xalan/xsltc/compiler/util/ErrorMsg.java
@@ -165,6 +165,7 @@
     // Recently added error messages
     public static final int STRAY_SORT_ERR          = 74;
     public static final int UNSUPPORTED_ENCODING    = 75;
+    public static final int SYNTAX_ERR              = 76;
 
     // All error messages are localized and are stored in resource bundles.
     // This array and the following 4 strings are read from that bundle.
diff --git a/src/org/apache/xalan/xsltc/compiler/util/LongType.java b/src/org/apache/xalan/xsltc/compiler/util/LongType.java
deleted file mode 100644
index cb9435a..0000000
--- a/src/org/apache/xalan/xsltc/compiler/util/LongType.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * @(#)$Id$
- *
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 2001 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Xalan" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 2001, Sun
- * Microsystems., http://www.sun.com.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * @author G. Todd Miller 
- *
- */
-
-package org.apache.xalan.xsltc.compiler.util;
-
-import org.apache.xalan.xsltc.compiler.util.Type;
-import org.apache.bcel.generic.*;
-import org.apache.xalan.xsltc.compiler.Parser;
-import org.apache.xalan.xsltc.compiler.FlowList;
-import org.apache.xalan.xsltc.compiler.Constants;
-
-public final class LongType extends NumberType {
-    protected LongType() {}
-
-    public String toString() {
-	return "long";
-    }
-
-    public boolean identicalTo(Type other) {
-	return this == other;
-    }
-
-    public String toSignature() {
-	return "J";
-    }
-
-    public org.apache.bcel.generic.Type toJCType() {
-	return org.apache.bcel.generic.Type.LONG;
-    }
-
-    /**
-     * @see	org.apache.xalan.xsltc.compiler.util.Type#distanceTo
-     */
-    public int distanceTo(Type type) {
-	if (type == this) {
-	    return 0;
-	}
-	else if (type == Type.Int) {
-	    return 1;
-	}
-	else
-	    return Integer.MAX_VALUE;
-    }
-    
-    /**
-     * Translates an long into an object of internal type <code>type</code>.
-     *
-     * @see	org.apache.xalan.xsltc.compiler.util.Type#translateTo
-     */
-    public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
-			    final Type type) {
-	if (type == Type.Real) {
-	    translateTo(classGen, methodGen, (RealType) type);
-	}
-	else if (type == Type.Int) {
-	    translateTo(classGen, methodGen, (IntType) type);
-	}
-	else if (type == Type.String) {
-	    translateTo(classGen, methodGen, (StringType) type);
-	}
-	else if (type == Type.Boolean) {
-	    translateTo(classGen, methodGen, (BooleanType) type);
-	}
-	else if (type == Type.Reference) {
-	    translateTo(classGen, methodGen, (ReferenceType) type);
-	}
-	else {
-	    ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
-					toString(), type.toString());
-	    classGen.getParser().reportError(Constants.FATAL, err);
-	}
-    }
-
-
-    /**
-     * Expects an long on the stack and pushes a real.
-     *
-     * @see	org.apache.xalan.xsltc.compiler.util.Type#translateTo
-     */
-    public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
-			    RealType type) {
-	methodGen.getInstructionList().append(L2D);
-    }
-
-    /**
-     * Expects an long on the stack and pushes its string value by calling
-     * <code>Long.toString(int i)</code>.
-     *
-     * @see	org.apache.xalan.xsltc.compiler.util.Type#translateTo
-     */
-    public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
-			    StringType type) {
-	final ConstantPoolGen cpg = classGen.getConstantPool();
-	final InstructionList il = methodGen.getInstructionList();
-	il.append(new INVOKESTATIC(cpg.addMethodref(LONG_CLASS,
-						    "toString",
-						    "(J)" + STRING_SIG)));
-    }
-
-    /**
-     * Expects an long on the stack and pushes a 0 if its value is 0 and
-     * a 1 otherwise.
-     *
-     * @see	org.apache.xalan.xsltc.compiler.util.Type#translateTo
-     */
-    public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
-			    BooleanType type) {
-	final InstructionList il = methodGen.getInstructionList();
-	final BranchHandle falsec = il.append(new IFEQ(null));
-	il.append(LCONST_1);
-	final BranchHandle truec = il.append(new GOTO(null));
-	falsec.setTarget(il.append(LCONST_0));
-	truec.setTarget(il.append(NOP));
-    }
-
-    /**
-     * Expects an long on the stack and translates it to a non-synthesized
-     * boolean. It does not push a 0 or a 1 but instead returns branchhandle 
-     * list to be appended to the false list.
-     *
-     * @see	org.apache.xalan.xsltc.compiler.util.Type#translateToDesynthesized
-     */
-    public FlowList translateToDesynthesized(ClassGenerator classGen, 
-					     MethodGenerator methodGen, 
-					     BooleanType type) {
-	final InstructionList il = methodGen.getInstructionList();
-	return new FlowList(il.append(new IFEQ(null)));
-    }
-
-    /**
-     * Expects an long on the stack and pushes a boxed integer.
-     * Boxed integers are represented by an instance of
-     * <code>java.lang.Integer</code>.
-     *
-     * @see	org.apache.xalan.xsltc.compiler.util.Type#translateTo
-     */
-    public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
-			    ReferenceType type) {
-	final ConstantPoolGen cpg = classGen.getConstantPool();
-	final InstructionList il = methodGen.getInstructionList();
-	il.append(new NEW(cpg.addClass(LONG_CLASS)));
-	il.append(DUP_X1);
-	il.append(SWAP);
-	il.append(new INVOKESPECIAL(cpg.addMethodref(LONG_CLASS,
-						     "<init>", "(J)V")));
-    }
-
-    /**
-     * Translates an long into the Java type denoted by <code>clazz</code>. 
-     * Expects an long on the stack and pushes a number of the appropriate
-     * type after coercion.
-     */
-    public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
-			    Class clazz) {
-	final InstructionList il = methodGen.getInstructionList();
-	if (clazz == Character.TYPE) {
-	    il.append(L2I);
-	    il.append(I2C);
-	}
-	else if (clazz == Byte.TYPE) {
-	    il.append(L2I);
-	    il.append(I2B);
-	}
-	else if (clazz == Short.TYPE) {
-	    il.append(L2I);
-	    il.append(I2S);
-	}
-	else if (clazz == Integer.TYPE) {
-	    il.append(L2I);
-	}
-	else if (clazz == Long.TYPE) {
-	    il.append(NOP);
-	}
-	else if (clazz == Float.TYPE) {
-	    il.append(L2F);
-	}
-	else if (clazz == Double.TYPE) {
-	    il.append(L2D);
-	}
-	else {
-	    ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
-					toString(), clazz.getName());
-	    classGen.getParser().reportError(Constants.FATAL, err);
-	}
-    }
-
-    /**
-     * Translates an object of this type to its boxed representation.
-     */ 
-    public void translateBox(ClassGenerator classGen,
-			     MethodGenerator methodGen) {
-	translateTo(classGen, methodGen, Type.Reference);
-    }
-
-    /**
-     * Translates an object of this type to its unboxed representation.
-     */ 
-    public void translateUnBox(ClassGenerator classGen,
-			       MethodGenerator methodGen) {
-	final ConstantPoolGen cpg = classGen.getConstantPool();
-	final InstructionList il = methodGen.getInstructionList();
-	il.append(new CHECKCAST(cpg.addClass(LONG_CLASS)));
-	final int index = cpg.addMethodref(LONG_CLASS,
-					   LONG_VALUE, 
-					   LONG_VALUE_SIG);
-	il.append(new INVOKEVIRTUAL(index));
-    }
-
-    public Instruction ADD() {
-	return InstructionConstants.LADD;
-    }
-
-    public Instruction SUB() {
-	return InstructionConstants.LSUB;
-    }
-
-    public Instruction MUL() {
-	return InstructionConstants.LMUL;
-    }
-
-    public Instruction DIV() {
-	return InstructionConstants.LDIV;
-    }
-
-    public Instruction REM() {
-	return InstructionConstants.LREM;
-    }
-
-    public Instruction NEG() {
-	return InstructionConstants.LNEG;
-    }
-
-    public Instruction LOAD(int slot) {
-	return new LLOAD(slot);
-    }
-	
-    public Instruction STORE(int slot) {
-	return new LSTORE(slot);
-    }
-
-    public BranchInstruction GT(boolean tozero) {
-	// GTM:TBD
-	return tozero ? (BranchInstruction) new IFGT(null) : 
-	    (BranchInstruction) new IF_ICMPGT(null);
-    }
-
-    public BranchInstruction GE(boolean tozero) {
-	// GTM:TBD
-	return tozero ? (BranchInstruction) new IFGE(null) : 
-	    (BranchInstruction) new IF_ICMPGE(null);
-    }
-
-    public BranchInstruction LT(boolean tozero) {
-	// GTM:TBD
-	return tozero ? (BranchInstruction) new IFLT(null) : 
-	    (BranchInstruction) new IF_ICMPLT(null);
-    }
-
-    public BranchInstruction LE(boolean tozero) {
-	// GTM:TBD
-	return tozero ? (BranchInstruction) new IFLE(null) : 
-	    (BranchInstruction) new IF_ICMPLE(null);
-    }
-}
diff --git a/src/org/apache/xalan/xsltc/compiler/util/MethodGenerator.java b/src/org/apache/xalan/xsltc/compiler/util/MethodGenerator.java
index a0e5fc8..45b42a0 100644
--- a/src/org/apache/xalan/xsltc/compiler/util/MethodGenerator.java
+++ b/src/org/apache/xalan/xsltc/compiler/util/MethodGenerator.java
@@ -103,6 +103,7 @@
     private final Instruction _nextNode;
 
     private SlotAllocator _slotAllocator;
+    private boolean _allocatorInit = false;
     
     public MethodGenerator(int access_flags, Type return_type,
 			   Type[] arg_types, String[] arg_names,
@@ -173,17 +174,26 @@
 	
 	_slotAllocator = new SlotAllocator();
 	_slotAllocator.initialize(getLocalVariables());
+	_allocatorInit = true;
     }
 
+    /**
+     * Allocates a local variable. If the slot allocator has already been
+     * initialized, then call addLocalVariable2() so that the new variable
+     * is known to the allocator. Failing to do this may cause the allocator 
+     * to return a slot that is already in use.
+     */
     public LocalVariableGen addLocalVariable(String name, Type type,
 					     InstructionHandle start,
-					     InstructionHandle end) {
-	
-	return super.addLocalVariable(name, type, start, end);
+					     InstructionHandle end) 
+    {
+	return (_allocatorInit) ? addLocalVariable2(name, type, start) 
+	    : super.addLocalVariable(name, type, start, end);
     }
     
     public LocalVariableGen addLocalVariable2(String name, Type type,
-					      InstructionHandle start) {
+					      InstructionHandle start) 
+    {
 	return super.addLocalVariable(name, type,
 				      _slotAllocator.allocateSlot(type),
 				      start, null);
diff --git a/src/org/apache/xalan/xsltc/compiler/util/ReferenceType.java b/src/org/apache/xalan/xsltc/compiler/util/ReferenceType.java
index 8d56714..c7ac287 100644
--- a/src/org/apache/xalan/xsltc/compiler/util/ReferenceType.java
+++ b/src/org/apache/xalan/xsltc/compiler/util/ReferenceType.java
@@ -113,6 +113,9 @@
 	else if (type == Type.Node) {
 	    translateTo(classGen, methodGen, (NodeType) type);
 	}
+	else if (type == Type.ResultTree) {
+	    translateTo(classGen, methodGen, (ResultTreeType) type);
+	}
 	else {
 	    ErrorMsg err = new ErrorMsg(ErrorMsg.INTERNAL_ERR, type.toString());
 	    classGen.getParser().reportError(Constants.FATAL, err);
@@ -211,6 +214,52 @@
     }
 
     /**
+     * Casts a reference into a ResultTree.
+     *
+     * @see	org.apache.xalan.xsltc.compiler.util.Type#translateTo
+     */
+    public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
+			    ResultTreeType type) {
+	final ConstantPoolGen cpg = classGen.getConstantPool();
+	final InstructionList il = methodGen.getInstructionList();
+	int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToResultTree", 
+				     "(" + OBJECT_SIG + ")" + DOM_INTF_SIG);
+	il.append(new INVOKESTATIC(index));
+    }
+
+    /**
+     * Translates a reference into the Java type denoted by <code>clazz</code>. 
+     * Only conversion allowed is to java.lang.Object.
+     */
+    public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
+			    Class clazz) {
+	if (clazz.getName().equals("java.lang.Object")) {
+	    methodGen.getInstructionList().append(NOP);	
+	}
+	else {
+	    ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
+					toString(), clazz.getName());
+	    classGen.getParser().reportError(Constants.FATAL, err);
+	}
+    }
+
+    /**
+     * Translates an external Java type into a reference. Only conversion
+     * allowed is from java.lang.Object.
+     */
+    public void translateFrom(ClassGenerator classGen, MethodGenerator methodGen, 
+			      Class clazz) {
+	if (clazz.getName().equals("java.lang.Object")) {
+	    methodGen.getInstructionList().append(NOP);	
+	}
+	else {
+	    ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
+				toString(), clazz.getName());
+	    classGen.getParser().reportError(Constants.FATAL, err);
+        } 
+    }
+
+    /**
      * Expects a reference on the stack and translates it to a non-synthesized
      * boolean. It does not push a 0 or a 1 but instead returns branchhandle 
      * list to be appended to the false list.
diff --git a/src/org/apache/xalan/xsltc/compiler/util/Type.java b/src/org/apache/xalan/xsltc/compiler/util/Type.java
index 5413d96..689b65f 100644
--- a/src/org/apache/xalan/xsltc/compiler/util/Type.java
+++ b/src/org/apache/xalan/xsltc/compiler/util/Type.java
@@ -72,7 +72,6 @@
 
 public abstract class Type implements Constants {
     public static final Type Int        = new IntType();
-    public static final Type Lng        = new LongType(); //GTM,bug 3592
     public static final Type Real       = new RealType();
     public static final Type Boolean    = new BooleanType();
     public static final Type NodeSet    = new NodeSetType();
diff --git a/src/org/apache/xalan/xsltc/compiler/util/Util.java b/src/org/apache/xalan/xsltc/compiler/util/Util.java
index 2082fe1..022bac5 100644
--- a/src/org/apache/xalan/xsltc/compiler/util/Util.java
+++ b/src/org/apache/xalan/xsltc/compiler/util/Util.java
@@ -66,6 +66,7 @@
 import org.apache.bcel.generic.Type;
 import org.apache.bcel.generic.*;
 import org.apache.xalan.xsltc.compiler.Parser;
+import org.apache.xalan.xsltc.compiler.Constants;
 
 public final class Util {
     static public char filesep;
@@ -108,17 +109,20 @@
      * Replace all illegal Java chars by '_'.
      */
     public static String toJavaName(String name) {
-	final StringBuffer result = new StringBuffer();
+	if (name.length() > 0) {
+	    final StringBuffer result = new StringBuffer();
 
-	char ch = name.charAt(0);
-	result.append(Character.isJavaIdentifierStart(ch) ? ch : '_');
+	    char ch = name.charAt(0);
+	    result.append(Character.isJavaIdentifierStart(ch) ? ch : '_');
 
-	final int n = name.length();
-	for (int i = 1; i < n; i++) {
-	    ch = name.charAt(i);
-	    result.append(Character.isJavaIdentifierPart(ch)  ? ch : '_');
+	    final int n = name.length();
+	    for (int i = 1; i < n; i++) {
+		ch = name.charAt(i);
+		result.append(Character.isJavaIdentifierPart(ch)  ? ch : '_');
+	    }
+	    return result.toString();
 	}
-	return result.toString();
+	return name;
     }
 
     public static Type getJCRefType(String signature) {
@@ -130,15 +134,11 @@
     }
 
     public static void println(String s) {
-	if (false) {
-	    System.out.println(s);
-	}
+	System.out.println(s);
     }
 
     public static void println(char ch) {
-	if (false) {
-	    System.out.println(ch);
-	}
+	System.out.println(ch);
     }
 
     public static void TRACE1() {
@@ -156,35 +156,46 @@
     /**
      * Replace a certain character in a string with a new substring.
      */
-    public 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;
+    public static String replace(String base, char ch, String str) {
+	return (base.indexOf(ch) < 0) ? base : 
+	    replace(base, String.valueOf(ch), new String[] { str });
+    }
+
+    public static String replace(String base, String delim, String[] str) {
+	final int len = base.length();
+	final StringBuffer result = new StringBuffer();
+
+	for (int i = 0; i < len; i++) {
+	    final char ch = base.charAt(i);
+	    final int k = delim.indexOf(ch);
+
+	    if (k >= 0) {
+		result.append(str[k]);
 	    }
 	    else {
-		final String before = base.substring(0, pos);
-		final String after = base.substring(pos+1);
-		base = before + str + after;
+		result.append(ch);
 	    }
 	}
-	return base;
+	return result.toString();
     }
 
     /**
-     * Replace occurances of '.' with '$dot$' and '-' with '$dash$'
+     * Replace occurances of '.', '-', '/' and ':'
      */
     public static String escape(String input) {
-	input = replace(input, '.', "$dot$");
-	input = replace(input, '-', "$dash$");
-	return input;
+	return replace(input, ".-/:", 
+	    new String[] { "$dot$", "$dash$", "$slash$", "$colon$" });
     }
 
+    public static String getLocalName(String qname) {
+	final int index = qname.lastIndexOf(":");
+	return (index > 0) ? qname.substring(index + 1) : qname;
+    }
+
+    public static String getPrefix(String qname) {
+	final int index = qname.lastIndexOf(":");
+	return (index > 0) ? qname.substring(0, index) : 
+	    Constants.EMPTYSTRING;
+    }
 }
 
diff --git a/src/org/apache/xalan/xsltc/compiler/xpath.cup b/src/org/apache/xalan/xsltc/compiler/xpath.cup
index 31a8a68..adce4e3 100644
--- a/src/org/apache/xalan/xsltc/compiler/xpath.cup
+++ b/src/org/apache/xalan/xsltc/compiler/xpath.cup
@@ -92,6 +92,11 @@
     private XSLTC  _xsltc;
 
     /**
+     * String representation of the expression being parsed.
+     */
+    private String _expression;
+
+    /**
      * Line number where this expression/pattern was declared.
      */
     private int _lineNumber = 0;
@@ -115,10 +120,18 @@
           return _parser.getQName(name);
     }    
 
+    public QName getQNameIgnoreDefaultNs(String name) {
+          return _parser.getQNameIgnoreDefaultNs(name);
+    }    
+
     public void setMultiDocument(boolean flag) {
           _xsltc.setMultiDocument(flag);
     }
 
+    public void setCallsNodeset(boolean flag) {
+          _xsltc.setCallsNodeset(flag);
+    }
+
     public int findNodeType(int axis, Object test) {
 
 	if (test == null) {  // *
@@ -174,8 +187,9 @@
      *                   compiled in a separate module.
      * 
      */
-    public Symbol parse(int lineNumber) throws Exception {
+    public Symbol parse(String expression, int lineNumber) throws Exception {
         try {
+	    _expression = expression;
 	    _lineNumber = lineNumber;
 	    return super.parse();
         }
@@ -206,12 +220,29 @@
     } 
            
     public void report_error(String message, Object info) {
-        // empty
+	final ErrorMsg err = new ErrorMsg(ErrorMsg.SYNTAX_ERR, _lineNumber, 
+	    _expression);
+	_parser.reportError(Constants.FATAL, err);
     }
 
     public void report_fatal_error(String message, Object info) {
         // empty
     }
+    
+    public RelativeLocationPath insertStep(Step step, RelativeLocationPath rlp) {
+	if (rlp instanceof Step) {
+	    return new ParentLocationPath(step, (Step) rlp);
+	}
+	else if (rlp instanceof ParentLocationPath) {
+	    final ParentLocationPath plp = (ParentLocationPath) rlp;
+	    final RelativeLocationPath newrlp = insertStep(step, plp.getPath());
+	    return new ParentLocationPath(newrlp, plp.getStep());
+	}
+	else {
+	    addError(new ErrorMsg(ErrorMsg.INTERNAL_ERR, "XPathParser.insertStep"));
+	    return rlp;
+	}
+    }
 :}
 
 terminal SLASH, DOT, LBRACK, RBRACK, VBAR, LPAREN, RPAREN, STAR, COMMA;
@@ -290,12 +321,6 @@
             | SLASH RelativePathPattern:rpp
             {: RESULT = new AbsolutePathPattern(rpp); :}
 
-            | ProcessingInstructionPattern:pip
-            {: RESULT = pip; :}
-
-	    | ProcessingInstructionPattern:pip Predicates:pp
-            {: RESULT = (ProcessingInstructionPattern)pip.setPredicates(pp); :}
-
             | IdKeyPattern:ikp
             {: RESULT = ikp; :}
 
@@ -341,6 +366,12 @@
                                         pp);
             :}
 
+            | ProcessingInstructionPattern:pip
+            {: RESULT = pip; :}
+
+	    | ProcessingInstructionPattern:pip Predicates:pp
+            {: RESULT = (ProcessingInstructionPattern)pip.setPredicates(pp); :}
+
             | ChildOrAttributeAxisSpecifier:axis NodeTestPattern:nt
             {: RESULT=new StepPattern(axis.intValue(),
                                       parser.findNodeType(axis.intValue(), nt),
@@ -352,7 +383,19 @@
             {: RESULT = new StepPattern(axis.intValue(),
                                         parser.findNodeType(axis.intValue(),nt),
                                         pp);
-            :};
+            :}
+
+            | ChildOrAttributeAxisSpecifier:axis ProcessingInstructionPattern:pip
+            {: 
+	       RESULT = pip; 	// TODO: report error if axis is attribute
+	    :}
+
+	    | ChildOrAttributeAxisSpecifier:axis ProcessingInstructionPattern:pip 
+		Predicates:pp
+            {: 
+	       // TODO: report error if axis is attribute	
+	       RESULT = (ProcessingInstructionPattern)pip.setPredicates(pp); 
+	    :};
 
 NodeTestPattern ::= NameTestPattern:nt
             {: RESULT = nt; :}
@@ -582,30 +625,13 @@
 
 AbbreviatedAbsoluteLocationPath ::= DSLASH RelativeLocationPath:rlp
         {:
+	    final Step step = new Step(Axis.DESCENDANTORSELF, -1, null);
 
-	AbsoluteLocationPath alp = null;
-
-        Step left = new Step(Axis.DESCENDANTORSELF, -1, null);
-
-	if (rlp instanceof ParentLocationPath) {
-	    ParentLocationPath plp = new ParentLocationPath(left, rlp);
-	    alp = new AbsoluteLocationPath(plp);
-	}
-	else if (rlp instanceof Step) {
-            Step right = (Step)rlp;
-            alp = new AbsoluteLocationPath(new ParentLocationPath(left, right));
-	}
-	else {
-            // Don't think we'll ever get here...
-            Step right = new Step(Axis.CHILD, NodeTest.ELEMENT, null);
-	    alp = new AbsoluteLocationPath(new ParentLocationPath(left, right));
-        }
-
-	RESULT = new FilteredAbsoluteLocationPath(alp);
+	    RESULT = new FilteredAbsoluteLocationPath(
+			new AbsoluteLocationPath(parser.insertStep(step, 
+				(RelativeLocationPath) rlp)));
 	:};
 
-
-
 Step ::= NodeTest:ntest
         {:
             if (ntest instanceof Step) {
@@ -714,25 +740,25 @@
 	/*
 	* If the string appears to have the syntax of a QName, store 
 	* namespace info in the literal expression. This is used for
-	* element-available and function-available functions.
+	* element-available and function-available functions, among
+	* others. Also, the default namespace must be ignored.
 	*/
+	String namespace = null;
 	final int index = string.lastIndexOf(':');
-	final String prefix = index >= 0
-                                     ? string.substring(0, index)
-                                     : Constants.EMPTYSTRING;
-	String namespace = parser._symbolTable.lookupNamespace(prefix);
-	RESULT = namespace == null
-                         ? new LiteralExpr(string)
-                         : new LiteralExpr(string, namespace); 
+
+	if (index > 0) {
+	    final String prefix = string.substring(0, index);
+	    namespace = parser._symbolTable.lookupNamespace(prefix);
+	}
+	RESULT = (namespace == null) ? new LiteralExpr(string)
+		     : new LiteralExpr(string, namespace); 
 	:}
 
         | INT:num
         {: 
-	   // bug fix 3592, num comes in as a Long rather than an Integer
-	   //               see xpath.lex, {Digit}+ rule. 
 	   long value = num.longValue();
-	   if ((value < Integer.MIN_VALUE) || (value > Integer.MAX_VALUE)) {
-		RESULT = new LongExpr(num.longValue());
+	   if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
+		RESULT = new RealExpr(value);
 	   }
 	   else {
                if (num.doubleValue() == -0)
@@ -741,7 +767,7 @@
                    RESULT = new IntExpr(num.intValue());
                else if (num.doubleValue() == 0.0)
                    RESULT = new RealExpr(num.doubleValue());
-               else
+               else 
                    RESULT = new IntExpr(num.intValue());
 	   }
         :}
@@ -773,49 +799,48 @@
             if (node == null) {
                 RESULT = new UnresolvedRef(varName);
             }
-
         :};
 
 FunctionCall ::= FunctionName:fname LPAREN RPAREN
         {: 
 
-          if (fname == parser.getQName("current")) {
+          if (fname == parser.getQNameIgnoreDefaultNs("current")) {
             RESULT = new CurrentCall(fname);
 	  }
-          else if (fname == parser.getQName("number")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("number")) {
             RESULT = new NumberCall(fname, parser.EmptyArgs);
 	  }
-          else if (fname == parser.getQName("string")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("string")) {
             RESULT = new StringCall(fname, parser.EmptyArgs);
 	  }
-          else if (fname == parser.getQName("concat")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("concat")) {
             RESULT = new ConcatCall(fname, parser.EmptyArgs);
 	  }
-          else if (fname == parser.getQName("true")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("true")) {
             RESULT = new BooleanExpr(true);
 	  }
-          else if (fname == parser.getQName("false")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("false")) {
             RESULT = new BooleanExpr(false);
 	  }
-          else if (fname == parser.getQName("name")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("name")) {
             RESULT = new NameCall(fname);
 	  }
-          else if (fname == parser.getQName("generate-id")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("generate-id")) {
             RESULT = new GenerateIdCall(fname, parser.EmptyArgs);
 	  }
-          else if (fname == parser.getQName("string-length")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("string-length")) {
             RESULT = new StringLengthCall(fname, parser.EmptyArgs);
 	  }
-          else if (fname == parser.getQName("position")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("position")) {
             RESULT = new PositionCall(fname);
 	  }
-          else if (fname == parser.getQName("last")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("last")) {
             RESULT = new LastCall(fname);
 	  }
-          else if (fname == parser.getQName("local-name")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("local-name")) {
             RESULT = new LocalNameCall(fname);
 	  }
-          else if (fname == parser.getQName("namespace-uri")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("namespace-uri")) {
             RESULT = new NamespaceUriCall(fname);
 	  }
           else {
@@ -825,76 +850,81 @@
 
         | FunctionName:fname LPAREN NonemptyArgumentList:argl RPAREN
         {:
-          if (fname == parser.getQName("concat")) {
+          if (fname == parser.getQNameIgnoreDefaultNs("concat")) {
             RESULT = new ConcatCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("number")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("number")) {
             RESULT = new NumberCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("document")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("document")) {
 	    parser.setMultiDocument(true);
             RESULT = new DocumentCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("string")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("string")) {
             RESULT = new StringCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("boolean")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("boolean")) {
             RESULT = new BooleanCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("name")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("name")) {
             RESULT = new NameCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("generate-id")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("generate-id")) {
             RESULT = new GenerateIdCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("not")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("not")) {
             RESULT = new NotCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("format-number")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("format-number")) {
             RESULT = new FormatNumberCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("unparsed-entity-uri")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("unparsed-entity-uri")) {
             RESULT = new UnparsedEntityUriCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("key")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("key")) {
             RESULT = new KeyCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("id")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("id")) {
             RESULT = new KeyCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("ceiling")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("ceiling")) {
             RESULT = new CeilingCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("round")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("round")) {
             RESULT = new RoundCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("floor")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("floor")) {
             RESULT = new FloorCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("contains")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("contains")) {
             RESULT = new ContainsCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("string-length")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("string-length")) {
             RESULT = new StringLengthCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("starts-with")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("starts-with")) {
             RESULT = new StartsWithCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("function-available")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("function-available")) {
             RESULT = new FunctionAvailableCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("element-available")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("element-available")) {
             RESULT = new ElementAvailableCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("local-name")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("local-name")) {
             RESULT = new LocalNameCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("lang")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("lang")) {
             RESULT = new LangCall(fname, argl);
 	  }
-          else if (fname == parser.getQName("namespace-uri")) {
+          else if (fname == parser.getQNameIgnoreDefaultNs("namespace-uri")) {
             RESULT = new NamespaceUriCall(fname, argl);
 	  }
+	  // Special case for extension function nodeset()
+          else if (fname.getLocalPart().equals("nodeset")) {
+	    parser.setCallsNodeset(true);  // implies MultiDOM
+            RESULT = new FunctionCall(fname, argl);
+	  }
           else {
             RESULT = new FunctionCall(fname, argl);
 	  }
@@ -911,18 +941,24 @@
         {: argl.insertElementAt(arg, 0); RESULT = argl; :};
 
 FunctionName ::= QName:fname
-        {:
-            fname.clearDefaultNamespace();
-            RESULT = fname; 
-        :};
+        {: 
+	    final String prefix = fname.getPrefix();
+	    if (prefix == null || prefix.equals(Constants.EMPTYSTRING)) {
+		fname = parser.getQNameIgnoreDefaultNs(fname.getLocalPart());
+	    }
+	    RESULT = fname; 
+	:};
 
 VariableName ::= QName:vname
-        {:
-            vname.clearDefaultNamespace();
-            RESULT = vname; 
-        :};
+        {: 
+	    final String prefix = vname.getPrefix();
+	    if (prefix == null || prefix.equals(Constants.EMPTYSTRING)) {
+		vname = parser.getQNameIgnoreDefaultNs(vname.getLocalPart());
+	    }
+	    RESULT = vname; 
+	:};
 
-Argument ::=    Expr:ex
+Argument ::= Expr:ex
         {: RESULT = ex; :};
 
 NodeTest ::= NameTest:nt
@@ -939,14 +975,13 @@
 
         | PIPARAM LPAREN Literal:l RPAREN
         {:
-           QName name = parser.getQName("name");
+           QName name = parser.getQNameIgnoreDefaultNs("name");
            Expression exp = new EqualityExpr(Operators.EQ,
                                              new NameCall(name),
                                              new LiteralExpr(l));
            Vector predicates = new Vector();
            predicates.addElement(new Predicate(exp));
            RESULT = new Step(Axis.CHILD, NodeTest.PI, predicates);
-	           //RESULT = new Integer(NodeTest.PI);
         :}
 
         | PI
@@ -961,54 +996,54 @@
 QName ::= QNAME:qname
         {: RESULT = parser.getQName(qname); :}
 
-        | DIV
-        {: RESULT = parser.getQName("div"); :}
+	| DIV
+        {: RESULT = parser.getQNameIgnoreDefaultNs("div"); :}
 
         | MOD
-        {: RESULT = parser.getQName("mod"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("mod"); :}
 
         | KEY
-        {: RESULT = parser.getQName("key"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("key"); :}
 
         | ANCESTOR
-        {: RESULT = parser.getQName("child"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("child"); :}
 
         | ANCESTORORSELF
-        {: RESULT = parser.getQName("ancestor-or-self"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("ancestor-or-self"); :}
 
         | ATTRIBUTE
-        {: RESULT = parser.getQName("attribute"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("attribute"); :}
 
         | CHILD
-        {: RESULT = parser.getQName("child"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("child"); :}
 
         | DESCENDANT
-        {: RESULT = parser.getQName("decendant"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("decendant"); :}
 
         | DESCENDANTORSELF
-        {: RESULT = parser.getQName("decendant-or-self"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("decendant-or-self"); :}
 
         | FOLLOWING
-        {: RESULT = parser.getQName("following"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("following"); :}
 
         | FOLLOWINGSIBLING
-        {: RESULT = parser.getQName("following-sibling"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("following-sibling"); :}
 
         | NAMESPACE
-        {: RESULT = parser.getQName("namespace"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("namespace"); :}
 
         | PARENT
-        {: RESULT = parser.getQName("parent"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("parent"); :}
 
         | PRECEDING
-        {: RESULT = parser.getQName("preceding"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("preceding"); :}
 
         | PRECEDINGSIBLING
-        {: RESULT = parser.getQName("preceding-sibling"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("preceding-sibling"); :}
 
         | SELF
-        {: RESULT = parser.getQName("self"); :}
+        {: RESULT = parser.getQNameIgnoreDefaultNs("self"); :}
 
         | ID
-        {: RESULT = parser.getQName("id"); :};
+        {: RESULT = parser.getQNameIgnoreDefaultNs("id"); :};
 
diff --git a/src/org/apache/xalan/xsltc/compiler/xpath.lex b/src/org/apache/xalan/xsltc/compiler/xpath.lex
index a82c95a..2f361a8 100644
--- a/src/org/apache/xalan/xsltc/compiler/xpath.lex
+++ b/src/org/apache/xalan/xsltc/compiler/xpath.lex
@@ -79,10 +79,22 @@
 Exception
 %yylexthrow}
 
-Digit=[0-9]
-Letter=[A-Za-z]
-NCNameChar=({Letter}|{Digit}|"."|"-"|"_")
+Letter={BaseChar}|{Ideographic}
+
+BaseChar=[\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u0131\u0134-\u013E\u0141-\u0148\u014A-\u017E\u0180-\u01C3\u01CD-\u01F0\u01F4-\u01F5\u01FA-\u0217\u0250-\u02A8\u02BB-\u02C1\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03D6\u03DA\u03DC\u03DE\u03E0\u03E2-\u03F3\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E-\u0481\u0490-\u04C4\u04C7-\u04C8\u04CB-\u04CC\u04D0-\u04EB\u04EE-\u04F5\u04F8-\u04F9\u0531-\u0556\u0559\u0561-\u0586\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0641-\u064A\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D3\u06D5\u06E5-\u06E6\u0905-\u0939\u093D\u0958-\u0961\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8B\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AE0\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B36-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CDE\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60-\u0D61\u0E01-\u0E2E\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EAE\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0F40-\u0F47\u0F49-\u0F69\u10A0-\u10C5\u10D0-\u10F6\u1100\u1102-\u1103\u1105-\u1107\u1109\u110B-\u110C\u110E-\u1112\u113C\u113E\u1140\u114C\u114E\u1150\u1154-\u1155\u1159\u115F-\u1161\u1163\u1165\u1167\u1169\u116D-\u116E\u1172-\u1173\u1175\u119E\u11A8\u11AB\u11AE-\u11AF\u11B7-\u11B8\u11BA\u11BC-\u11C2\u11EB\u11F0\u11F9\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2126\u212A-\u212B\u212E\u2180-\u2182\u3041-\u3094\u30A1-\u30FA\u3105-\u312C\uAC00-\uD7A3]
+
+Ideographic=[\u4E00-\u9FA5\u3007\u3021-\u3029] 
+
+CombiningChar=[\u0300-\u0345\u0360-\u0361\u0483-\u0486\u0591-\u05A1\u05A3-\u05B9\u05BB-\u05BD\u05BF\u05C1-\u05C2\u05C4\u064B-\u0652\u0670\u06D6-\u06DC\u06DD-\u06DF\u06E0-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0901-\u0903\u093C\u093E-\u094C\u094D\u0951-\u0954\u0962-\u0963\u0981-\u0983\u09BC\u09BE\u09BF\u09C0-\u09C4\u09C7-\u09C8\u09CB-\u09CD\u09D7\u09E2-\u09E3\u0A02\u0A3C\u0A3E\u0A3F\u0A40-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A70-\u0A71\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0B01-\u0B03\u0B3C\u0B3E-\u0B43\u0B47-\u0B48\u0B4B-\u0B4D\u0B56-\u0B57\u0B82-\u0B83\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C01-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C82-\u0C83\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5-\u0CD6\u0D02-\u0D03\u0D3E-\u0D43\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86-\u0F8B\u0F90-\u0F95\u0F97\u0F99-\u0FAD\u0FB1-\u0FB7\u0FB9\u20D0-\u20DC\u20E1\u302A-\u302F\u3099\u309A] 
+
+Digit=[\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE7-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29] 
+
+Extender=[\u00B7\u02D0\u02D1\u0387\u0640\u0E46\u0EC6\u3005\u3031-\u3035\u309D-\u309E\u30FC-\u30FE] 
+
 NCName=({Letter}|"_")({NCNameChar})*
+
+NCNameChar={Letter}|{Digit}|"."|"-"|"_"|{CombiningChar}|{Extender}
+
 %%
 
 "*"                      { return new Symbol(sym.STAR); }
diff --git a/src/org/apache/xalan/xsltc/dom/BitArray.java b/src/org/apache/xalan/xsltc/dom/BitArray.java
index 9e33047..16894a4 100644
--- a/src/org/apache/xalan/xsltc/dom/BitArray.java
+++ b/src/org/apache/xalan/xsltc/dom/BitArray.java
@@ -93,6 +93,10 @@
     /**
      * Constructor. Defines the initial size of the bit array (in bits).
      */
+    public BitArray() {
+	this(32);
+    }
+
     public BitArray(int size) {
 	if (size < 32) size = 32;
 	_bitSize = size;
diff --git a/src/org/apache/xalan/xsltc/dom/CurrentNodeListIterator.java b/src/org/apache/xalan/xsltc/dom/CurrentNodeListIterator.java
index dfb9f3d..5e26eec 100644
--- a/src/org/apache/xalan/xsltc/dom/CurrentNodeListIterator.java
+++ b/src/org/apache/xalan/xsltc/dom/CurrentNodeListIterator.java
@@ -70,28 +70,31 @@
 import org.apache.xalan.xsltc.runtime.BasisLibrary;
 
 public final class CurrentNodeListIterator extends NodeIteratorBase {
-    private NodeIterator _source;
+
     private boolean _docOrder;
+    private NodeIterator _source;
     private final CurrentNodeListFilter _filter;
     private IntegerArray _nodes = new IntegerArray();
 	
     private int _current;	// index in _nodes of the next node to try
+    private int _last = -1;		
 	
-    private AbstractTranslet _translet;
     private final int _currentNode;
-    private int _last;		
+    private AbstractTranslet _translet;
 
     public CurrentNodeListIterator(NodeIterator source, 
 				   CurrentNodeListFilter filter,
 				   int currentNode,
-				   AbstractTranslet translet) {
+				   AbstractTranslet translet) 
+    {
 	this(source, !source.isReverse(), filter, currentNode, translet);
     }
 
     public CurrentNodeListIterator(NodeIterator source, boolean docOrder,
 				   CurrentNodeListFilter filter,
 				   int currentNode,
-				   AbstractTranslet translet) {
+				   AbstractTranslet translet) 
+    {
 	_source = source;
 	_filter = filter;
 	_translet = translet;
@@ -99,11 +102,6 @@
 	_currentNode = currentNode;
     }
 
-    public NodeIterator forceNaturalOrder() {
-	_docOrder = true;
-	return this;
-    }
-
     public void setRestartable(boolean isRestartable) {
 	_isRestartable = isRestartable;
 	_source.setRestartable(isRestartable);
@@ -134,14 +132,13 @@
     }
 
     public int next() {
-	final boolean docOrder = _docOrder;
 	final int last = _nodes.cardinality();
 	final int currentNode = _currentNode;
+	final AbstractTranslet translet = _translet;
 
 	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);
 	    }
@@ -149,29 +146,12 @@
 	return END;
     }
 
-    private int computePositionOfLast() {
-	int lastPosition = 0;
-	final boolean docOrder = _docOrder;
-        final int last = _nodes.cardinality();
-        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)) {
-                lastPosition++;
-            }
-        }
-	return lastPosition;
-    }
-
     public NodeIterator setStartNode(int node) {
 	NodeIterator retval = this;
 	
 	if (_isRestartable) {
-	    // iterator is not a clone
 	    _source.setStartNode(_startNode = node);
-	    // including ROOT
+
 	    _nodes.clear();
 	    while ((node = _source.next()) != END) {
 		_nodes.add(node);
@@ -179,13 +159,14 @@
 	    _current = 0;
 	    retval = resetPosition();
 	}
-	// compute position of _last
-  	_last = computePositionOfLast();	
 	return retval;
     }
 	
     public int getLast() {
-	return ( _last == -1 ) ? computePositionOfLast() : _last;
+	if (_last == -1) {
+	    _last = computePositionOfLast();
+	}
+	return _last;
     }
 
     public void setMark() {
@@ -197,4 +178,20 @@
 	_source.gotoMark();
 	_current = _markedNode;
     }
+
+    private int computePositionOfLast() {
+        final int last = _nodes.cardinality();
+        final int currNode = _currentNode;
+	final AbstractTranslet translet = _translet;
+
+	int lastPosition = 0;
+	for (int index = _current; index < last; ) {
+            int nodeIndex = _nodes.at(index++); 	// note increment
+            if (_filter.test(nodeIndex, index, last, currNode, translet, this)) {
+                lastPosition++;
+            }
+        }
+	return lastPosition;
+    }
 }
+
diff --git a/src/org/apache/xalan/xsltc/dom/DOMAdapter.java b/src/org/apache/xalan/xsltc/dom/DOMAdapter.java
index 4d75669..450f844 100644
--- a/src/org/apache/xalan/xsltc/dom/DOMAdapter.java
+++ b/src/org/apache/xalan/xsltc/dom/DOMAdapter.java
@@ -73,6 +73,7 @@
 import org.apache.xalan.xsltc.TransletException;
 
 public final class DOMAdapter implements DOM {
+
     private final DOMImpl _domImpl;
     private short[] _mapping;
     private short[] _reverse;
@@ -80,10 +81,13 @@
     private short[] _NSreverse;
 
     private StripFilter _filter = null;
+
+    private int _multiDOMMask;
     
     public DOMAdapter(DOMImpl dom,
 		      String[] namesArray,
-		      String[] namespaceArray) {
+		      String[] namespaceArray) 
+    {
 	_domImpl = dom;
 	_mapping = dom.getMapping(namesArray);
 	_reverse = dom.getReverseMapping(namesArray);
@@ -98,7 +102,9 @@
 	_NSreverse = _domImpl.getReverseNamespaceMapping(namespaces);
     }
 
-    /** returns singleton iterator containg the document root */
+    /** 
+      * Returns singleton iterator containg the document root 
+      */
     public NodeIterator getIterator() {
 	return _domImpl.getIterator();
     }
@@ -111,14 +117,22 @@
 	return _domImpl.getTreeString();
     }
     
+    public int getMultiDOMMask() {
+	return _multiDOMMask;
+    }
+
+    public void setMultiDOMMask(int mask) {
+	_multiDOMMask = mask;
+    }
+
     public NodeIterator getChildren(final int node) {
 	NodeIterator iterator = _domImpl.getChildren(node);
 	if (_filter == null) {
-	    return(iterator.setStartNode(node));
+	    return iterator.setStartNode(node);
 	}
 	else {
-	    iterator = _domImpl.strippingIterator(iterator,_mapping,_filter);
-	    return(iterator.setStartNode(node));
+	    iterator = _domImpl.strippingIterator(iterator, _mapping, _filter);
+	    return iterator.setStartNode(node);
 	}
     }
 
@@ -128,9 +142,10 @@
     
     public NodeIterator getTypedChildren(final int type) {
 	NodeIterator iterator = _domImpl.getTypedChildren(_reverse[type]);
-	if ((_reverse[type] == DOM.TEXT) && (_filter != null))
-	    iterator = _domImpl.strippingIterator(iterator,_mapping,_filter);
-	return(iterator);
+	if (_reverse[type] == DOM.TEXT && _filter != null) {
+	    return _domImpl.strippingIterator(iterator,_mapping,_filter);
+	}
+	return iterator;
     }
 
     public NodeIterator getNamespaceAxisIterator(final int axis, final int ns) {
@@ -139,26 +154,28 @@
 
     public NodeIterator getAxisIterator(final int axis) {
 	NodeIterator iterator = _domImpl.getAxisIterator(axis);
-	if (_filter != null)
-	    iterator = _domImpl.strippingIterator(iterator,_mapping,_filter);
-	return(iterator);
+	if (_filter != null) {
+	    return _domImpl.strippingIterator(iterator, _mapping, _filter);
+	}
+	return iterator;
     }
     
     public NodeIterator getTypedAxisIterator(final int axis, final int type) {
 	NodeIterator iterator;
 
 	if (axis == Axis.NAMESPACE) {
-	    if ((type == NO_TYPE) || (type > _NSreverse.length))
-		iterator = _domImpl.getAxisIterator(axis);
-	    else
-		iterator = _domImpl.getTypedAxisIterator(axis,_NSreverse[type]);
+	    iterator = (type == NO_TYPE || type > _NSreverse.length) ?
+		_domImpl.getAxisIterator(axis) :
+		_domImpl.getTypedAxisIterator(axis,_NSreverse[type]);
 	}
-	else
+	else {
 	    iterator = _domImpl.getTypedAxisIterator(axis, _reverse[type]);
+	}
 	
-	if ((_reverse[type] == DOM.TEXT) && (_filter != null))
-	    iterator = _domImpl.strippingIterator(iterator,_mapping,_filter);
-	return(iterator);
+	if (_reverse[type] == DOM.TEXT && _filter != null) {
+	    iterator = _domImpl.strippingIterator(iterator, _mapping, _filter);
+	}
+	return iterator;
     }
 
     public NodeIterator getNthDescendant(int type, int n, boolean includeself) {
@@ -166,7 +183,8 @@
     }
 
     public NodeIterator getNodeValueIterator(NodeIterator iterator, int type,
-					     String value, boolean op) {
+					     String value, boolean op) 
+    {
 	return _domImpl.getNodeValueIterator(iterator, type, value, op);
     }
 
@@ -278,4 +296,9 @@
 	return(_domImpl.isAttribute(node));
     }
 
+    public String lookupNamespace(int node, String prefix) 
+	throws TransletException 
+    {
+	return _domImpl.lookupNamespace(node, prefix);
+    }
 }
diff --git a/src/org/apache/xalan/xsltc/dom/DOMBuilder.java b/src/org/apache/xalan/xsltc/dom/DOMBuilder.java
index cc67a53..dabd49e 100644
--- a/src/org/apache/xalan/xsltc/dom/DOMBuilder.java
+++ b/src/org/apache/xalan/xsltc/dom/DOMBuilder.java
@@ -64,4 +64,4 @@
 import org.xml.sax.ContentHandler;
 import org.xml.sax.ext.LexicalHandler;
 
-public interface DOMBuilder extends ContentHandler, LexicalHandler { }
+public interface DOMBuilder extends  ExtendedSAX { }
diff --git a/src/org/apache/xalan/xsltc/dom/DOMImpl.java b/src/org/apache/xalan/xsltc/dom/DOMImpl.java
index df1a7ea..f82c8df 100644
--- a/src/org/apache/xalan/xsltc/dom/DOMImpl.java
+++ b/src/org/apache/xalan/xsltc/dom/DOMImpl.java
@@ -81,6 +81,7 @@
 
 import org.xml.sax.*;
 import org.xml.sax.ext.*;
+import org.xml.sax.helpers.AttributesImpl;
 import org.apache.xalan.xsltc.*;
 import org.apache.xalan.xsltc.util.IntegerArray;
 import org.apache.xalan.xsltc.runtime.BasisLibrary;
@@ -136,8 +137,12 @@
     // Tracks which textnodes are whitespaces and which are not
     private BitArray  _whitespace; // takes xml:space into acc.
 
+    // Tracks which textnodes are not escaped
+    private BitArray  _dontEscape = null; 
+
     // The URI to this document
-    private String    _documentURI;
+    private String    _documentURI = null;
+    static private int _documentURIIndex = 0;
 
     // Support for access/navigation through org.w3c.dom API
     private Node[] _nodes;
@@ -159,11 +164,11 @@
      * Returns the origin of the document from which the tree was built
      */
     public String getDocumentURI() {
-	return(_documentURI);
+	return (_documentURI != null) ? _documentURI : "rtf" + _documentURIIndex++;
     }
 
     public String getDocumentURI(int node) {
-	return(_documentURI);
+	return getDocumentURI();
     }
 
     public void setupMapping(String[] names, String[] namespaces) {
@@ -171,6 +176,37 @@
     }
 
     /**
+     * Lookup a namespace URI from a prefix starting at node. This method 
+     * is used in the execution of xsl:element when the prefix is not known 
+     * at compile time.
+     */
+    public String lookupNamespace(int node, String prefix) 
+	throws TransletException 
+    {
+	int anode, nsnode;
+	final AncestorIterator ancestors = new AncestorIterator();
+	
+	if (isElement(node)) {
+	    ancestors.includeSelf();
+	}
+
+	ancestors.setStartNode(node);
+	while ((anode = ancestors.next()) != NULL) {
+	    final NodeIterator namespaces = 
+		new NamespaceIterator().setStartNode(anode);
+
+	    while ((nsnode = namespaces.next()) != NULL) {
+		if (_prefixArray[_prefix[nsnode]].equals(prefix)) {
+		    return getNodeValue(nsnode);
+		}
+	    }
+	}
+
+	// TODO: Internationalization?
+	throw new TransletException("Namespace prefix '" + prefix + "' is undeclared.");
+    }
+
+    /**
      * Returns 'true' if a specific node is an element (of any type)
      */
     public boolean isElement(final int node) {
@@ -206,11 +242,7 @@
 	// Hack for ordering attribute nodes
 	if (node1 >= _firstAttributeNode) node1 = _parent[node1];
 	if (node2 >= _firstAttributeNode) node2 = _parent[node2];
-
-	if ((node2 < _treeNodeLimit) && (node1 < node2))
-	    return(true);
-	else
-	    return(false);
+	return (node2 < _treeNodeLimit && node1 < node2);
     }
 
     /**
@@ -220,9 +252,8 @@
 	if (_nodes == null) {
 	    _nodes = new Node[_type.length];
 	}
-	return _nodes[index] != null
-	    ? _nodes[index]
-	    : (_nodes[index] = new NodeImpl(index));
+	return _nodes[index] != null ? _nodes[index]
+				     : (_nodes[index] = new NodeImpl(index));
     }
 
     /**
@@ -240,9 +271,8 @@
 	if (_nodeLists == null) {
 	    _nodeLists = new NodeList[_type.length];
 	}
-	return _nodeLists[index] != null
-	    ? _nodeLists[index]
-	    : (_nodeLists[index] = new NodeListImpl(index));
+	return _nodeLists[index] != null ? _nodeLists[index]
+		     : (_nodeLists[index] = new NodeListImpl(index));
     }
 
     /**
@@ -257,8 +287,7 @@
      * Create an empty org.w3c.dom.NodeList
      */
     private NodeList getEmptyNodeList() {
-	return EmptyNodeList != null
-	    ? EmptyNodeList
+	return EmptyNodeList != null ? EmptyNodeList
 	    : (EmptyNodeList = new NodeListImpl(new int[0]));
     }
 
@@ -266,8 +295,7 @@
      * Create an empty org.w3c.dom.NamedNodeMap
      */
     private NamedNodeMap getEmptyNamedNodeMap() {
-	return EmptyNamedNodeMap != null
-	    ? EmptyNamedNodeMap
+	return EmptyNamedNodeMap != null ? EmptyNamedNodeMap
 	    : (EmptyNamedNodeMap = new NamedNodeMapImpl(new int[0]));
     }
 
@@ -755,18 +783,19 @@
 	}
 
 	public NodeIterator reset() {
-	    if (hasChildren(_startNode))
-		_currentChild = _offsetOrChild[_startNode];
-	    else
-		_currentChild = END;
+	    _currentChild = hasChildren(_startNode) ? 
+			    _offsetOrChild[_startNode] : END;
 	    return resetPosition();
 	}
 
 	public int next() {
-	    for (int node = _currentChild; node != END;
-		 node = _nextSibling[node]) {
-		if (_type[node] == _nodeType) {
-		    _currentChild = _nextSibling[node];
+	    final short[] type = _type;
+	    final int nodeType = _nodeType;
+	    final int[] nextSibling = _nextSibling;
+
+	    for (int node = _currentChild; node != END; node = nextSibling[node]) {
+		if (type[node] == nodeType) {
+		    _currentChild = nextSibling[node];
 		    return returnNode(node);
 		}
 	    }
@@ -982,9 +1011,14 @@
 	    _nodeType = nodeType;
 	}
                   
-	// assumes caller will pass element nodes
 	public NodeIterator setStartNode(int node) {
 	    if (_isRestartable) {
+		// If not an element node, then set iterator at END
+		if (!isElement(node)) {
+		    _attribute = END;
+		    return resetPosition();
+		}
+
 		for (node = _lengthOrAttr[_startNode = node];
 		     node != NULL && _type[node] != _nodeType;
 		     node = _nextSibling[node]);
@@ -1053,6 +1087,7 @@
 		while ((_ns == DOM.NULL) && (_node != DOM.NULL)) {
 		    _node = _parent[_node];
 		    _ns = _lengthOrAttr[_node];
+
 		    while ((_ns != DOM.NULL) && (_type[_ns] != NAMESPACE)) {
 			_ns = _nextSibling[_ns];
 		    }
@@ -1376,12 +1411,15 @@
 	public NodeIterator setStartNode(int node) {
 	    if (_isRestartable) {
 		_last = -1;
-		if (node >= _firstAttributeNode)
-		    _startNode = node = _parent[node];
-		else if (_includeSelf)
+		if (_includeSelf) {
 		    _startNode = node;
-		else
+		}
+		else if (node >= _firstAttributeNode) {
+		    _startNode = node = _parent[node];
+		}
+		else {
 		    _startNode = _parent[node];
+		}
 		_index = _startNode;
 		return resetPosition();
 	    }
@@ -1395,12 +1433,9 @@
                   
 	public int next() {
 	    if (_index >= 0) {
-		int bob = _index;
-		if (_index == 0)
-		    _index = -1;
-		else
-		    _index = _parent[_index];
-		return returnNode(bob);
+		final int node = _index;
+		_index = (_index == 0) ? -1 : _parent[_index];
+		return returnNode(node);
 	    }
 	    return(NULL);
 	}
@@ -1482,7 +1517,9 @@
 
 	public int next() {
 	    while (++_node < _limit) {
-		if (_type[_node] > TEXT) return(returnNode(_node));
+		if (_type[_node] > TEXT) {
+		    return(returnNode(_node));
+		}
 	    } 
 	    return(NULL);
 	}
@@ -1946,10 +1983,7 @@
      * Returns the type of a specific node
      */
     public int getType(final int node) {
-	if (node >= _type.length)
-	    return(0);
-	else
-	    return _type[node];
+	return (node >= _type.length) ? 0 : _type[node];
     }
     
     /**
@@ -1957,10 +1991,8 @@
      */
     public int getNamespaceType(final int node) {
 	final int type = _type[node];
-	if (type >= NTYPES)
-	    return(_namespace[type-NTYPES]);
-	else
-	    return(0); // default namespace
+	return (type >= NTYPES) ? _namespace[type-NTYPES] 
+	    : 0; 	// default namespace
     }
 
     /**
@@ -1980,20 +2012,16 @@
 	case ROOT:
 	    return getNodeValue(_offsetOrChild[node]);
 	case TEXT:
+	    // GTM - add escapign code here too.
 	case COMMENT:
 	    return makeStringValue(node);
 	case PROCESSING_INSTRUCTION:
 	    final String pistr = makeStringValue(node);
 	    final int col = pistr.indexOf(' ');
-	    if (col > 0)
-		return pistr.substring(col+1);
-	    else
-		return pistr;
+	    return (col > 0) ?  pistr.substring(col+1) : pistr;
 	default:
-	    if (node < _firstAttributeNode)
-		return getElementValue(node); // element string value
-	    else
-		return makeStringValue(node); // attribute value
+	    return (node < _firstAttributeNode) ? getElementValue(node) :
+						  makeStringValue(node);
 	}
     }
 
@@ -2061,20 +2089,16 @@
 		len = uri.length();
 		if (len > 0) len++;
 	    }
-
-	    if ((name.length() > 0) && (name.charAt(len) == '@'))
-		result[i] = (short)ATTRIBUTE;
-	    else
-		result[i] = (short)ELEMENT;
+	    result[i] = (short) ((name.length() > 0 && name.charAt(len) == '@') ?
+		ATTRIBUTE : ELEMENT);
 	}
 
 	// actual mapping of caller requested names
 	for (i = 0; i < namesLength; i++) {
 	    result[getGeneralizedType(names[i])] = (short)(i + NTYPES);
 	}
-             
-	return(result);
 
+	return result;
     }
 
     /**
@@ -2093,7 +2117,7 @@
 	    if (result[i + NTYPES] == ELEMENT)
 		result[i + NTYPES] = NO_TYPE;
 	}
-	return(result);
+	return result;
     }
 
     /**
@@ -2127,15 +2151,11 @@
 	final int length = namespaces.length;
 	final short[] result = new short[length];
 
-	for (i=0; i<length; i++) {
+	for (i = 0; i < length; i++) {
 	    Integer type = (Integer)_nsIndex.get(namespaces[i]);
-	    if (type == null)
-		result[i] = -1;
-	    else
-		result[i] = type.shortValue();
+	    result[i] = (type == null) ? -1 : type.shortValue();
 	}
-
-	return(result);
+	return result;
     }
 
     /**
@@ -2162,6 +2182,13 @@
 
 	out.writeObject(_whitespace);
 
+	if (_dontEscape != null) {
+	    out.writeObject(_dontEscape);
+	}
+	else {
+	    out.writeObject(new BitArray(0));
+	}
+
 	out.flush();
     }
 
@@ -2190,6 +2217,11 @@
 
 	_whitespace    = (BitArray)in.readObject();
 
+	_dontEscape    = (BitArray)in.readObject();
+	if (_dontEscape.size() == 0) {
+	    _dontEscape = null;
+        }
+
 	_types         = setupMapping(_namesArray);
     }
 
@@ -2261,17 +2293,12 @@
 	    return EMPTYSTRING;
 	case DOM.NAMESPACE:
 	    final int index = _prefix[node];
-	    if (index < _prefixArray.length)
-		return _prefixArray[index];
-	    else
-		return EMPTYSTRING;
+	    return (index < _prefixArray.length) ? _prefixArray[index]
+						 : EMPTYSTRING;
 	case DOM.PROCESSING_INSTRUCTION:
 	    final String pistr = makeStringValue(node);
 	    final int col = pistr.indexOf(' ');
-	    if (col > -1)
-		return(pistr.substring(0,col));
-	    else
-		return pistr;
+	    return (col > -1) ? pistr.substring(0,col) : pistr;
 	default:
 	    // Construct the local part (omit '@' for attributes)
 	    String name  = getLocalName(node);
@@ -2281,8 +2308,9 @@
 	    final int pi = _prefix[node];
 	    if (pi > 0) {
 		final String prefix = _prefixArray[pi];
-		if (prefix != EMPTYSTRING)
-		    name = prefix+':'+name;
+		if (prefix != EMPTYSTRING) {
+		    name = prefix + ':' + name;
+		}
 	    }
 	    return name;
 	}
@@ -2298,10 +2326,7 @@
 	else {
 	    final int type = getNamespaceType(node);
 	    final String name = _uriArray[type];
-	    if (name == null)
-		return(EMPTYSTRING);
-	    else
-		return(name);
+	    return (name == null) ? EMPTYSTRING : name;
 	}
     }
 
@@ -2330,20 +2355,14 @@
      */
     public String getAttributeValue(final int type, final int element) {
 	final int attr = getAttributeNode(type, element);
-	if (attr != NULL)
-	    return makeStringValue(attr);
-	else
-	    return EMPTYSTRING;
+	return (attr != NULL) ? makeStringValue(attr) : EMPTYSTRING;
     }
 
     /**
      * Returns true if a given element has an attribute of a given type
      */
     public boolean hasAttribute(final int type, final int node) {
-	if (getAttributeNode(type, node) != NULL)
-	    return true;
-	else
-	    return false;
+	return (getAttributeNode(type, node) != NULL);
     }
 
     /**
@@ -2369,10 +2388,8 @@
      * Returns an iterator with all the children of a given node
      */
     public NodeIterator getChildren(final int node) {
-	if (hasChildren(node))
-	    return(new ChildrenIterator());
-	else
-	    return(EMPTYITERATOR);
+	return hasChildren(node) ? new ChildrenIterator()
+				 : EMPTYITERATOR;
     }
 
     /**
@@ -2440,66 +2457,58 @@
      * containing nodes of a typed axis (ex.: child::foo)
      */
     public NodeIterator getTypedAxisIterator(int axis, int type) {
-	NodeIterator iterator = null;
-
 	/* This causes an error when using patterns for elements that
 	   do not exist in the DOM (translet types which do not correspond
 	   to a DOM type are mapped to the DOM.ELEMENT type).
 	*/
 
-	if (type == NO_TYPE) {
-	    return(EMPTYITERATOR);
+	// Most common case handled first
+	if (axis == Axis.CHILD && type != ELEMENT) {
+	    return new TypedChildrenIterator(type);
 	}
-        else if ((type == ELEMENT) && (axis != Axis.NAMESPACE)) {
-	    iterator = new FilterIterator(getAxisIterator(axis),
-					  getElementFilter());
+
+	if (type == NO_TYPE) {
+	    return EMPTYITERATOR;
+	}
+
+        if (type == ELEMENT && axis != Axis.NAMESPACE) {
+	    return new FilterIterator(getAxisIterator(axis),
+				      getElementFilter());
 	}
 	else {
 	    switch (axis) {
 	    case Axis.SELF:
-		iterator = new TypedSingletonIterator(type);
-		break;
-	    case Axis.CHILD:
-		iterator = new TypedChildrenIterator(type);
-		break;
+		return new TypedSingletonIterator(type);
 	    case Axis.PARENT:
-		return(new ParentIterator().setNodeType(type));
+		return new ParentIterator().setNodeType(type);
 	    case Axis.ANCESTOR:
-		return(new TypedAncestorIterator(type));
+		return new TypedAncestorIterator(type);
 	    case Axis.ANCESTORORSELF:
-		return((new TypedAncestorIterator(type)).includeSelf());
+		return (new TypedAncestorIterator(type)).includeSelf();
 	    case Axis.ATTRIBUTE:
-		return(new TypedAttributeIterator(type));
+		return new TypedAttributeIterator(type);
 	    case Axis.DESCENDANT:
-		iterator = new TypedDescendantIterator(type);
-		break;
+		return new TypedDescendantIterator(type);
 	    case Axis.DESCENDANTORSELF:
-		iterator = (new TypedDescendantIterator(type)).includeSelf();
-		break;
+		return (new TypedDescendantIterator(type)).includeSelf();
 	    case Axis.FOLLOWING:
-		iterator = new TypedFollowingIterator(type);
-		break;
+		return new TypedFollowingIterator(type);
 	    case Axis.PRECEDING:
-		iterator = new TypedPrecedingIterator(type);
-		break;
+		return new TypedPrecedingIterator(type);
 	    case Axis.FOLLOWINGSIBLING:
-		iterator = new TypedFollowingSiblingIterator(type);
-		break;
+		return new TypedFollowingSiblingIterator(type);
 	    case Axis.PRECEDINGSIBLING:
-		iterator = new TypedPrecedingSiblingIterator(type);
-		break;
+		return new TypedPrecedingSiblingIterator(type);
 	    case Axis.NAMESPACE:
-		if (type == ELEMENT)
-		    iterator = new NamespaceIterator();
-		else
-		    iterator = new TypedNamespaceIterator(type);
-		break;
+		return (type == ELEMENT) ?  
+		    (NodeIterator) new NamespaceIterator() :
+		    (NodeIterator) new TypedNamespaceIterator(type);
 	    default:
 		BasisLibrary.runTimeError(BasisLibrary.TYPED_AXIS_SUPPORT_ERR,
 					  Axis.names[axis]);
 	    }
 	}
-	return(iterator);
+	return null;
     }
 
     /**
@@ -2510,26 +2519,21 @@
      * nodes are taken, while 'ns' specifies the namespace URI type.
      */
     public NodeIterator getNamespaceAxisIterator(int axis, int ns) {
-
-	NodeIterator iterator = null;
-
 	if (ns == NO_TYPE) {
-	    return(EMPTYITERATOR);
+	    return EMPTYITERATOR;
 	}
 	else {
 	    switch (axis) {
 	    case Axis.CHILD:
-		iterator = new NamespaceChildrenIterator(ns);
-		break;
+		return new NamespaceChildrenIterator(ns);
 	    case Axis.ATTRIBUTE:
-		iterator = new NamespaceAttributeIterator(ns);
-		break;
+		return new NamespaceAttributeIterator(ns);
 	    default:
 		BasisLibrary.runTimeError(BasisLibrary.TYPED_AXIS_SUPPORT_ERR,
 					  Axis.names[axis]);
 	    }
 	}
-	return(iterator);
+	return null;
     }
 
     /**
@@ -2537,27 +2541,23 @@
      * a given type.
      */
     public NodeIterator getTypedDescendantIterator(int type) {
-	NodeIterator iterator;
-	if (type == ELEMENT)
-	    iterator = new FilterIterator(new DescendantIterator(),
-					  getElementFilter());
-	else
-	    iterator = new TypedDescendantIterator(type);
-	return(iterator);
+	return (type == ELEMENT) ? (NodeIterator)
+	    new FilterIterator(new DescendantIterator(), getElementFilter())
+	    : (NodeIterator) new TypedDescendantIterator(type);
     }
 
     /**
      * Returns the nth descendant of a node
      */
     public NodeIterator getNthDescendant(int type, int n, boolean includeself) {
-	NodeIterator source;
-	if (type == ELEMENT)
-	    source = new FilterIterator(new DescendantIterator(),
-					getElementFilter());
-	else
-	    source = new TypedDescendantIterator(type);
-	if (includeself) ((NodeIteratorBase)source).includeSelf();
-	return(new NthDescendantIterator(source, n, type));
+	NodeIterator source = (type == ELEMENT) ? (NodeIterator)
+	     new FilterIterator(new DescendantIterator(), getElementFilter())
+	     : (NodeIterator) new TypedDescendantIterator(type);
+
+	if (includeself) {
+	    ((NodeIteratorBase)source).includeSelf();
+	}
+	return new NthDescendantIterator(source, n, type);
     }
 
     /**
@@ -2614,9 +2614,23 @@
 				       _lengthOrAttr[node]));
 	    break;
 	case TEXT:
+	    boolean last = false;
+	    boolean escapeBit = false;
+
+	    if (_dontEscape != null) {	
+		escapeBit = _dontEscape.getBit(node);
+		if (escapeBit) {
+		    last = handler.setEscaping(false);
+		}	
+	    }
+
 	    handler.characters(_text,
 			       _offsetOrChild[node],
 			       _lengthOrAttr[node]);
+
+            if (_dontEscape != null && escapeBit) {
+		handler.setEscaping(last);
+	    }	
 	    break;
 	case ATTRIBUTE:
 	    shallowCopy(node, handler);
@@ -2628,6 +2642,7 @@
 	    if (isElement(node)) {
 		// Start element definition
 		final String name = copyElement(node, type, handler);
+
 		// Copy element attribute
 		for (int a=_lengthOrAttr[node]; a!=NULL; a=_nextSibling[a]) {
 		    if (_type[a] != NAMESPACE) {
@@ -2686,17 +2701,19 @@
      * Performs a shallow copy (ref. XSLs copy())
      */
     public String shallowCopy(final int node, TransletOutputHandler handler)
-	throws TransletException {
-
+	throws TransletException 
+    {
 	final int type = _type[node];
 
 	switch(type) {
 	case ROOT: // do nothing
 	    return EMPTYSTRING;
 	case TEXT:
+
 	    handler.characters(_text,
 			       _offsetOrChild[node],
 			       _lengthOrAttr[node]);
+
 	    return null;
 	case PROCESSING_INSTRUCTION:
 	    copyPI(node, handler);
@@ -2729,40 +2746,53 @@
 
     private String copyElement(int node, int type,
 			       TransletOutputHandler handler)
-	throws TransletException {
-
+	throws TransletException 
+    {
 	type = type - NTYPES;
 	String name = _namesArray[type];
 	final int pi = _prefix[node];
 	final int ui = _namespace[type];
+
 	if (pi > 0) {
 	    final String prefix = _prefixArray[pi];
 	    final String uri = _uriArray[ui];
 	    final String local = getLocalName(node);
-	    if (prefix.equals(EMPTYSTRING))
-		name = local;
-	    else
-		name = prefix+':'+local;
+
+	    name = prefix.equals(EMPTYSTRING) ? local : (prefix + ':' + local);
 	    handler.startElement(name);
 	    handler.namespace(prefix, uri);
 	}
 	else {
 	    if (ui > 0) {
-		handler.startElement(getLocalName(node));
+		handler.startElement(name = getLocalName(node));
 		handler.namespace(EMPTYSTRING, _uriArray[ui]);
 	    }
 	    else {
 		handler.startElement(name);
 	    }
 	}
+
+	// Copy element namespaces
+	for (int a = _lengthOrAttr[node]; a != NULL; a = _nextSibling[a]) {
+	    if (_type[a] == NAMESPACE) {
+		handler.namespace(_prefixArray[_prefix[a]],
+				  makeStringValue(a));
+	    }
+	}
+
 	return name;
     }
 
     /**
      * Returns the string value of the entire tree
      */
+    private String _cachedStringValue = null;
+
     public String getStringValue() {
-	return getElementValue(ROOTNODE);
+	if (_cachedStringValue == null) {
+	    _cachedStringValue = getElementValue(ROOTNODE);
+	}
+	return _cachedStringValue;
     }
 
     /**
@@ -2819,6 +2849,18 @@
 	    if ((name = getNodeName(element)) != null) {
 		buffer.append('<');
 		buffer.append(name);
+
+		int attribute = _lengthOrAttr[element];
+		while (attribute != NULL) {
+		    // Skip namespace nodes
+		    if (_type[attribute] != NAMESPACE) {
+			buffer.append(' ').append(getNodeName(attribute))
+			      .append("=\"").append(getNodeValue(attribute))
+			      .append('"');
+		    }
+		    attribute = _nextSibling[attribute];
+		}
+
 		if (_offsetOrChild[element] == NULL) {
 		    buffer.append("/>");
 		    return buffer;
@@ -2899,8 +2941,7 @@
      * DOM builder's interface is pure SAX2 (must investigate)
      */
     public TransletOutputHandler getOutputDomBuilder() {
-	DOMBuilder builder = getBuilder();
-	return new SAXAdapter(builder, builder);
+	return new SAXAdapter(new DOMBuilderImpl());
     }
 
     /**
@@ -2959,6 +3000,11 @@
 	private static final String XML_STRING = "xml:";
 	private static final String XMLSPACE_STRING = "xml:space";
 	private static final String PRESERVE_STRING = "preserve";
+	private static final String XML_PREFIX   = "xml";
+	private static final String XMLNS_PREFIX = "xmlns";
+
+	private boolean _escaping = true;
+	private boolean _disableEscaping = false;
 
 	/**
 	 * Default constructor for the DOMBuiler class
@@ -2973,11 +3019,8 @@
 	private String getNamespaceURI(String prefix) {
 	    // Get the stack associated with this namespace prefix
 	    final Stack stack = (Stack)_nsPrefixes.get(prefix);
-	    if ((stack != null) && (!stack.empty())) {
-		return((String)stack.peek());
-	    }
-	    else
-		return(EMPTYSTRING);
+	    return (stack != null && !stack.empty()) ? (String) stack.peek()
+		: EMPTYSTRING;
 	}
 
 	/**
@@ -3076,7 +3119,6 @@
 	 */
 	private short makeElementNode(String uri, String localname)
 	    throws SAXException {
-	    
 	    final String name;
 	    if (uri != EMPTYSTRING)
 		name = uri + ':' + localname;
@@ -3170,6 +3212,7 @@
 	 */
 	private int makeTextNode(boolean isWhitespace) {
 	    if (_currentOffset > _baseOffset) {
+
 		final int node = nextNode();
 		final int limit = _currentOffset;
 		// Tag as whitespace node if the parser tells us that it is...
@@ -3188,6 +3231,14 @@
 		_type[node] = TEXT;
 		linkChildren(node);
 		storeTextRef(node);
+
+		if (_disableEscaping) {
+		    if (_dontEscape == null) {
+			_dontEscape = new BitArray(_whitespace.size());
+		    }
+		    _dontEscape.setBit(node);
+		    _disableEscaping = false;
+		}
 		return node;
 	    }
 	    return -1;
@@ -3217,33 +3268,34 @@
 	 * Creates an attribute node
 	 */
 	private int makeAttributeNode(int parent, Attributes attList, int i)
-	    throws SAXException {
-
+	    throws SAXException 
+	{
     	    final int node = nextAttributeNode();
-
 	    final String qname = attList.getQName(i);
-	    final String localname = attList.getLocalName(i);
+	    String localName = attList.getLocalName(i);
 	    final String value = attList.getValue(i);
 	    StringBuffer namebuf = new StringBuffer(EMPTYSTRING);
 	    
-	    // Create the internal attribute node name (uri+@+localname)
-	    if (qname.startsWith(XML_STRING)) {
-		if (qname.startsWith(XMLSPACE_STRING))
-		    xmlSpaceDefine(attList.getValue(i), parent);
+	    if (qname.startsWith(XMLSPACE_STRING)) {
+		xmlSpaceDefine(attList.getValue(i), parent);
 	    }
+
+	    // If local name is null set it to the empty string
+	    if (localName == null) {
+		localName = EMPTYSTRING;
+	    }
+
+	    // Create the internal attribute node name (uri+@+localname)
 	    final String uri = attList.getURI(i);
-	    if ((uri != null) && (!uri.equals(EMPTYSTRING))) {
+	    if (uri != null && !uri.equals(EMPTYSTRING)) {
 		namebuf.append(uri);
 		namebuf.append(':');
 	    }
 	    namebuf.append('@');
-	    if (localname != null )
-                namebuf.append(localname);
-            else
-                namebuf.append(qname);
+	    namebuf.append(localName.length() > 0 ? localName : qname);
 
 	    String name = namebuf.toString();
-	    
+
 	    // Get the index of the attribute node name (create new if non-ex).
 	    Integer obj = (Integer)_names.get(name);
 	    if (obj == null) {
@@ -3273,13 +3325,14 @@
 	 */
 	public void characters(char[] ch, int start, int length) {
 	    if (_currentOffset + length > _text.length) {
-		// GTM resizeTextArray(_text.length * 2);
-		// bug fix 6189, contributed by Mirko Seifert
 		resizeTextArray(
 		    Math.max(_text.length * 2, _currentOffset + length));
 	    }
 	    System.arraycopy(ch, start, _text, _currentOffset, length);
 	    _currentOffset += length;
+
+	    _disableEscaping = !_escaping;	
+
 	}
 
 	/**
@@ -3295,7 +3348,7 @@
 	    _type2[0] = NAMESPACE;
 
 	    startPrefixMapping(EMPTYSTRING, EMPTYSTRING);
-	    startPrefixMapping("xml", "http://www.w3.org/XML/1998/namespace");
+	    startPrefixMapping(XML_PREFIX, "http://www.w3.org/XML/1998/namespace");
 	    _lengthOrAttr[ROOTNODE] = _nextNamespace;
 	    _parent2[_nextNamespace] = ROOTNODE;
 	    _nextNamespace = DOM.NULL;
@@ -3374,41 +3427,52 @@
 
 	    _lengthOrAttr[node] = DOM.NULL;
 
+	    int last = -1;
 	    final int count = attributes.getLength();
 
 	    // Append any namespace nodes
 	    if (_nextNamespace != DOM.NULL) {
 		_lengthOrAttr[node] = _nextNamespace;
+
 		while (_nextNamespace != DOM.NULL) {
 		    _parent2[_nextNamespace] = node;
-		    int tail = _nextNamespace;
-		    _nextNamespace = _nextSibling2[_nextNamespace];
+		    _nextNamespace = _nextSibling2[last = _nextNamespace];
 		    // Chain last namespace node to following attribute node(s)
-		    if ((_nextNamespace == DOM.NULL) && (count > 0))
-			_nextSibling2[tail] = _currentAttributeNode;
+		    if (_nextNamespace == DOM.NULL && count > 0) {
+			_nextSibling2[last] = _currentAttributeNode;
+		    }
 		}
 	    }
 
+	    // If local name is null set it to the empty string
+	    if (localName == null) {
+		localName = EMPTYSTRING;
+	    }
+
 	    // Append any attribute nodes
+	    boolean attrsAdded = false;
 	    if (count > 0) {
 		int attr = _currentAttributeNode;
-		if (_lengthOrAttr[node] == DOM.NULL)
+		if (_lengthOrAttr[node] == DOM.NULL) {
 		    _lengthOrAttr[node] = attr;
-		for (int i = 0; i<count; i++) {
-		    attr = makeAttributeNode(node, attributes, i);
-		    _parent2[attr] = node;
-		    _nextSibling2[attr] = attr + 1;
 		}
-		_nextSibling2[attr] = DOM.NULL;
+		for (int i = 0; i < count; i++) {
+		    if (!attributes.getQName(i).startsWith(XMLNS_PREFIX)) {
+			attr = makeAttributeNode(node, attributes, i);
+			_parent2[attr] = node;
+			_nextSibling2[attr] = attr + 1;
+			attrsAdded = true;
+		    }
+		}
+		// Did we append namespace nodes only?
+		_nextSibling2[(!attrsAdded && last != -1) ? last : attr] = DOM.NULL;
 	    }
 
 	    final int col = qname.lastIndexOf(':');
 
 	    // Assign an internal type to this element (may exist)
-	    if ((uri != null) && (localName.length() > 0))
-		_type[node] = makeElementNode(uri, localName);
-	    else
-		_type[node] = makeElementNode(qname, col);
+	    _type[node] = (uri != null && localName.length() > 0) ?
+		makeElementNode(uri, localName) : makeElementNode(qname, col);
 
 	    // Assign an internal type to the element's prefix (may exist)
 	    if (col > -1) {
@@ -3451,7 +3515,8 @@
 	 */
 	public void ignorableWhitespace(char[] ch, int start, int length) {
 	    if (_currentOffset + length > _text.length) {
-		resizeTextArray(_text.length * 2);
+		resizeTextArray(
+		    Math.max(_text.length * 2, _currentOffset + length));
 	    }
 	    System.arraycopy(ch, start, _text, _currentOffset, length);
 	    _currentOffset += length;
@@ -3502,7 +3567,8 @@
 		else
 		    _nextSibling2[attr-1] = attr;
 		_nextSibling2[attr] = DOM.NULL;
-		_prefix2[attr] = idx.shortValue();
+		// _prefix2[attr] = idx.shortValue();
+		_prefix2[attr] = ((Integer) stack.elementAt(0)).shortValue();
 	    }
 	}
 
@@ -3521,7 +3587,8 @@
 	public void comment(char[] ch, int start, int length) {
 	    makeTextNode(false);
 	    if (_currentOffset + length > _text.length) {
-		resizeTextArray(_text.length * 2);
+		resizeTextArray(
+		    Math.max(_text.length * 2, _currentOffset + length));
 	    }
 	    System.arraycopy(ch, start, _text, _currentOffset, length);
 	    _currentOffset += length;
@@ -3546,8 +3613,6 @@
 	private void characters(final String string) {
 	    final int length = string.length();
 	    if (_currentOffset + length > _text.length) {
-		// GTM: resizeTextArray(_text.length * 2);
-		// bug fix 6189, contributed by Mirko Seifert
 		resizeTextArray(
 		    Math.max(_text.length * 2, _currentOffset + length));
 	    }
@@ -3587,6 +3652,11 @@
 	    // Resize the '_whitespace' array (a BitArray instance)
 	    _whitespace.resize(newSize);
 
+	    // Resize the '_dontEscape' array (a BitArray instance)
+	    if (_dontEscape != null) {
+		_dontEscape.resize(newSize);
+	    }
+
 	    // Resize the '_prefix' array
 	    final short[] newPrefix = new short[newSize];
 	    System.arraycopy(_prefix, 0, newPrefix, 0, length);
@@ -3656,5 +3726,11 @@
 	    }
 	}
 
+ 	public boolean setEscaping(boolean value) {
+	    final boolean temp = _escaping;
+	    _escaping = value; 
+	    return temp;
+    	}
+
     } // end of DOMBuilder
 }
diff --git a/src/org/apache/xalan/xsltc/compiler/LongExpr.java b/src/org/apache/xalan/xsltc/dom/ExtendedSAX.java
similarity index 77%
rename from src/org/apache/xalan/xsltc/compiler/LongExpr.java
rename to src/org/apache/xalan/xsltc/dom/ExtendedSAX.java
index e650658..8e87428 100644
--- a/src/org/apache/xalan/xsltc/compiler/LongExpr.java
+++ b/src/org/apache/xalan/xsltc/dom/ExtendedSAX.java
@@ -56,34 +56,14 @@
  * information on the Apache Software Foundation, please see
  * <http://www.apache.org/>.
  *
- * @author G. Todd Miller 
+ * @author Morten Jorgensen
  *
  */
+package org.apache.xalan.xsltc.dom;
 
-package org.apache.xalan.xsltc.compiler;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ext.LexicalHandler;
 
-import org.apache.xalan.xsltc.compiler.util.Type;
-import org.apache.bcel.generic.*;
-import org.apache.xalan.xsltc.compiler.util.*;
-
-final class LongExpr extends Expression {
-    private final long _value;
-
-    public LongExpr(long value) {
-        _value = value;
-    }
-
-    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
-	return _type = Type.Lng;
-    }
-
-    public String toString() {
-	return "long-expr(" + _value + ')';
-    }
-
-    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
-	ConstantPoolGen cpg = classGen.getConstantPool();
-	InstructionList il = methodGen.getInstructionList();
-	il.append(new PUSH(cpg, _value));
-    }
+public interface ExtendedSAX extends ContentHandler, LexicalHandler { 
+    public boolean setEscaping(boolean escape);
 }
diff --git a/src/org/apache/xalan/xsltc/dom/MultiDOM.java b/src/org/apache/xalan/xsltc/dom/MultiDOM.java
index 95b7b87..95bfa77 100644
--- a/src/org/apache/xalan/xsltc/dom/MultiDOM.java
+++ b/src/org/apache/xalan/xsltc/dom/MultiDOM.java
@@ -76,6 +76,7 @@
 import org.apache.xalan.xsltc.runtime.BasisLibrary;
 
 public final class MultiDOM implements DOM {
+
     private static final int NO_TYPE = DOM.FIRST_TYPE - 2;
     private static final int INITIAL_SIZE = 4;
     private static final int CLR = 0x00FFFFFF;
@@ -88,12 +89,11 @@
     private Hashtable _documents = new Hashtable();
 
     private final class AxisIterator implements NodeIterator {
-	// constitutive data
 	private final int _axis;
 	private final int _type;
-	// implementation mechanism
-	private NodeIterator _source;
+
 	private int _mask;
+	private NodeIterator _source = null;
 	
 	public AxisIterator(final int axis, final int type) {
 	    _axis = axis;
@@ -112,18 +112,23 @@
 	}
 
 	public NodeIterator setStartNode(final int node) {
-	    _mask = node & SET;
-	    int dom = node >>> 24;
-	    // consider caching these
-	    if ((_type == NO_TYPE) || (_type == DOM.ELEMENT)) {
-		_source = _adapters[dom].getAxisIterator(_axis);
+	    final int dom = node >>> 24;
+	    final int mask = node & SET;
+
+	    // Get a new source first time and when mask changes
+	    if (_source == null || _mask != mask) {
+		if (_type == NO_TYPE) {
+		    _source = _adapters[dom].getAxisIterator(_axis);
+		}
+		else if (_axis == Axis.CHILD && _type != ELEMENT) {
+		    _source = _adapters[dom].getTypedChildren(_type);
+		}
+		else {
+		    _source = _adapters[dom].getTypedAxisIterator(_axis, _type);
+		}
 	    }
-	    else if (_axis == Axis.CHILD) {
-		_source = _adapters[dom].getTypedChildren(_type);
-	    }
-	    else {
-		_source = _adapters[dom].getTypedAxisIterator(_axis,_type);
-	    }
+
+	    _mask = mask;
 	    _source.setStartNode(node & CLR);
 	    return this;
 	}
@@ -142,10 +147,7 @@
 	}
     
 	public boolean isReverse() {
-	    if (_source == null)
-		return(false);
-	    else
-		return _source.isReverse();
+	    return (_source == null) ? false : _source.isReverse();
 	}
     
 	public void setMark() {
@@ -262,8 +264,7 @@
 	// This method only has a function in DOM adapters
     }
 
-    public int addDOMAdapter(DOM dom) {
-
+    public int addDOMAdapter(DOMAdapter dom) {
 	// Add the DOM adapter to the array of DOMs
 	final int domNo = _free++;
 	if (domNo == _size) {
@@ -275,9 +276,11 @@
 
 	// Store reference to document (URI) in hashtable
 	String uri = dom.getDocumentURI(0);
-	_documents.put(uri,new Integer(domNo));
+	_documents.put(uri, new Integer(domNo));
 	
-	return domNo << 24;
+	// Store mask in DOMAdapter
+	dom.setMultiDOMMask(domNo << 24);
+	return (domNo << 24);
     }
     
     public int getDocumentMask(String uri) {
@@ -288,7 +291,9 @@
 	    return((domIdx.intValue() << 24));
     }
 
-    /** returns singleton iterator containg the document root */
+    /** 
+      * Returns singleton iterator containg the document root 
+      */
     public NodeIterator getIterator() {
 	// main source document @ 0
 	return _adapters[0].getIterator();
@@ -453,4 +458,9 @@
 	return(_adapters[node>>>24].isAttribute(node & CLR));
     }
 
+    public String lookupNamespace(int node, String prefix) 
+	throws TransletException
+    {
+	return _adapters[node>>>24].lookupNamespace(node, prefix);
+    }
 }
diff --git a/src/org/apache/xalan/xsltc/dom/NodeIteratorBase.java b/src/org/apache/xalan/xsltc/dom/NodeIteratorBase.java
index 310ae5e..78d56a4 100644
--- a/src/org/apache/xalan/xsltc/dom/NodeIteratorBase.java
+++ b/src/org/apache/xalan/xsltc/dom/NodeIteratorBase.java
@@ -83,7 +83,8 @@
     public NodeIterator reset() {
 	final boolean temp = _isRestartable;
 	_isRestartable = true;
-	setStartNode(_startNode);
+	// Must adjust _startNode if self is included
+	setStartNode(_includeSelf ? _startNode + 1 : _startNode);
 	_isRestartable = temp;
 	return this;
     }
diff --git a/src/org/apache/xalan/xsltc/dom/SortingIterator.java b/src/org/apache/xalan/xsltc/dom/SortingIterator.java
index 9d16c2b..e2ffd9e 100644
--- a/src/org/apache/xalan/xsltc/dom/SortingIterator.java
+++ b/src/org/apache/xalan/xsltc/dom/SortingIterator.java
@@ -66,11 +66,12 @@
 
 import org.apache.xalan.xsltc.NodeIterator;
 import org.apache.xalan.xsltc.TransletException;
+import org.apache.xalan.xsltc.runtime.BasisLibrary;
 
 public final class SortingIterator extends NodeIteratorBase {
     private final static int INIT_DATA_SIZE = 16;
-    private final NodeIterator _source;
-    private final NodeSortRecordFactory _factory;
+    private NodeIterator _source;
+    private NodeSortRecordFactory _factory;
     private NodeSortRecord[] _data;
     private int _free = 0;
     private int _current;	// index in _nodes of the next node to try
@@ -124,6 +125,29 @@
 	_current = _markedNode;
     }
     
+    /**
+     * Clone a <code>SortingIterator</code> by cloning its source
+     * iterator and then sharing the factory and the array of
+     * <code>NodeSortRecords</code>.
+     */
+    public NodeIterator cloneIterator() {
+	try {
+	    final SortingIterator clone = (SortingIterator) super.clone();
+	    clone._source = _source.cloneIterator();  
+	    clone._factory = _factory;		// shared between clones
+	    clone._data = _data;		// shared between clones
+	    clone._free = _free;
+	    clone._current = _current;
+	    clone.setRestartable(false);
+	    return clone.reset();
+	}
+	catch (CloneNotSupportedException e) {
+	    BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR,
+				      e.toString());
+	    return null;
+	}
+    }
+
     private void addRecord(NodeSortRecord record) {
 	if (_free == _data.length) {
 	    NodeSortRecord[] newArray = new NodeSortRecord[_data.length * 2];
diff --git a/src/org/apache/xalan/xsltc/dom/StepIterator.java b/src/org/apache/xalan/xsltc/dom/StepIterator.java
index fe4cdbe..8edb6b3 100644
--- a/src/org/apache/xalan/xsltc/dom/StepIterator.java
+++ b/src/org/apache/xalan/xsltc/dom/StepIterator.java
@@ -104,12 +104,10 @@
 	if (_isRestartable) {
 	    // Set start node for left-hand iterator...
 	    _source.setStartNode(_startNode = node);
+
 	    // ... and get start node for right-hand iterator from left-hand,
 	    // with special case for //* path - see ParentLocationPath
-	    if (_includeSelf)
-		_iterator.setStartNode(_startNode);
-	    else
-		_iterator.setStartNode(_source.next());
+	    _iterator.setStartNode(_includeSelf ? _startNode : _source.next());
 	    return resetPosition();
 	}
 	return this;
@@ -118,10 +116,7 @@
     public NodeIterator reset() {
 	_source.reset();
 	// Special case for //* path - see ParentLocationPath
-	if (_includeSelf)
-	    _iterator.setStartNode(_startNode);
-	else
-	    _iterator.setStartNode(_source.next());
+	_iterator.setStartNode(_includeSelf ? _startNode : _source.next());
 	return resetPosition();
     }
     
diff --git a/src/org/apache/xalan/xsltc/dom/UnionIterator.java b/src/org/apache/xalan/xsltc/dom/UnionIterator.java
index bfd1452..be22cd1 100644
--- a/src/org/apache/xalan/xsltc/dom/UnionIterator.java
+++ b/src/org/apache/xalan/xsltc/dom/UnionIterator.java
@@ -152,8 +152,10 @@
 	    final int smallest = _heap[0].node;
 	    if (smallest == END) { // iterator _heap[0] is done
 		if (_heapSize > 1) {
-		    // replace it with last
+		    // Swap first and last (iterator must be restartable)
+		    final LookAheadIterator temp = _heap[0];
 		    _heap[0] = _heap[--_heapSize];
+		    _heap[_heapSize] = temp;
 		}
 		else {
 		    return END;
diff --git a/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java b/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java
index e363410..8bffb59 100644
--- a/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java
+++ b/src/org/apache/xalan/xsltc/runtime/AbstractTranslet.java
@@ -65,8 +65,8 @@
 
 package org.apache.xalan.xsltc.runtime;
 
-import java.io.File;
-import java.util.Vector;
+import java.io.FileWriter;
+import java.util.ArrayList;
 import java.util.Enumeration;
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
@@ -77,6 +77,7 @@
 import org.apache.xalan.xsltc.dom.KeyIndex;
 import org.apache.xalan.xsltc.dom.DTDMonitor;
 import org.apache.xalan.xsltc.util.IntegerArray;
+import org.apache.xalan.xsltc.runtime.output.*;
 
 public abstract class AbstractTranslet implements Translet {
 
@@ -103,6 +104,25 @@
     // Use one empty string instead of constantly instanciating String("");
     private final static String EMPTYSTRING = "";
 
+    
+    /************************************************************************
+     * Debugging
+     ************************************************************************/
+    public void printInternalState() {
+	System.out.println("-------------------------------------");
+	System.out.println("AbstractTranslet this = " + this);
+	System.out.println("vbase = " + vbase);
+	System.out.println("vframe = " + vframe);
+	System.out.println("varsStack.size() = " + varsStack.size());
+	System.out.println("pbase = " + pbase);
+	System.out.println("vframe = " + pframe);
+	System.out.println("paramsStack.size() = " + paramsStack.size());
+	System.out.println("namesArray.size = " + namesArray.length);
+	System.out.println("namespaceArray.size = " + namespaceArray.length);
+	System.out.println("");
+	System.out.println("Total memory = " + Runtime.getRuntime().totalMemory());
+    }
+
     /**
      * Wrap the initial input DOM in a dom adapter. This adapter is wrapped in
      * a DOM multiplexer if the document() function is used (handled by compiled
@@ -123,18 +143,18 @@
     // Variable's stack: <tt>vbase</tt> and <tt>vframe</tt> are used 
     // to denote the current variable frame.
     protected int vbase = 0, vframe = 0;
-    protected Vector varsStack = new Vector();
+    protected ArrayList varsStack = new ArrayList();
 
     // Parameter's stack: <tt>pbase</tt> and <tt>pframe</tt> are used 
     // to denote the current parameter frame.
     protected int pbase = 0, pframe = 0;
-    protected Vector paramsStack = new Vector();
+    protected ArrayList paramsStack = new ArrayList();
 
     /**
      * Push a new parameter frame.
      */
     public final void pushParamFrame() {
-	paramsStack.insertElementAt(new Integer(pbase), pframe);
+	paramsStack.add(pframe, new Integer(pbase));
 	pbase = ++pframe;
     }
 
@@ -143,51 +163,21 @@
      */
     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.get(--pbase)).intValue();
+	    for (int i = pframe - 1; i >= pbase; i--) {
+		paramsStack.remove(i);
 	    }
+	    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) {
-	String parName = new String(name);
-	parName = replace(parName, '.', "$dot$");
-	parName = replace(parName, '-', "$dash$");
-	return addParameter(parName, value, false);
+	name = BasisLibrary.replace(name, ".-", 
+				    new String[] { "$dot$", "$dash$" });
+	return addParameter(name, value, false);
     }
 
     /**
@@ -196,16 +186,17 @@
      * default value from the <xsl:parameter> element's select attribute or
      * element body.
      */
-    public final Object addParameter(String name, Object value,
-				     boolean isDefault) {
-
+    public final Object addParameter(String name, Object value, 
+	boolean isDefault) 
+    {
 	// Local parameters need to be re-evaluated for each iteration
 	for (int i = pframe - 1; i >= pbase; i--) {
-	    final Parameter param = (Parameter) paramsStack.elementAt(i);
+	    final Parameter param = (Parameter) paramsStack.get(i);
+
 	    if (param._name.equals(name)) {
 		// Only overwrite if current value is the default value and
 		// the new value is _NOT_ the default value.
-		if ((param._isDefault == true) || (!isDefault)) {
+		if (param._isDefault || !isDefault) {
 		    param._value = value;
 		    param._isDefault = isDefault;
 		    return value;
@@ -215,8 +206,7 @@
 	}
 
 	// Add new parameter to parameter stack
-	final Parameter param = new Parameter(name, value, isDefault);
-	paramsStack.insertElementAt(param, pframe++);
+	paramsStack.add(pframe++, new Parameter(name, value, isDefault));
 	return value;
     }
 
@@ -224,6 +214,7 @@
      * Clears the parameter stack.
      */
     public void clearParameters() {  
+	pbase = pframe = 0;
 	paramsStack.clear();
     }
 
@@ -233,7 +224,7 @@
      */
     public final Object getParameter(String name) {
 	for (int i = pframe - 1; i >= pbase; i--) {
-	    final Parameter param = (Parameter)paramsStack.elementAt(i);
+	    final Parameter param = (Parameter)paramsStack.get(i);
 	    if (param._name.equals(name)) return param._value;
 	}
 	return null;
@@ -243,9 +234,14 @@
      * Push a new variable frame.
      */
     public final void pushVarFrame(int frameSize) {
-	varsStack.insertElementAt(new Integer(vbase), vframe);
+	varsStack.add(vframe, new Integer(vbase));
 	vbase = ++vframe;
 	vframe += frameSize;
+
+	// Clear stack frame
+	for (int i = vbase; i <= vframe + 1; i++) {
+	    varsStack.add(i, null);
+	}
     }
 
     /**
@@ -253,16 +249,11 @@
      */
     public final void popVarFrame() {
 	if (vbase > 0) {
-	    int bot = vbase - 1;
-	    int top = vframe - 1;
-	    vframe = vbase - 1;
-	    vbase = ((Integer)varsStack.elementAt(vframe)).intValue();
-	    // bug fix 3424, John Howard
-	    // remove objects that are in the stack since objects are	
-	    // added with insertElementAt(int) and will cause memory retention
-	    for (int i=top; i>=bot; i--) {
-		varsStack.removeElementAt(i);
+	    final int oldvbase = ((Integer)varsStack.get(--vbase)).intValue();
+	    for (int i = vbase; i < vframe; i++) {
+		varsStack.set(i, null);		// for the GC
 	    }
+	    vframe = vbase; vbase = oldvbase;
 	}
     }
 
@@ -270,18 +261,14 @@
      * 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);
+	return varsStack.get(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.set(vbase + vindex, value);
     }
 
     /************************************************************************
@@ -501,17 +488,23 @@
      ************************************************************************/
 
     public TransletOutputHandler openOutputHandler(String filename) 
-	throws TransletException {
+	throws TransletException 
+    {
 	try {
-	    // Use the default SAX handler to send the output to the file
-	    DefaultSAXOutputHandler handler =
-		new DefaultSAXOutputHandler(filename, _encoding);
+	    final TransletOutputHandlerFactory factory 
+		= TransletOutputHandlerFactory.newInstance();
 
-	    // Create a translet output handler and plug in the SAX handler
-	    TextOutput text = new TextOutput(handler, handler, _encoding);
-	    transferOutputSettings(text);
-	    text.startDocument();
-	    return(text);
+	    factory.setEncoding(_encoding);
+	    factory.setOutputMethod(_method);
+	    factory.setWriter(new FileWriter(filename));
+	    factory.setOutputType(TransletOutputHandlerFactory.STREAM);
+
+	    final TransletOutputHandler handler 
+		= factory.getTransletOutputHandler();
+
+	    transferOutputSettings(handler);
+	    handler.startDocument();
+	    return handler;
 	}
 	catch (Exception e) {
 	    throw new TransletException(e);
@@ -569,46 +562,43 @@
     /**
      * Transfer the output settings to the output post-processor
      */
-    protected void transferOutputSettings(TransletOutputHandler output) {
-
-	// It is an error if this method is called with anything else than
-	// the translet post-processor (TextOutput)
-	if (!(output instanceof TextOutput)) return;
-
-	TextOutput handler = (TextOutput)output;
-
-	// Transfer the output method setting
+    protected void transferOutputSettings(TransletOutputHandler handler) {
 	if (_method != null) {
-	    // Transfer all settings relevant to XML output
 	    if (_method.equals("xml")) {
-	        if (_standalone != null) handler.setStandalone(_standalone);
-		handler.setType(TextOutput.XML);
+	        if (_standalone != null) {
+		    handler.setStandalone(_standalone);
+		}
+		if (_omitHeader) {
+		    handler.omitHeader(true);
+		}
 		handler.setCdataElements(_cdata);
-		if (_version != null) handler.setVersion(_version);
-		if (_omitHeader) handler.omitHeader(true);
+		if (_version != null) {
+		    handler.setVersion(_version);
+		}
 		handler.setIndent(_indent);
-		if (_doctypeSystem != null)
+		if (_doctypeSystem != null) {
 		    handler.setDoctype(_doctypeSystem, _doctypePublic);
+		}
 	    }
-	    // Transfer all output settings relevant to HTML output
 	    else if (_method.equals("html")) {
-		handler.setType(TextOutput.HTML);
 		handler.setIndent(_indent);
 		handler.setDoctype(_doctypeSystem, _doctypePublic);
-		if (_mediaType != null) handler.setMediaType(_mediaType);
-	    }
-	    else if (_method.equals("text")) {
-		handler.setType(TextOutput.TEXT);
-	    }
-	    else {
-		handler.setType(TextOutput.QNAME);
+		if (_mediaType != null) {
+		    handler.setMediaType(_mediaType);
+		}
 	    }
 	}
 	else {
 	    handler.setCdataElements(_cdata);
-	    if (_version != null) handler.setVersion(_version);
-	    if (_standalone != null) handler.setStandalone(_standalone);
-	    if (_omitHeader) handler.omitHeader(true);
+	    if (_version != null) {
+		handler.setVersion(_version);
+	    }
+	    if (_standalone != null) {
+		handler.setStandalone(_standalone);
+	    }
+	    if (_omitHeader) {
+		handler.omitHeader(true);
+	    }
 	    handler.setIndent(_indent);
 	    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..93f8f0c 100644
--- a/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java
+++ b/src/org/apache/xalan/xsltc/runtime/BasisLibrary.java
@@ -79,6 +79,10 @@
 import org.apache.xalan.xsltc.*;
 import org.apache.xalan.xsltc.DOM;
 import org.apache.xalan.xsltc.NodeIterator;
+import org.apache.xalan.xsltc.dom.Axis;
+import org.apache.xalan.xsltc.dom.DOMAdapter;
+import org.apache.xalan.xsltc.dom.MultiDOM;
+import org.apache.xalan.xsltc.dom.AbsoluteIterator;
 import org.apache.xalan.xsltc.dom.SingletonIterator;
 
 /**
@@ -427,7 +431,7 @@
 	if (name.equals("xsl:version"))
 	    return("1.0");
 	if (name.equals("xsl:vendor"))
-	    return("Apache Xalan XSLTC");
+	    return("Apache Software Foundation (Xalan XSLTC)");
 	if (name.equals("xsl:vendor-url"))
 	    return("http://xml.apache.org/xalan-j");
 	
@@ -447,6 +451,15 @@
 	    return EMPTYSTRING;
     }
 
+    /**
+     * Implements the nodeset() extension function. 
+     */
+    public static NodeIterator nodesetF(DOM rtf) {
+	final DOMAdapter adapter = (DOMAdapter) rtf;
+	return new SingletonIterator(
+	    DOM.ROOTNODE | adapter.getMultiDOMMask(), true);
+    }
+
     //-- Begin utility functions
 
     private static boolean isWhiteSpace(char ch) {
@@ -877,6 +890,31 @@
 	try {
 	    StringBuffer result = new StringBuffer();
 	    formatter.applyLocalizedPattern(pattern);
+
+	    //------------------------------------------------------
+ 	    // bug fix # 9179 - make sure localized pattern contains
+	    //   a leading zero before decimal, handle cases where  
+	    //   decimal is in position zero, and >= to 1. 
+	    //   localized pattern is ###.### convert to ##0.###
+	    //   localized pattern is .###    convert to 0.###
+	    //------------------------------------------------------
+	    String localizedPattern = formatter.toPattern();
+	    int index = localizedPattern.indexOf('.');
+	    if ( index >= 1  && localizedPattern.charAt(index-1) == '#' ) {
+		//insert a zero before the decimal point in the pattern
+		StringBuffer newpattern = new StringBuffer();
+		newpattern.append(localizedPattern.substring(0, index-1));
+                newpattern.append("0");
+                newpattern.append(localizedPattern.substring(index));
+		formatter.applyLocalizedPattern(newpattern.toString());
+	    } else if (index == 0) {
+                // insert a zero before decimal point in pattern
+                StringBuffer newpattern = new StringBuffer();
+                newpattern.append("0");
+                newpattern.append(localizedPattern);
+		formatter.applyLocalizedPattern(newpattern.toString());
+            }
+
 	    formatter.format(number, result, _fieldPosition);
 	    return(result.toString());
 	}
@@ -891,28 +929,31 @@
      * obj is an instanceof Node then create a singleton iterator.
      */
     public static NodeIterator referenceToNodeSet(Object obj) {
-	try {
-	    // Convert var/param -> node
-	    if (obj instanceof Node) {
-		return(new SingletonIterator(((Node)obj).node));
-	    }
-	    // Convert var/param -> node-set
-	    else if (obj instanceof NodeIterator) {
-		return(((NodeIterator)obj).cloneIterator());
-	    }
-	    // Convert var/param -> result-tree fragment
-	    else if (obj instanceof DOM) {
-		DOM dom = (DOM)obj;
-		return(dom.getIterator());
-	    }
-	    else {
-		final String className = obj.getClass().getName();
-		runTimeError(DATA_CONVERSION_ERR, "reference", className);
-		return null;
-	    }
+	// Convert var/param -> node
+	if (obj instanceof Node) {
+	    return(new SingletonIterator(((Node)obj).node));
 	}
-	catch (ClassCastException e) {
-	    runTimeError(DATA_CONVERSION_ERR, "reference", "node-set");
+	// Convert var/param -> node-set
+	else if (obj instanceof NodeIterator) {
+	    return(((NodeIterator)obj).cloneIterator());
+	}
+	else {
+	    final String className = obj.getClass().getName();
+	    runTimeError(DATA_CONVERSION_ERR, "reference", className);
+	    return null;
+	}
+    }
+
+    /**
+     * Utility function used to convert references to DOMs. 
+     */
+    public static DOM referenceToResultTree(Object obj) {
+	try {
+	    return ((DOM) obj);
+	}
+	catch (IllegalArgumentException e) {
+	    final String className = obj.getClass().getName();
+	    runTimeError(DATA_CONVERSION_ERR, "reference", className);
 	    return null;
 	}
     }
@@ -960,6 +1001,29 @@
 	}
     }
     
+    /**
+     * This function is used in the execution of xsl:element
+     */
+    public static String getPrefix(String qname) {
+	final int index = qname.indexOf(':');
+	return (index > 0) ? qname.substring(0, index) : null;
+    }
+
+    /**
+     * This function is used in the execution of xsl:element
+     */
+    private static int prefixIndex = 0;
+    public static String generatePrefix() {
+	return ("ns" + prefixIndex++);
+    }
+
+    /**
+     * This function is used in the execution of xsl:element
+     */
+    public static String makeQName(String localName, String prefix) {
+	return (new StringBuffer(prefix).append(':').append(localName).toString());
+    }
+
     public static final int RUN_TIME_INTERNAL_ERR   = 0;
     public static final int RUN_TIME_COPY_ERR       = 1;
     public static final int DATA_CONVERSION_ERR     = 2;
@@ -1011,5 +1075,31 @@
 	System.out.println(msg);
     }
 
+    /**
+     * Replace a certain character in a string with a new substring.
+     */
+    public static String replace(String base, char ch, String str) {
+	return (base.indexOf(ch) < 0) ? base : 
+	    replace(base, String.valueOf(ch), new String[] { str });
+    }
+
+    public static String replace(String base, String delim, String[] str) {
+	final int len = base.length();
+	final StringBuffer result = new StringBuffer();
+
+	for (int i = 0; i < len; i++) {
+	    final char ch = base.charAt(i);
+	    final int k = delim.indexOf(ch);
+
+	    if (k >= 0) {
+		result.append(str[k]);
+	    }
+	    else {
+		result.append(ch);
+	    }
+	}
+	return result.toString();
+    }
+
     //-- End utility functions
 }
diff --git a/src/org/apache/xalan/xsltc/runtime/Constants.java b/src/org/apache/xalan/xsltc/runtime/Constants.java
index 4f72e23..da2bdb3 100644
--- a/src/org/apache/xalan/xsltc/runtime/Constants.java
+++ b/src/org/apache/xalan/xsltc/runtime/Constants.java
@@ -83,4 +83,9 @@
     public static final String NAMESPACE_FEATURE =
 	"http://xml.org/sax/features/namespaces";
 
+    public static final String EMPTYSTRING = "";
+    public static final String XML_PREFIX = "xml";
+    public static final String XMLNS_PREFIX = "xmlns";
+    public static final String XMLNS_STRING = "xmlns:";
+    public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
 }
diff --git a/src/org/apache/xalan/xsltc/runtime/DefaultRun.java b/src/org/apache/xalan/xsltc/runtime/DefaultRun.java
deleted file mode 100644
index 6b66121..0000000
--- a/src/org/apache/xalan/xsltc/runtime/DefaultRun.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * @(#)$Id$
- *
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 2001 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- *    if any, must include the following acknowledgment:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowledgment may appear in the software itself,
- *    if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Xalan" and "Apache Software Foundation" must
- *    not be used to endorse or promote products derived from this
- *    software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- *    nor may "Apache" appear in their name, without prior written
- *    permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 2001, Sun
- * Microsystems., http://www.sun.com.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * @author Jacek Ambroziak
- * @author Santiago Pericas-Geertsen
- * @author G. Todd Miller
- * @author Morten Jorgensen
- *
- */
-
-package org.apache.xalan.xsltc.runtime;
-
-import java.io.*;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.UnknownHostException;
-import java.util.Vector;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.xml.sax.XMLReader;
-import org.xml.sax.SAXException;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.ext.LexicalHandler;
-
-import org.apache.xalan.xsltc.*;
-import org.apache.xalan.xsltc.dom.DOMImpl;
-import org.apache.xalan.xsltc.dom.Axis;
-import org.apache.xalan.xsltc.dom.DTDMonitor;
-import org.apache.xalan.xsltc.runtime.Constants;
-
-final public class DefaultRun {
-
-    private TransletOutputHandler _handler;
-
-    private String  _fileName;
-    private String  _className;
-    private String  _jarFileSrc;
-    private boolean _isJarFileSpecified = false;
-    private Vector  _params = null;
-    private boolean _uri, _debug;
-
-    AbstractTranslet _translet;
-
-    public DefaultRun(String className, String fileName,
-		      boolean uri, boolean debug) {
-	_fileName = fileName;
-	_className = className;
-	_uri = uri;
-	_debug = debug;
-    }
-
-    public void setParameters(Vector params) {
-	_params = params;
-    }
-
-    private void setJarFileInputSrc(boolean flag,  String jarFile) {
-	// TODO: at this time we do not do anything with this
-	// information, attempts to add the jarfile to the CLASSPATH
-	// were successful via System.setProperty, but the effects
-	// were not visible to the running JVM. For now we add jarfile
-	// to CLASSPATH in the wrapper script that calls this program. 
-	_isJarFileSpecified = flag;
-	// TODO verify jarFile exists...
-	_jarFileSrc = jarFile;	
-    }
-
-    private void doTransform() {
-	try {
-	    final Class clazz = Class.forName(_className);
-	    final Translet translet = (Translet)clazz.newInstance();
-
-	    // Create a SAX parser and get the XMLReader object it uses
-	    final SAXParserFactory factory = SAXParserFactory.newInstance();
-	    try {
-		factory.setFeature(Constants.NAMESPACE_FEATURE, true);
-	    }
-	    catch (Exception e) {
-		factory.setNamespaceAware(true);
-	    }
-	    final SAXParser parser = factory.newSAXParser();
-	    final XMLReader reader = parser.getXMLReader();
-
-	    // Set the DOM's DOM builder as the XMLReader's SAX2 content handler
-	    final DOMImpl dom = new DOMImpl();
-	    reader.setContentHandler(dom.getBuilder());
-	    // Create a DTD monitor and pass it to the XMLReader object
-	    final DTDMonitor dtdMonitor = new DTDMonitor();
-	    dtdMonitor.handleDTD(reader);
-
-	    _translet = (AbstractTranslet)translet;
-	    dom.setDocumentURI(_fileName);
-	    if (_uri)
-		reader.parse(_fileName);
-	    else {
-	        reader.parse(new File(_fileName).toURL().toExternalForm());
-	    }
-	    
-	    // Set size of key/id indices
-	    _translet.setIndexSize(dom.getSize());
-	    // If there are any elements with ID attributes, build an index
-	    dtdMonitor.buildIdIndex(dom, 0, _translet);
-
-	    _translet.setDTDMonitor(dtdMonitor);
-
-	    // Pass global parameters
-	    int n = _params.size();
-	    for (int i = 0; i < n; i++) {
-		Parameter param = (Parameter) _params.elementAt(i);
-		translet.addParameter(param._name, param._value);
-	    }
-
-	    // Transform the document
-	    String encoding = _translet._encoding;
-
-	    DefaultSAXOutputHandler saxHandler =
-		new DefaultSAXOutputHandler(System.out, encoding);
-	    TextOutput textOutput =
-		new TextOutput((ContentHandler)saxHandler,
-			       (LexicalHandler)saxHandler, encoding);
-	    translet.transform(dom, textOutput);
-
-	    if (_debug) {
-		TransletOutputBase handler = new TransletOutputBase();
-		long start = System.currentTimeMillis();
-		final int nTimes = 100;
-		for (int i = 0; i < nTimes; i++)
-		    translet.transform(dom, dom.getIterator(), handler);
-		long end = System.currentTimeMillis();
-		System.out.println("total " + (end - start) + " msec for " 
-				   + nTimes + " transformations");
-		System.out.println(((double)end - start)/nTimes + " msec avg");
-	    }
-	}
-	catch (TransletException e) {
-	    System.err.println("\nTranslet Error: " + e.getMessage());
-	    if (_debug) {
-		System.err.println(e.toString());
-		e.printStackTrace();
-	    }
-	    doSystemExit(1);	    
-	}
-	catch (RuntimeException e) {
-	    System.err.println("\nRuntime Error: " + e.getMessage());
-	    if (_debug) {
-		System.err.println(e.toString());
-		e.printStackTrace();
-	    }
-	    doSystemExit(1);
-	}
-	catch (FileNotFoundException e) {
-	    System.err.println("Error: File or URI '"+_fileName+"' not found.");
-	    doSystemExit(1);
-	}
-	catch (MalformedURLException e) {
-	    System.err.println("Error: Invalid URI '"+_fileName+"'.");
-	    doSystemExit(1);
-	}
-	catch (ClassNotFoundException e) {
-	    System.err.println("Error: Cannot find class '"+_className+"'.");
-	    doSystemExit(1);
-	}
-        catch (UnknownHostException e) {
-	    System.err.println("Error: Can't resolve URI specification '"+ 
-			       _fileName+"'.");
-	    doSystemExit(1);
-        }
-	catch (Exception e) {
-	    e.printStackTrace();
-	    System.err.println("Error: internal error.");
-	    doSystemExit(1);
-	}
-    }
-
-    /** If we should call System.exit or not */
-    protected static boolean allowSystemExit = true;
-
-    /** Worker method to call System.exit or not */
-    protected static void doSystemExit(int retVal) {
-        if (allowSystemExit)
-            System.exit(retVal);
-    }
-
-    private final static String USAGE_STRING =
-	"Usage: \n" +
-	"     xslt [-j <jarfile>] {-u <document_url> | <document>} <class>\n"+
-	"          [<name1>=<value1> ...]\n\n" +
-	"           <document> is the xml document to be transformed, or\n" +
-	"           <document_url> is a url for the xml document,\n" +
-	"           <class> is the translet class which is either in\n" +
-	"           user's CLASSPATH or in the <jarfile> specified \n" +
-	"           with the -j option.\n" +
-	"          also: [-x] (debug), [-s] (don't allow System.exit)";	
-
-    public static void printUsage() {
-	System.err.println(USAGE_STRING);
-	System.exit(1);
-    }
-
-    public static void main(String[] args) {
-	try {
-	    if (args.length > 0) {
-		int i;
-		boolean uri = false, debug = false;
-		boolean isJarFileSpecified = false;
-		String  jarFile = null;
-
-		// Parse options starting with '-'
-		for (i = 0; i < args.length && args[i].charAt(0) == '-'; i++) {
-		    if (args[i].equals("-u")) {
-			uri = true;
-		    }
-		    else if (args[i].equals("-s")){
-			allowSystemExit = false;
-		    }
-		    else if (args[i].equals("-x")) {
-			debug = true;
-		    }
-		    else if (args[i].equals("-j")) {
-			isJarFileSpecified = true;	
-			jarFile = args[++i];
-		    }
-		    else {
-			printUsage();
-		    }
-		}
-
-		// Enough arguments left ?
-		if (args.length - i < 2) {
-		    printUsage();
-		}
-
-		// Get document file and class name
-		DefaultRun handler = new DefaultRun(args[i+1], args[i], 
-						    uri, debug);
-		handler.setJarFileInputSrc(isJarFileSpecified,	jarFile);
-
-		// Parse stylesheet parameters
-		Vector params = new Vector();
-		for (i += 2; i < args.length; i++) {
-		    int equal = args[i].indexOf('=');
-		    if (equal > 0) {
-			final Parameter param =
-			    new Parameter(args[i].substring(0, equal), 
-					  args[i].substring(equal + 1,
-							    args[i].length()));
-			params.addElement(param);
-		    }
-		    else {
-			printUsage();
-		    }
-		}
-
-		if (i == args.length) {
-		    handler.setParameters(params);
-		    handler.doTransform();
-		    doSystemExit(0);
-		}
-	    }else{
-	       printUsage();
-	    }
-	}
-	catch (Exception e) {
-	    e.printStackTrace();
-	}
-    }
-}
diff --git a/src/org/apache/xalan/xsltc/runtime/DefaultSAXOutputHandler.java b/src/org/apache/xalan/xsltc/runtime/DefaultSAXOutputHandler.java
index 37e3c3e..f808a3c 100644
--- a/src/org/apache/xalan/xsltc/runtime/DefaultSAXOutputHandler.java
+++ b/src/org/apache/xalan/xsltc/runtime/DefaultSAXOutputHandler.java
@@ -63,6 +63,8 @@
 
 package org.apache.xalan.xsltc.runtime;
 
+import java.util.Vector;
+
 import java.io.IOException;
 import java.io.Writer;
 import java.io.FileOutputStream;
@@ -122,7 +124,7 @@
     private int     _indentLevel = 0;
 
     // This is used for aggregating namespace declarations
-    private AttributeList _namespaceDeclarations = new AttributeList();
+    private Vector _namespaceDecls = null;
 
     /**
      * Constructor - set Writer to send output to and output encoding
@@ -213,11 +215,11 @@
 	buffer.append(_version);
 	buffer.append("\" encoding=\"");
 	buffer.append(_encoding);
-	if (_standalone != null) {
+	if ( _standalone != null ) {
 	    buffer.append("\" standalone=\"");
 	    buffer.append(_standalone);
 	}
-	buffer.append("\" ?>\n");
+	buffer.append("\"?>\n");
 	characters(buffer.toString());
     }
 
@@ -239,7 +241,8 @@
     /**
      * SAX2: Receive notification of the beginning of a document.
      */
-    public void startDocument() throws SAXException { }
+    public void startDocument() throws SAXException { 
+    }
 
     /**
      * SAX2: Receive notification of the end of an element.
@@ -266,7 +269,7 @@
             if (_startTagOpen) closeStartTag(true); // Close any open element.
             _element = elementName; // Save element name
 
-	    // Handle indentation (not a requirement)
+	    // Handle inden3dcb50483dcb504tation (not a requirement)
             if (_indent) {
 		if (!_emptyElements.containsKey(elementName.toLowerCase())) {
 		    indent(_lineFeedNextStartTag);
@@ -283,24 +286,26 @@
 	    _indentNextEndTag = false;
 
 	    // Output namespace declarations first...
-	    int declCount = _namespaceDeclarations.getLength();
-	    for (int i=0; i<declCount; i++) {
-		final String prefix = _namespaceDeclarations.getQName(i);
-		_writer.write(XMLNS);
-		if ((prefix != null) && (prefix != EMPTYSTRING)) {
-		    _writer.write(':');
-		    _writer.write(prefix);
+	    if (_namespaceDecls != null) {
+		int nDecls = _namespaceDecls.size();
+		for (int i = 0; i < nDecls; i++) {
+		    final String prefix = (String) _namespaceDecls.elementAt(i++);
+		    _writer.write(XMLNS);
+		    if ((prefix != null) && (prefix != EMPTYSTRING)) {
+			_writer.write(':');
+			_writer.write(prefix);
+		    }
+		    _writer.write('=');
+		    _writer.write('\"');
+		    _writer.write((String) _namespaceDecls.elementAt(i));
+		    _writer.write('\"');
 		}
-		_writer.write('=');
-		_writer.write('\"');
-		_writer.write(_namespaceDeclarations.getValue(i));
-		_writer.write('\"');
-            }
-	    _namespaceDeclarations.clear();
+		_namespaceDecls.clear();
+	    }
 
 	    // ...then output all attributes
 	    int attrCount = attrs.getLength();
-	    for (int i=0; i<attrCount; i++) {
+	    for (int i = 0; i < attrCount; i++) {
 		_writer.write(' ');
 		_writer.write(attrs.getQName(i));
 		_writer.write('=');
@@ -440,7 +445,11 @@
      *       Namespace declarations are output in startElement()
      */
     public void startPrefixMapping(String prefix, String uri) {
-	_namespaceDeclarations.add(prefix,uri);
+	if (_namespaceDecls == null) {
+	    _namespaceDecls = new Vector(2);
+	}
+	_namespaceDecls.addElement(prefix);
+	_namespaceDecls.addElement(uri);
     }
 
     /**
diff --git a/src/org/apache/xalan/xsltc/runtime/SAXAdapter.java b/src/org/apache/xalan/xsltc/runtime/SAXAdapter.java
index ae0e891..f77f890 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,18 +99,22 @@
     
     public void endDocument() throws TransletException {
 	try {
-	    _saxHandler.endDocument();
+	    _domBuilder.endDocument();
 	}
 	catch (SAXException e) {
 	    throw new TransletException(e);
 	}
     }
     
+    public void characters(String characters) throws TransletException {
+	characters(characters.toCharArray(), 0, characters.length());
+    }
+
     public void characters(char[] characters, int offset, int length)
 	throws TransletException {
 	try {
 	    maybeEmitStartElement();
-	    _saxHandler.characters(characters, offset, length);
+	    _domBuilder.characters(characters, offset, length);
 	}
 	catch (SAXException e) {
 	    throw new TransletException(e);
@@ -136,7 +135,7 @@
     public void endElement(String elementName) throws TransletException {
 	try {
 	    maybeEmitStartElement();
-	    _saxHandler.endElement(null, null, elementName);
+	    _domBuilder.endElement(null, null, elementName);
 	}
 	catch (SAXException e) {
 	    throw new TransletException(e);
@@ -161,9 +160,9 @@
     public void comment(String comment) throws TransletException {
 	try {
 	    maybeEmitStartElement();
-	    if (_lexHandler != null) {
+	    if (_domBuilder != null) {
 		char[] chars = comment.toCharArray();
-		_lexHandler.comment(chars, 0, chars.length);
+		_domBuilder.comment(chars, 0, chars.length);
 	    }
 	}
 	catch (SAXException e) {
@@ -175,22 +174,27 @@
 	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) {}
     public void setIndent(boolean indent) {}
     public void omitHeader(boolean value) {}
-    public void setCdataElements(Hashtable elements) { }
+    public void setCdataElements(Hashtable elements) {}
+    public void setDoctype(String system, String pub) {}
+    public void setMediaType(String mediaType) {}
+    public void setStandalone(String standalone) {}
+    public void setVersion(String version) {}
     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..dec46b5 100644
--- a/src/org/apache/xalan/xsltc/runtime/StringValueHandler.java
+++ b/src/org/apache/xalan/xsltc/runtime/StringValueHandler.java
@@ -71,7 +71,9 @@
     private char[] _buffer = new char[32];
     private int _free = 0;
 	
-    public void characters(char[] ch, int off, int len) {
+    public void characters(char[] ch, int off, int len) 
+	throws TransletException 
+    {
 	if (_free + len >= _buffer.length) {
 	    char[] newBuffer = new char[_free + len + 32];
 	    System.arraycopy(_buffer, 0, newBuffer, 0, _free);
@@ -86,4 +88,33 @@
 	_free = 0;		// getValue resets
 	return new String(_buffer, 0, length);
     }
+
+    public void characters(String characters) throws TransletException {
+	characters(characters.toCharArray(), 0, characters.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..73068e0 100644
--- a/src/org/apache/xalan/xsltc/runtime/TextOutput.java
+++ b/src/org/apache/xalan/xsltc/runtime/TextOutput.java
@@ -72,10 +72,11 @@
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
 
 import org.apache.xalan.xsltc.*;
 
-public final class TextOutput implements TransletOutputHandler {
+public final class TextOutput implements TransletOutputHandler, Constants {
 
     // These are the various output types we handle
     public static final int UNKNOWN = 0; // determine type from output contents
@@ -96,12 +97,11 @@
     private boolean   _startTagOpen = false;
     private boolean   _headTagOpen = false;
     private boolean   _cdataTagOpen = false;
+    private boolean   _is8859Encoded = false;
 
     // Contains all elements that should be output as CDATA sections
     private Hashtable _cdata = null;
 
-    private static final String XML_PREFIX = "xml";
-
     private static final char[] AMP      = "&amp;".toCharArray();
     private static final char[] LT       = "&lt;".toCharArray();
     private static final char[] GT       = "&gt;".toCharArray();
@@ -124,15 +124,15 @@
     private static final int BEGCOMM_length = BEGCOMM.length;
     private static final int ENDCOMM_length = ENDCOMM.length;
 
-    private static final String EMPTYSTRING     = "";
     private static final String HREF_STR        = "href";
-    private static final String SRC_STR         = "str";
+    private static final String CITE_STR        = "cite";
+    private static final String SRC_STR         = "src";
     private static final String CHAR_ESC_START  = "&#";
     private static final String CDATA_ESC_START = "]]>&#";
     private static final String CDATA_ESC_END   = ";<![CDATA[";
 
-    private AttributeList _attributes = new AttributeList();
-    private String        _elementName = null;
+    private AttributesImpl _attributes = new AttributesImpl();
+    private String         _elementName = null;
 
     // Each entry (prefix) in this hashtable points to a Stack of URIs
     private Hashtable _namespaces;
@@ -179,6 +179,7 @@
         _saxHandler = handler;
         init();
 	_encoding = encoding;
+	_is8859Encoded = _encoding.equalsIgnoreCase("iso-8859-1");	
     }
 
     /**
@@ -194,6 +195,7 @@
 	_lexHandler = lex;
         init();
 	_encoding = encoding;
+	_is8859Encoded = _encoding.equalsIgnoreCase("iso-8859-1");	
     }
 
     /**
@@ -252,8 +254,8 @@
 	    AttributeList attrs = new AttributeList();
 	    attrs.add("http-equiv", "Content-Type");
 	    attrs.add("content", _mediaType+"; charset="+_encoding);
-	    _saxHandler.startElement(null, null, "meta", attrs);
-	    _saxHandler.endElement(null, null, "meta");
+	    _saxHandler.startElement(EMPTYSTRING, EMPTYSTRING, "meta", attrs);
+	    _saxHandler.endElement(EMPTYSTRING, EMPTYSTRING, "meta");
 	}
     }
 
@@ -264,27 +266,10 @@
     public void closeStartTag() throws TransletException {
 	try {
 	    _startTagOpen = false;
-	    
-	    // Final check to assure that the element is within a namespace
-	    // that has been declared (all declarations for this element
-	    // should have been processed at this point).
-	    int col = _elementName.lastIndexOf(':');
-	    if (col > 0) {
-		final String prefix = _elementName.substring(0,col);
-		final String localname = _elementName.substring(col+1);
-		final String uri = lookupNamespace(prefix);
-		if (uri == null)
-		    BasisLibrary.runTimeError(BasisLibrary.NAMESPACE_PREFIX_ERR,
-					      prefix);
-		if (uri.equals(EMPTYSTRING)) _elementName = localname;
-		_saxHandler.startElement(uri, localname,
-					 _elementName, _attributes);
-	    }
-	    else {
-		final String uri = lookupNamespace(EMPTYSTRING);
-		_saxHandler.startElement(uri, _elementName,
-					 _elementName, _attributes);
-	    }
+
+	    // Now is time to send the startElement event
+	    _saxHandler.startElement(getNamespaceURI(_elementName, true),
+		getLocalName(_elementName), _elementName, _attributes);
 
 	    // Insert <META> tag directly after <HEAD> element in HTML output
 	    if (_headTagOpen) {
@@ -350,12 +335,13 @@
         }
     }
 
-    /**
-     * Utility method - pass a string to the SAX handler's characters() method
-     */
-    private void characters(String str) throws SAXException {
-	final char[] ch = str.toCharArray();
-	characters(ch, 0, ch.length);
+    public void characters(String str) throws TransletException {
+	try {
+	    characters(str.toCharArray(), 0, str.length());
+	}
+	catch (SAXException e) {
+            throw new TransletException(e);
+	}
     }
 
     /**
@@ -417,17 +403,19 @@
 		// the first CDATA and '>' at the beginning of the next. Other
 		// special characters/sequences are _NOT_ escaped within CDATA.
 		Integer I = (Integer)_cdataStack.peek();
-		if ((I.intValue() == _depth) && (!_cdataTagOpen))
+		if ((I.intValue() == _depth) && (!_cdataTagOpen)) {
 		    startCDATA(ch, off, len);
-		// Output characters escaped if required.
-		else if (_escapeChars)
-		    if (_cdataTagOpen)
+		} 
+		else if (_escapeChars) {
+		    if (_cdataTagOpen) {
 			escapeCDATA(ch, off, len);
-		    else
+		    } else {
 			escapeCharacters(ch, off, len);
-		// Output the chracters as the are if not.
-		else
+		    }
+		} 
+		else {
 		    _saxHandler.characters(ch, off, len);
+		}
 		return;
 
 	    case HTML:
@@ -467,9 +455,7 @@
      * Start an element in the output document. This might be an XML
      * element (<elem>data</elem> type) or a CDATA section.
      */
-    public void startElement(String elementName)
-	throws TransletException {
-
+    public void startElement(String elementName) throws TransletException {
 	try {
 	    switch(_outputType) {
 
@@ -552,9 +538,11 @@
 
 	if (limit > ch.length) limit = ch.length;;
 
+
 	// Step through characters and escape all special characters
 	for (int i = off; i < limit; i++) {
-	    switch (ch[i]) {
+	    char current = ch[i];
+	    switch (current) {
 	    case '&':
 		_saxHandler.characters(ch, offset, i - offset);
 		_saxHandler.characters(AMP, 0, AMP_length);
@@ -576,9 +564,9 @@
 		offset = i + 1;
 		break;
 	    default:
-		// Escape all characters not in the basic ASCII character set
-		// to simple (hexadecimal) character references
-		if (ch[i] > '\u007F') {
+		if ( (current >= '\u007F' && current < '\u00A0') ||
+		     (_is8859Encoded && (current > '\u00FF')) )
+		{
 		    StringBuffer buf = new StringBuffer(CHAR_ESC_START);
 		    buf.append(Integer.toString((int)ch[i]));
 		    buf.append(';');
@@ -670,6 +658,14 @@
 	return(buf.toString());
     }
 
+    private String makeHHString(int i) {
+	String s = Integer.toHexString(i).toUpperCase();
+	if (s.length() == 1) {
+	    s = "0"+s;
+	}
+	return s;
+    }
+
     /**
      * This method escapes special characters used in HTML attribute values
      */
@@ -681,9 +677,17 @@
 	char[] ch = base.toCharArray();
 	StringBuffer buf = new StringBuffer();
         for(int i=0; i<base.length(); i++){
-	    if (ch[i] > '\u007F') {
-	        buf.append('%');
-		buf.append(Integer.toHexString((int)ch[i]));
+	    if (ch[i] <= 0x20) {
+		buf.append('%');
+		buf.append(makeHHString(ch[i]));
+	    } 
+	    else if (ch[i] > '\u007F') {
+		int high = (ch[i] >> 6) | 0xC0;
+		int low  = (ch[i] & 0x3F) | 0x80;  // First 6 bits + high bit
+		buf.append('%');
+		buf.append(makeHHString(high));
+		buf.append('%');
+		buf.append(makeHHString(low));
 	    }
 	    else {
 		// These chars are reserved or unsafe in URLs
@@ -705,7 +709,8 @@
 		        buf.append(Integer.toHexString((int)ch[i]));
 		        break;
 		    case '\u0026' :
-			buf.append("&amp;");
+			//bug fix for customer/murphy3: buf.append("&amp;");
+			buf.append("&");
 			break;
 		    default:	
 		        buf.append(ch[i]); break;
@@ -758,27 +763,51 @@
 	return base;
     }
 
-    private String expandAttribute(String qname) throws TransletException {
-	// If this attribute was created using an <xsl:attribute>
-	// element with a 'namespace' attribute and a 'name' attribute
-	// containing an AVT, then we might get an attribute name on
-	// a strange format like 'prefix1:prefix2:localpart', where
-	// prefix1 is from the AVT and prefix2 from the namespace.
-	final int endcol = qname.lastIndexOf(':');
-	if (endcol > 0) {
-	    final int startcol = qname.indexOf(':');
-	    final String localname = qname.substring(endcol+1);
-	    final String prefix = qname.substring(0,startcol);
-	    final String uri = lookupNamespace(prefix);
-	    if (uri == null)
+    /**
+     * Returns the URI of an element or attribute. Note that default namespaces 
+     * do not apply directly to attributes.
+     */
+    private String getNamespaceURI(String qname, boolean isElement) 
+	throws TransletException 
+    {
+	String uri = EMPTYSTRING;
+	int col = qname.lastIndexOf(':');
+	final String prefix = (col > 0) ? qname.substring(0, col) : EMPTYSTRING;
+
+	if (prefix != EMPTYSTRING || isElement) { 
+	    uri = lookupNamespace(prefix);
+	    if (uri == null && !prefix.equals(XMLNS_PREFIX)) {
 		BasisLibrary.runTimeError(BasisLibrary.NAMESPACE_PREFIX_ERR,
-					  prefix);
-	    // Omit prefix (use default) if the namespace URI is null
-	    if (uri.equals(EMPTYSTRING))
-		return(localname);
-	    // Construct new QName if we've got two alt. prefixes
-	    else if (endcol != startcol)
-		return(prefix+':'+localname);
+					  qname.substring(0, col));
+	    }
+	}
+	return uri;
+    }
+
+    /**
+     * Returns the local name of a qualified name. If the name has no prefix
+     * then return null. 
+     */
+    private static String getLocalName(String qname) throws TransletException {
+	final int col = qname.lastIndexOf(':');
+	return (col > 0) ? qname.substring(col + 1) : null;
+    }
+
+    /**
+     * TODO: This method is a HACK! Since XSLTC does not have access to the
+     * XML file, it sometimes generates a NS prefix of the form "ns?" for
+     * an attribute. If at runtime, when the qname of the attribute is
+     * known, another prefix is specified for the attribute, then we can get 
+     * a qname of the form "ns?:otherprefix:name". This function patches the 
+     * qname by simply ignoring "otherprefix".
+     */
+    private static String patchQName(String qname) throws TransletException {
+	final int lastColon = qname.lastIndexOf(':');
+	if (lastColon > 0) {
+	    final int firstColon = qname.indexOf(':');
+	    if (firstColon != lastColon) {
+		return qname.substring(0, firstColon) + qname.substring(lastColon);
+	    }
 	}
 	return qname;
     }
@@ -790,59 +819,102 @@
     public void attribute(String name, final String value)
 	throws TransletException {
 
-	switch(_outputType) {
-	case TEXT:
-	    // Do not output attributes if output mode is 'text'
-	    return;
-	case XML:
-	    if (!_startTagOpen)
-		BasisLibrary.runTimeError(BasisLibrary.STRAY_ATTRIBUTE_ERR,name);
-	    // Attributes whose names start with XML need special handling
-	    if (name.startsWith("xml")) {
-		// Output as namespace declaration
-		if (name.startsWith("xmlns")) {
-		    if (name.length() == 5)
-			namespace(EMPTYSTRING, value);
-		    else
-			namespace(name.substring(6),value);
-		    return;
-		}
-		// Output as xml:<blah> attribute
-		_attributes.add(name, value);
-	    }
-	    else {
-		// Output as regular attribute
-		_attributes.add(expandAttribute(name), escapeString(value));
-	    }
-	    return;
-	case HTML:
-	    if (!_startTagOpen)
-		BasisLibrary.runTimeError(BasisLibrary.STRAY_ATTRIBUTE_ERR,name);
-	    // The following is an attempt to escape an URL stored in a href
-	    // attribute of HTML output. Normally URLs should be encoded at
-	    // the time they are created, since escaping or unescaping a
-	    // completed URI might change its semantics. We limit or escaping
-	    // to include space characters only - and nothing else. This is for
-	    // two reasons: (1) performance and (2) we want to make sure that
-	    // we do not change the meaning of the URL.
+	if (_outputType == TEXT) return;
 
-	    // URL-encode href attributes in HTML output
-	    final String tmp = name.toLowerCase();
-	    if  (tmp.equals(HREF_STR) || tmp.equals(SRC_STR)) {
-		_attributes.add(name,quickAndDirtyUrlEncode(escapeAttr(value)));
+	final String patchedName = patchQName(name);
+	final String localName = getLocalName(patchedName);
+	final String uri = getNamespaceURI(patchedName, false);
+	final int index = (localName == null) ?
+				_attributes.getIndex(name) :	/* don't use patchedName */
+				_attributes.getIndex(uri, localName);
+
+	switch(_outputType) {
+	case XML:
+	    if (!_startTagOpen) {
+		BasisLibrary.runTimeError(BasisLibrary.STRAY_ATTRIBUTE_ERR, patchedName);
+	    }
+
+	    // Output as namespace declaration
+	    if (name.startsWith(XMLNS_PREFIX)) {
+		namespace(name.length() > 6 ? name.substring(6) : EMPTYSTRING, value);
 	    }
 	    else {
-		_attributes.add(expandAttribute(name), escapeAttr(value));
+		if (index >= 0) {	// Duplicate attribute?
+		    _attributes.setAttribute(index, uri, localName, patchedName, "CDATA", 
+			escapeString(value));	
+		}
+		else {
+		    _attributes.addAttribute(uri, localName, patchedName, "CDATA", 
+			escapeString(value));
+		}
 	    }
-	    return;
+	    break;
+	case HTML:
+	    if (!_startTagOpen) {
+		BasisLibrary.runTimeError(BasisLibrary.STRAY_ATTRIBUTE_ERR,name);
+	    }
+
+	    /* 
+	     * The following is an attempt to escape an URL stored in a href
+	     * attribute of HTML output. Normally URLs should be encoded at
+	     * the time they are created, since escaping or unescaping a
+	     * completed URI might change its semantics. We limit or escaping
+	     * to include space characters only - and nothing else. This is for
+	     * two reasons: (1) performance and (2) we want to make sure that
+	     * we do not change the meaning of the URL.
+	     */
+	    final String tmp = name.toLowerCase();
+	    if (tmp.equals(HREF_STR) || tmp.equals(SRC_STR) || tmp.equals(CITE_STR)) {
+		if (index >= 0) {
+		    _attributes.setAttribute(index, EMPTYSTRING, EMPTYSTRING, name, 
+			"CDATA", quickAndDirtyUrlEncode(escapeAttr(value)));
+		}
+		else {
+		    _attributes.addAttribute(EMPTYSTRING, EMPTYSTRING, name, "CDATA",
+			quickAndDirtyUrlEncode(escapeAttr(value)));
+		}
+	    }
+	    else {
+		if (index >= 0) {
+		    _attributes.setAttribute(index, EMPTYSTRING, EMPTYSTRING, 
+			name, "CDATA", escapeNonURLAttr(value));
+		}
+		else {
+		    _attributes.addAttribute(EMPTYSTRING, EMPTYSTRING, 
+			name, "CDATA", escapeNonURLAttr(value));
+		}
+	    }
+	    break;
 	}
     }
 
     /**
+     * Escape non ASCII characters (> u007F) as &#XXX; entities.
+     */
+    private String escapeNonURLAttr(String base) {
+	final int len = base.length() - 1;
+
+	char[] ch = base.toCharArray();
+	StringBuffer buf = new StringBuffer();
+        for(int i=0; i<base.length(); i++){
+	    if (ch[i] > '\u007F') {
+	        buf.append(CHAR_ESC_START);
+		buf.append(Integer.toString((int)ch[i]));
+	        buf.append(';');
+	    }
+	    else {
+	        buf.append(ch[i]); 
+	    } 
+  	}
+	base = buf.toString();
+	return base;
+    }
+
+
+    /**
      * End an element or CDATA section in the output document
      */
     public void endElement(String elementName) throws TransletException {
-	
 	try {
 	    switch(_outputType) {
 	    case TEXT:
@@ -853,7 +925,10 @@
 		if (_startTagOpen) closeStartTag();
 		if (_cdataTagOpen) closeCDATA();
 
-		_saxHandler.endElement(null, null, (String)(_qnameStack.pop()));
+		final String qname = (String) _qnameStack.pop();
+		_saxHandler.endElement(getNamespaceURI(qname, true), 
+		    getLocalName(qname), qname);
+
 		popNamespaces();
 		if (((Integer)_cdataStack.peek()).intValue() == _depth)
 		    _cdataStack.pop();
@@ -862,7 +937,8 @@
 	    case HTML:
 		// Close any open element
 		if (_startTagOpen) closeStartTag();
-		_saxHandler.endElement(null, null, (String)(_qnameStack.pop()));
+		_saxHandler.endElement(EMPTYSTRING, EMPTYSTRING, 
+		    (String)(_qnameStack.pop()));
 		popNamespaces();
 		_depth--;		
 		return;
@@ -929,10 +1005,15 @@
 	_prefixStack = new Stack();
 
 	// Define the default namespace (initially maps to "" uri)
-	Stack stack =  new Stack();
-	_namespaces.put(EMPTYSTRING, stack);
+	Stack stack;
+	_namespaces.put(EMPTYSTRING, stack = new Stack());
 	stack.push(EMPTYSTRING);
 	_prefixStack.push(EMPTYSTRING);
+
+	_namespaces.put(XML_PREFIX, stack = new Stack());
+	stack.push("http://www.w3.org/XML/1998/namespace");
+	_prefixStack.push(XML_PREFIX);
+
 	_nodeStack.push(new Integer(-1));
 	_depth = 0;
     }
@@ -941,9 +1022,9 @@
      * Declare a prefix to point to a namespace URI
      */
     private void pushNamespace(String prefix, String uri) throws SAXException {
-
+	// Prefixes "xml" and "xmlns" cannot be redefined
 	if (prefix.equals(XML_PREFIX)) return;
-
+	
 	Stack stack;
 	// Get the stack that contains URIs for the specified prefix
 	if ((stack = (Stack)_namespaces.get(prefix)) == null) {
@@ -958,15 +1039,15 @@
 	_prefixStack.push(prefix);
 	_nodeStack.push(new Integer(_depth));
 
-	if ((!prefix.equals(EMPTYSTRING)) && (uri.equals(EMPTYSTRING))) return;
-	_saxHandler.startPrefixMapping(prefix, uri);
+	// Inform the SAX handler
+	_saxHandler.startPrefixMapping(prefix, escapeString(uri));
     }
 
     /**
      * Undeclare the namespace that is currently pointed to by a given prefix
      */
     private void popNamespace(String prefix) throws SAXException {
-
+	// Prefixes "xml" and "xmlns" cannot be redefined
 	if (prefix.equals(XML_PREFIX)) return;
 
 	Stack stack;
diff --git a/src/org/apache/xalan/xsltc/runtime/TransletLoader.java b/src/org/apache/xalan/xsltc/runtime/TransletLoader.java
index 1974afa..faa8861 100644
--- a/src/org/apache/xalan/xsltc/runtime/TransletLoader.java
+++ b/src/org/apache/xalan/xsltc/runtime/TransletLoader.java
@@ -57,6 +57,7 @@
  * <http://www.apache.org/>.
  *
  * @author Morten Jorgensen
+ * @author Santiago Pericas-Geertsen
  *
  */
 
@@ -64,6 +65,9 @@
 
 import java.lang.Class;
 import java.lang.ClassLoader;
+import java.lang.Thread;
+
+import java.net.*;	// temporary
 
 /**
  * This class is intended used when the default Class.forName() method fails.
@@ -91,14 +95,14 @@
      * Get a handle to the system class loader
      */
     public TransletLoader() {
-	// Get the default class loader
-	ClassLoader loader = this.getClass().getClassLoader();
-	// If this is the extensions class loader we need to get the
-	// default system class loader instead. This is permitted if
-	// this class was loaded by the extensions class loader.
-	String loaderName = loader.getClass().getName();
-	if (loaderName.equals("sun.misc.Launcher$ExtClassLoader"))
+	// Get the loader for the current thread (not the current class)
+	ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+	// Avoid using the extensions class loader (see comment above)
+	final String loaderName = loader.getClass().getName();
+	if (loaderName.equals("sun.misc.Launcher$ExtClassLoader")) {
 	    loader = ClassLoader.getSystemClassLoader();
+	}
 	_loader = loader;
     }
 
@@ -108,6 +112,7 @@
     public Class loadClass(String name) throws ClassNotFoundException {
 	return(Class.forName(name, false, _loader));
     }
+
     /**
      * Loads a Class definition and runs static initializers.
      */
diff --git a/src/org/apache/xalan/xsltc/runtime/TransletOutputBase.java b/src/org/apache/xalan/xsltc/runtime/TransletOutputBase.java
index 79bc81a..61d69ea 100644
--- a/src/org/apache/xalan/xsltc/runtime/TransletOutputBase.java
+++ b/src/org/apache/xalan/xsltc/runtime/TransletOutputBase.java
@@ -71,6 +71,7 @@
 public class TransletOutputBase implements TransletOutputHandler {
     public void startDocument() throws TransletException {}
     public void endDocument() throws TransletException {}
+    public void characters(String characters) throws TransletException {}
     public void characters(char[] characters, int offset, int length)
 	throws TransletException {}
     public void startElement(String elementName) throws TransletException {}
@@ -89,5 +90,9 @@
     public void setIndent(boolean indent) {}
     public void omitHeader(boolean value) {}
     public void setCdataElements(Hashtable elements) {}
+    public void setDoctype(String system, String pub) {}
+    public void setMediaType(String mediaType) {}
+    public void setStandalone(String standalone) {}
+    public void setVersion(String version) {}
     public void close() {}
 }
diff --git a/src/org/apache/xalan/xsltc/runtime/output/OutputBase.java b/src/org/apache/xalan/xsltc/runtime/output/OutputBase.java
new file mode 100644
index 0000000..ebb864e
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/runtime/output/OutputBase.java
@@ -0,0 +1,302 @@
+/*
+ * @(#)$Id$
+ *
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF
+ * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 2001, Sun
+ * Microsystems., http://www.sun.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * @author Santiago Pericas-Geertsen
+ * @author G. Todd Miller 
+ *
+ */
+
+package org.apache.xalan.xsltc.runtime.output;
+
+import java.util.Stack;
+
+import org.apache.xalan.xsltc.*;
+import org.apache.xalan.xsltc.runtime.*;
+import org.apache.xalan.xsltc.runtime.Hashtable;
+
+import org.apache.xalan.xsltc.TransletException;
+import org.apache.xalan.xsltc.TransletOutputHandler;
+import org.apache.xalan.xsltc.runtime.Hashtable;
+
+public abstract class OutputBase implements TransletOutputHandler, Constants {
+
+    /**
+     * Document system identifier
+     */
+    protected String  _doctypeSystem = null;
+
+    /**
+     * Document public identifier
+     */
+    protected String  _doctypePublic = null;
+
+    /**
+     * Holds the current tree depth.
+     */
+    protected int _depth = 0;
+
+    /**
+     * Each entry (prefix) in this hashtable points to a Stack of URIs
+     */
+    protected Hashtable _namespaces;
+
+    /** 
+     * The top of this stack contains an id of the element that last declared
+     * a namespace. Used to ensure prefix/uri map scopes are closed correctly
+     */
+    protected Stack _nodeStack;
+
+    /** 
+     * The top of this stack is the prefix that was last mapped to an URI
+     */
+    protected Stack _prefixStack;
+
+    /**
+     * Contains all elements that should be output as CDATA sections.
+     */
+    protected Hashtable _cdata = null;
+
+    /**
+     * The top of this stack contains the element id of the last element whose
+     * contents should be output as CDATA sections.
+     */
+    protected Stack _cdataStack;
+
+    /**
+     * Set to true when a CDATA section is being output.
+     */
+    protected boolean _cdataTagOpen = false;
+
+    /**
+     * Set to true when a start tag is being output.
+     */
+    protected boolean _startTagOpen  = false;
+ 
+    /**
+     * Set to false after processing first element.
+     */
+    protected boolean _firstElement = true;
+
+    /**
+     * Initialize global variables
+     */
+    protected void initCDATA() {
+	// CDATA stack
+	_cdataStack = new Stack();
+	_cdataStack.push(new Integer(-1)); 	// push dummy value
+    }
+
+    protected void initNamespaces() {
+	// Namespaces
+	_namespaces = new Hashtable();
+	_nodeStack = new Stack();
+	_prefixStack = new Stack();
+
+	// Define the default namespace (initially maps to "" uri)
+	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;
+    }
+
+    /**
+     * Set the output document system/public identifiers
+     */
+    public void setDoctype(String system, String pub) {
+        _doctypeSystem = system;
+        _doctypePublic = pub;
+
+    }
+
+    public void setCdataElements(Hashtable elements) { 
+	_cdata = elements;
+    }
+
+ 
+   /**
+     * 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".
+     */ 
+    protected static String patchName(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;
+    }
+
+    /**
+     * Declare a prefix to point to a namespace URI
+     */
+    protected boolean pushNamespace(String prefix, String uri) {
+	// Prefixes "xml" and "xmlns" cannot be redefined
+	if (prefix.startsWith(XML_PREFIX)) {
+	    return false;
+	}
+	
+	Stack stack;
+	// Get the stack that contains URIs for the specified prefix
+	if ((stack = (Stack)_namespaces.get(prefix)) == null) {
+	    _namespaces.put(prefix, stack = new Stack());
+	}
+
+	if (!stack.empty() && uri.equals(stack.peek())) {
+	    return false;
+	}
+
+	stack.push(uri);
+	_prefixStack.push(prefix);
+	_nodeStack.push(new Integer(_depth));
+	return true;
+    }
+
+    /**
+     * Undeclare the namespace that is currently pointed to by a given prefix
+     */
+    protected boolean popNamespace(String prefix) {
+	// Prefixes "xml" and "xmlns" cannot be redefined
+	if (prefix.startsWith(XML_PREFIX)) {
+	    return false;
+	}
+
+	Stack stack;
+	if ((stack = (Stack)_namespaces.get(prefix)) != null) {
+	    stack.pop();
+	    return true;
+	}
+	return false;
+    }
+
+    /**
+     * Pop all namespace definitions that were delcared by the current element
+     */
+    protected void popNamespaces() {
+	while (true) {
+	    if (_nodeStack.isEmpty()) return;
+	    Integer i = (Integer)(_nodeStack.peek());
+	    if (i.intValue() != _depth) return;
+	    _nodeStack.pop();
+	    popNamespace((String)_prefixStack.pop());
+	}
+    }
+
+    /**
+     * Use a namespace prefix to lookup a namespace URI
+     */
+    protected String lookupNamespace(String prefix) {
+        final Stack stack = (Stack)_namespaces.get(prefix);
+        return stack != null && !stack.isEmpty() ? (String)stack.peek() : null;
+    }
+
+    /**
+     * Returns the local name of a qualified name. If the name has 
+     * no prefix, then it works as the identity (SAX2).
+     */
+    protected static String getLocalName(String qname) {
+        final int col = qname.lastIndexOf(':');
+        return (col > 0) ? qname.substring(col + 1) : qname;
+    }
+
+    /**
+     * Returns the URI of an element or attribute. Note that default namespaces
+     * do not apply directly to attributes.
+     */
+    protected 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,
+                                          qname.substring(0, col));
+            }
+        }
+        return uri;
+    }
+
+    // -- Temporary
+    public void namespace(String prefix, String uri) throws TransletException { }
+    public void setType(int type) { }
+    public void setIndent(boolean indent) { }
+    public void omitHeader(boolean value) { }
+    public boolean setEscaping(boolean escape) throws TransletException { return true; }
+    public void setMediaType(String mediaType) { }
+    public void setStandalone(String standalone) { }
+    public void setVersion(String version) { }
+    public void close() { }
+
+}
diff --git a/src/org/apache/xalan/xsltc/runtime/output/SAXHTMLOutput.java b/src/org/apache/xalan/xsltc/runtime/output/SAXHTMLOutput.java
new file mode 100644
index 0000000..77e4355
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/runtime/output/SAXHTMLOutput.java
@@ -0,0 +1,204 @@
+/*
+ * @(#)$Id$
+ *
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF
+ * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 2001, Sun
+ * Microsystems., http://www.sun.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * @author Santiago Pericas-Geertsen
+ * @author G. Todd Miller 
+ *
+ */
+
+package org.apache.xalan.xsltc.runtime.output;
+
+import java.util.Stack;
+import java.io.IOException;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ext.LexicalHandler;
+import org.apache.xalan.xsltc.TransletException;
+import org.apache.xalan.xsltc.runtime.BasisLibrary;
+import org.apache.xalan.xsltc.runtime.AttributeList;
+
+public class SAXHTMLOutput extends SAXOutput { 
+
+    public SAXHTMLOutput(ContentHandler handler, String encoding) 
+	throws IOException 
+    {
+	super(handler, encoding);
+    }
+
+    public SAXHTMLOutput(ContentHandler handler, LexicalHandler lex, 
+	String encoding) throws IOException
+    {
+	super(handler, lex, encoding);
+    }
+   
+    public void endDocument() throws TransletException {
+        try {
+            // Close any open start tag
+            if (_startTagOpen) {
+		closeStartTag();
+	    }
+
+            // Close output document
+            _saxHandler.endDocument();
+        } 
+	catch (SAXException e) {
+            throw new TransletException(e);
+        }
+    }
+
+    /**
+     * 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 {
+    	try {
+	    // Close any open start tag
+            if (_startTagOpen) {
+		closeStartTag();
+	    }
+
+            // Handle document type declaration (for first element only)
+            if (_lexHandler != null) {
+                if ((_doctypeSystem != null) || (_doctypePublic != null))
+                    _lexHandler.startDTD(elementName,
+                             _doctypePublic,_doctypeSystem);
+                _lexHandler = null;
+            }
+
+            _depth++;
+            _elementName = elementName;
+            _attributes.clear();
+            _startTagOpen = true;
+        } 
+	catch (SAXException e) {
+            throw new TransletException(e);
+        }
+    }
+
+    /**
+     * End an element or CDATA section in the output document
+     */
+    public void endElement(String elementName) throws TransletException {
+        try {
+            // Close any open element
+            if (_startTagOpen) {
+		closeStartTag();
+	    }
+            _saxHandler.endElement(EMPTYSTRING, EMPTYSTRING, elementName);
+        } 
+	catch (SAXException e) {
+            throw new TransletException(e);
+        }
+
+    }
+
+    public void attribute(String name, final String value) 
+	throws TransletException
+    {
+	final String patchedName = patchName(name);
+	final String localName = getLocalName(patchedName);
+	final int index = _attributes.getIndex(name); 
+
+	if (!_startTagOpen) {
+            BasisLibrary.runTimeError(BasisLibrary.STRAY_ATTRIBUTE_ERR,name);
+        }
+
+        if (index >= 0) {
+            _attributes.setAttribute(index, EMPTYSTRING, EMPTYSTRING,
+                    name, "CDATA", value);
+        }
+        else {
+            _attributes.addAttribute(EMPTYSTRING, EMPTYSTRING,
+                name, "CDATA", value);
+        }
+    }
+
+    /**
+    * Send characters to the output document
+    */
+    public void characters(char[] ch, int off, int len)
+        throws TransletException 
+    {
+	try {
+            // Close any open start tag
+            if (_startTagOpen) closeStartTag();
+            _saxHandler.characters(ch, off, len);
+        }
+        catch (SAXException e) {
+            throw new TransletException(e);
+        }
+    }
+
+    /**
+     * This method is called when all the data needed for a call to the
+     * SAX handler's startElement() method has been gathered.
+     */
+    protected void closeStartTag() throws TransletException {
+        try {
+            _startTagOpen = false;
+
+            // Now is time to send the startElement event
+            _saxHandler.startElement(null, _elementName, _elementName, 
+		_attributes);
+        }
+        catch (SAXException e) {
+            throw new TransletException(e);
+        }
+    }
+}
diff --git a/src/org/apache/xalan/xsltc/runtime/output/SAXOutput.java b/src/org/apache/xalan/xsltc/runtime/output/SAXOutput.java
new file mode 100644
index 0000000..f324812
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/runtime/output/SAXOutput.java
@@ -0,0 +1,140 @@
+/*
+ * @(#)$Id$
+ *
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF
+ * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 2001, Sun
+ * Microsystems., http://www.sun.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * @author Santiago Pericas-Geertsen
+ * @author G. Todd Miller 
+ *
+ */
+
+package org.apache.xalan.xsltc.runtime.output;
+
+import java.util.Stack;
+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.TransletException;
+import org.apache.xalan.xsltc.runtime.Constants;
+
+abstract class SAXOutput extends OutputBase implements Constants { 
+
+    protected ContentHandler _saxHandler;
+    protected LexicalHandler _lexHandler = null;
+    protected AttributesImpl _attributes = new AttributesImpl();
+    protected String	     _elementName = null;
+    protected String         _encoding = null; 
+
+    public SAXOutput(ContentHandler handler, String encoding) {
+	_saxHandler = handler;
+	_encoding = encoding;	
+    } 
+
+    public SAXOutput(ContentHandler hdler, LexicalHandler lex, String encoding) {
+	_saxHandler = hdler;
+	_lexHandler = lex;
+	_encoding = encoding;
+    }
+
+    public void startDocument() throws TransletException {
+	try {
+	    _saxHandler.startDocument();
+	} 
+	catch (SAXException e) {
+	    throw new TransletException(e);
+	}
+    }
+
+    public void characters(String  characters)
+       throws TransletException
+    {
+	characters(characters.toCharArray(), 0, characters.length());	
+    }
+
+    public void comment(String comment) throws TransletException {
+	try {
+	    // Close any open element before emitting comment
+            if (_startTagOpen) {
+		closeStartTag();
+	    }
+	    else if (_cdataTagOpen) {
+		closeCDATA();
+	    }
+
+	    // Ignore if a lexical handler has not been set
+	    if (_lexHandler != null) {
+		_lexHandler.comment(comment.toCharArray(), 0, comment.length());
+	    }
+	}
+	catch (SAXException e) {
+	    throw new TransletException(e);
+	}
+    }
+
+    public void processingInstruction(String target, String data) 
+	throws TransletException 
+    {
+        // Redefined in SAXXMLOutput
+    }
+
+    protected void closeStartTag() throws TransletException {
+    }
+
+    protected void closeCDATA() throws SAXException {
+        // Redefined in SAXXMLOutput
+    }
+}
diff --git a/src/org/apache/xalan/xsltc/runtime/output/SAXTextOutput.java b/src/org/apache/xalan/xsltc/runtime/output/SAXTextOutput.java
new file mode 100644
index 0000000..28353cc
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/runtime/output/SAXTextOutput.java
@@ -0,0 +1,148 @@
+/*
+ * @(#)$Id$
+ *
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF
+ * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 2001, Sun
+ * Microsystems., http://www.sun.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * @author Santiago Pericas-Geertsen
+ *
+ */
+
+package org.apache.xalan.xsltc.runtime.output;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.SAXException;
+
+import org.apache.xalan.xsltc.TransletException;
+
+public class SAXTextOutput extends SAXOutput {
+
+    public SAXTextOutput(ContentHandler handler, String encoding) 
+    {
+    	super(handler, encoding);
+    }
+
+    public SAXTextOutput(ContentHandler handler, LexicalHandler lex, 
+        String encoding)
+    {
+        super(handler, lex, encoding);
+    }
+
+    public void startDocument() throws TransletException { 
+	try {
+	    _saxHandler.startDocument();
+	}
+	catch (SAXException e) {
+	    throw new TransletException(e);
+	}
+    }
+
+    public void endDocument() throws TransletException { 
+	try {
+	    _saxHandler.endDocument();
+	}
+	catch (SAXException e) {
+	    throw new TransletException(e);
+	}
+    }
+
+    public void startElement(String elementName) 
+	throws TransletException 
+    {
+    }
+
+    public void endElement(String elementName) 
+	throws TransletException 
+    {
+    }
+
+    public void characters(String characters) 
+	throws TransletException 
+    { 
+	try {
+	    _saxHandler.characters(characters.toCharArray(), 0, 
+		characters.length());
+	}
+	catch (SAXException e) {
+	    throw new TransletException(e);
+	}
+    }
+
+    public void characters(char[] characters, int offset, int length)
+	throws TransletException 
+    { 
+	try {
+	    _saxHandler.characters(characters, offset, length);
+	}
+	catch (SAXException e) {
+	    throw new TransletException(e);
+	}
+    }
+
+    public void comment(String comment) throws TransletException {
+    }
+
+    public void attribute(String name, String value) 
+	throws TransletException 
+    {
+    }
+
+    public void processingInstruction(String target, String data) 
+	throws TransletException
+    {
+    }
+}
+
diff --git a/src/org/apache/xalan/xsltc/runtime/output/SAXXMLOutput.java b/src/org/apache/xalan/xsltc/runtime/output/SAXXMLOutput.java
new file mode 100644
index 0000000..55ec226
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/runtime/output/SAXXMLOutput.java
@@ -0,0 +1,366 @@
+/*
+ * @(#)$Id$
+ *
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF
+ * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 2001, Sun
+ * Microsystems., http://www.sun.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * @author Santiago Pericas-Geertsen
+ * @author G. Todd Miller 
+ *
+ */
+
+package org.apache.xalan.xsltc.runtime.output;
+
+import java.util.Stack;
+import java.io.IOException;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ext.LexicalHandler;
+import org.apache.xalan.xsltc.TransletException;
+import org.apache.xalan.xsltc.runtime.Hashtable;
+import org.xml.sax.SAXException;
+import org.apache.xalan.xsltc.runtime.BasisLibrary;
+
+public class SAXXMLOutput extends SAXOutput {
+
+    private static final char[] BEGCDATA = "<![CDATA[".toCharArray();
+    private static final char[] ENDCDATA = "]]>".toCharArray();
+    private static final char[] CNTCDATA = "]]]]><![CDATA[>".toCharArray();
+
+    public SAXXMLOutput(ContentHandler handler, String encoding) 
+	throws IOException 
+    {
+    	super(handler, encoding);
+	initCDATA();
+	initNamespaces();
+    }
+
+    public SAXXMLOutput(ContentHandler handler, LexicalHandler lex, 
+        String encoding) throws IOException
+    {
+        super(handler, lex, encoding);
+	initCDATA();
+	initNamespaces();
+    }
+
+    public void endDocument() throws TransletException {
+	try {
+	    // Close any open start tag
+            if (_startTagOpen) {
+		closeStartTag();
+	    }
+            else if (_cdataTagOpen) {
+		closeCDATA();
+	    }
+
+            // Close output document
+            _saxHandler.endDocument();
+        } 
+	catch (SAXException e) {
+            throw new TransletException(e);
+        }
+    }
+
+    /**
+     * 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 {
+// System.out.println("SAXXMLOutput.startElement name = " + elementName);
+	try {
+            // Close any open start tag
+            if (_startTagOpen) {
+		closeStartTag();
+	    }
+            else if (_cdataTagOpen) {
+		closeCDATA();
+	    }
+
+            // Handle document type declaration (for first element only)
+            if (_firstElement) {
+                if (_doctypeSystem != null) {
+                    _lexHandler.startDTD(elementName, _doctypePublic,
+			_doctypeSystem);
+		}
+                _firstElement = false;
+            }
+
+            _depth++;
+            _elementName = elementName;
+            _attributes.clear();
+            _startTagOpen = true;
+	}
+        catch (SAXException e) {
+            throw new TransletException(e);
+        }
+    }
+
+    /**
+     * Put an attribute and its value in the start tag of an element.
+     * Signal an exception if this is attempted done outside a start tag.
+     */
+    public void attribute(String name, final String value)
+        throws TransletException 
+    {
+	final String patchedName = patchName(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);
+
+        if (!_startTagOpen) {
+            BasisLibrary.runTimeError(BasisLibrary.STRAY_ATTRIBUTE_ERR,
+                patchedName);
+        }
+
+	if (index >= 0) {       // Duplicate attribute?
+	    _attributes.setAttribute(index, uri, localName,
+		patchedName, "CDATA", value);
+	}
+	else {
+	    _attributes.addAttribute(uri, localName, patchedName,
+		"CDATA", value);
+        }
+    }
+
+    public void characters(char[] ch, int off, int len)
+        throws TransletException 
+    {
+// System.out.println("SAXXMLOutput.characters ch = " + new String(ch, off, len));
+
+	try {
+            // Close any open start tag
+            if (_startTagOpen) {
+		closeStartTag();
+	    }
+
+            Integer I = (Integer)_cdataStack.peek();
+            if ((I.intValue() == _depth) && (!_cdataTagOpen)) {
+                startCDATA(ch, off, len);
+            }
+            else {
+                _saxHandler.characters(ch, off, len);
+            }
+	}
+        catch (SAXException e) {
+            throw new TransletException(e);
+        }
+    }
+
+    public void endElement(String elementName) throws TransletException {
+// System.out.println("SAXXMLOutput.endElement name = " + elementName);
+        try {
+            // Close any open element
+            if (_startTagOpen) {
+		closeStartTag();
+	    }
+            else if (_cdataTagOpen) {
+		closeCDATA();
+	    }
+
+            _saxHandler.endElement(getNamespaceURI(elementName, true),
+                getLocalName(elementName), elementName);
+
+            popNamespaces();
+            if (((Integer)_cdataStack.peek()).intValue() == _depth){
+                _cdataStack.pop();
+	    }
+            _depth--;
+
+    	} 
+	catch (SAXException e) {
+            throw new TransletException(e);
+    	}
+    }
+
+    /**
+     * Send a namespace declaration in the output document. The namespace
+     * declaration will not be include if the namespace is already in scope
+     * with the same prefix.
+     */
+    public void namespace(final String prefix, final String uri)
+        throws TransletException 
+    {
+	if (_startTagOpen) {
+	    pushNamespace(prefix, uri);
+	}
+	else {
+	    if ((prefix == EMPTYSTRING) && (uri == EMPTYSTRING)) return;
+	    BasisLibrary.runTimeError(BasisLibrary.STRAY_NAMESPACE_ERR,
+				      prefix, uri);
+	}
+    }
+
+    /**
+     * Send a processing instruction to the output document
+     */
+    public void processingInstruction(String target, String data)
+        throws TransletException {
+        try {
+            // Close any open element
+            if (_startTagOpen) {
+		closeStartTag();
+	    }
+            else if (_cdataTagOpen) {
+		closeCDATA();
+	    }
+
+            // Pass the processing instruction to the SAX handler
+            _saxHandler.processingInstruction(target, data);
+        }
+        catch (SAXException e) {
+            throw new TransletException(e);
+        }
+    }
+
+    /**
+     * Declare a prefix to point to a namespace URI. Inform SAX handler
+     * if this is a new prefix mapping.
+     */
+    protected boolean pushNamespace(String prefix, String uri) {
+	try {
+	    if (super.pushNamespace(prefix, uri)) {
+		_saxHandler.startPrefixMapping(prefix, uri);
+		return true;
+	    }
+	} 
+	catch (SAXException e) {
+	    // falls through
+	}
+	return false;
+    }
+
+    /**
+     * Undeclare the namespace that is currently pointed to by a given 
+     * prefix. Inform SAX handler if prefix was previously mapped.
+     */
+    protected boolean popNamespace(String prefix) {
+	try {
+	    if (super.popNamespace(prefix)) {
+		_saxHandler.endPrefixMapping(prefix);
+		return true;
+	    }
+	}
+	catch (SAXException e) {
+	    // falls through
+	}
+	return false;
+    }
+
+    /**
+     * This method is called when all the data needed for a call to the
+     * SAX handler's startElement() method has been gathered.
+     */
+    protected void closeStartTag() throws TransletException {
+        try {
+            _startTagOpen = false;
+
+	    final String localName = getLocalName(_elementName);
+	    final String uri = getNamespaceURI(_elementName, true);
+
+            // Now is time to send the startElement event
+            _saxHandler.startElement(uri, localName, _elementName, 
+		_attributes);
+
+	    if (_cdata != null) {
+		final StringBuffer expandedName = (uri == EMPTYSTRING) ? 
+		    new StringBuffer(_elementName) :
+		    new StringBuffer(uri).append(':').append(localName);
+
+		if (_cdata.containsKey(expandedName.toString())) {
+		    _cdataStack.push(new Integer(_depth));
+		}
+	    }
+        }
+        catch (SAXException e) {
+            throw new TransletException(e);
+        }
+    }
+
+    protected void closeCDATA() throws SAXException {
+        // Output closing bracket - "]]>"
+        _saxHandler.characters(ENDCDATA, 0, ENDCDATA.length);
+        _cdataTagOpen = false;
+    }
+
+    /**
+     * Utility method - pass a whole charactes as CDATA to SAX handler
+     */
+    private void startCDATA(char[] ch, int off, int len) throws SAXException {
+        final int limit = off + len;
+        int offset = off;
+
+        // Output start bracket - "<![CDATA["
+        _saxHandler.characters(BEGCDATA, 0, BEGCDATA.length);
+
+        // Detect any occurence of "]]>" in the character array
+        for (int i = offset; i < limit - 2; i++) {
+            if (ch[i] == ']' && ch[i + 1] == ']' && ch[i + 2] == '>') {
+                _saxHandler.characters(ch, offset, i - offset);
+                _saxHandler.characters(CNTCDATA, 0, CNTCDATA.length);
+                offset = i+3;
+                i += 2; 	// Skip next chars ']' and '>'
+            }
+        }
+
+        // Output the remaining characters
+        if (offset < limit) {
+	    _saxHandler.characters(ch, offset, limit - offset);
+	}	    
+        _cdataTagOpen = true;
+    }
+}
+
diff --git a/src/org/apache/xalan/xsltc/runtime/output/StreamHTMLOutput.java b/src/org/apache/xalan/xsltc/runtime/output/StreamHTMLOutput.java
new file mode 100644
index 0000000..c0439f9
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/runtime/output/StreamHTMLOutput.java
@@ -0,0 +1,419 @@
+/*
+ * @(#)$Id$
+ *
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF
+ * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 2001, Sun
+ * Microsystems., http://www.sun.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * @author Santiago Pericas-Geertsen
+ * @author G. Todd Miller 
+ *
+ */
+
+package org.apache.xalan.xsltc.runtime.output;
+
+import java.util.Vector;
+
+import java.io.Writer;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.xalan.xsltc.*;
+import org.apache.xalan.xsltc.runtime.*;
+import org.apache.xalan.xsltc.runtime.Hashtable;
+
+public class StreamHTMLOutput extends StreamOutput {
+
+    private static final String HREF_STR = "href";
+    private static final String CITE_STR = "cite";
+    private static final String SRC_STR  = "src";
+
+    private static final Hashtable _emptyElements = new Hashtable();
+    private static final String[] tags = { "area", "base", "basefont", "br",
+					   "col", "frame", "hr", "img", "input",
+					   "isindex", "link", "meta", "param" };
+    static {
+        for (int i = 0; i < tags.length; i++) {
+            _emptyElements.put(tags[i], "");
+	}
+    }
+
+    private boolean _headTagOpen = false;
+    private boolean _inStyleScript = false;
+    private String  _mediaType     = "text/html";
+
+    public StreamHTMLOutput(StreamOutput output) {
+	super(output);
+	setIndent(true);  // default for HTML
+// System.out.println("StreamHTMLOutput.<init>");
+    }
+
+    public StreamHTMLOutput(Writer writer, String encoding) {
+	super(writer, encoding);
+// System.out.println("StreamHTMLOutput.<init>");
+    }
+
+    public StreamHTMLOutput(OutputStream out, String encoding) 
+	throws IOException
+    {
+	super(out, encoding);
+// System.out.println("StreamHTMLOutput.<init>");
+    }
+
+    public void startDocument() throws TransletException { 
+	// empty
+    }
+
+    public void endDocument() throws TransletException { 
+	// Finally, output buffer to writer
+	outputBuffer();
+    }
+
+    public void startElement(String elementName) throws TransletException { 
+	if (_startTagOpen) {
+	    closeStartTag();
+	}
+
+	// Handle document type declaration (for first element only)
+	if (_firstElement) {
+	    if (_doctypeSystem != null || _doctypePublic != null) {
+		appendDTD(elementName);
+	    }
+	    _firstElement = false;
+	}
+
+	if (_indent) {
+	    if (!_emptyElements.containsKey(elementName.toLowerCase())) {
+		indent(_lineFeedNextStartTag);
+		_lineFeedNextStartTag = true;
+		_indentNextEndTag = false;
+	    }
+	    _indentLevel++;
+	}
+
+	_buffer.append('<').append(elementName);
+	_startTagOpen = true;
+	_indentNextEndTag = false;
+
+	if (elementName.equalsIgnoreCase("head")) {
+	    _headTagOpen = true;
+	}
+	else if (elementName.equalsIgnoreCase("style") || 
+		 elementName.equalsIgnoreCase("script")) 
+	{
+	    _inStyleScript = true;
+	}
+    }
+
+    public void endElement(String elementName) 
+	throws TransletException 
+    { 
+	if (_inStyleScript && 
+	    (elementName.equalsIgnoreCase("style") || 
+	     elementName.equalsIgnoreCase("script"))) 
+	{
+	    _inStyleScript = false;
+	}
+
+	if (_startTagOpen) {
+	    appendAttributes();
+	    if (_emptyElements.containsKey(elementName.toLowerCase())) {
+		_buffer.append('>');
+	    }
+	    else {
+		closeStartTag();
+		_buffer.append("</").append(elementName).append('>');
+	    }
+	    _startTagOpen = false;
+
+	    if (_indent) {
+		_indentLevel--;
+		_indentNextEndTag = true;
+	    }
+	}
+	else {
+	    if (_indent) {
+		_indentLevel--;
+
+		if (_indentNextEndTag) {
+		    indent(_indentNextEndTag);
+		    _indentNextEndTag = true;
+		    _lineFeedNextStartTag = true;
+		}
+	    }
+	    _buffer.append("</").append(elementName).append('>');
+	    _indentNextEndTag = true;
+	}
+    }
+
+    public void characters(String characters)
+	throws TransletException 
+    { 
+	if (_startTagOpen) {
+	    closeStartTag();
+	}
+
+	if (_escaping && !_inStyleScript) {
+	    escapeCharacters(characters.toCharArray(), 0, characters.length());
+	}
+	else {
+	    _buffer.append(characters);
+	}
+    }
+
+    public void characters(char[] characters, int offset, int length)
+	throws TransletException 
+    { 
+	if (_startTagOpen) {
+	    closeStartTag();
+	}
+
+	if (_escaping && !_inStyleScript) {
+	    escapeCharacters(characters, offset, length);
+	}
+	else {
+	    _buffer.append(characters, offset, length);
+	}
+    }
+
+    public void attribute(String name, String value)
+	throws TransletException 
+    { 
+// System.out.println("attribute = " + name + " " + value);
+	if (_startTagOpen) {
+	    int k;
+	    Attribute attr;
+
+	    if (name.equalsIgnoreCase(HREF_STR) || 
+		name.equalsIgnoreCase(SRC_STR)  || 
+		name.equals(CITE_STR)) 
+	    {
+		attr = new Attribute(name, escapeURL(value));
+	    }
+	    else {
+		attr = new Attribute(name, escapeNonURL(value));
+	    }
+
+	    if ((k = _attributes.indexOf(attr)) >= 0) {
+		_attributes.setElementAt(attr, k);
+	    }
+	    else {
+		_attributes.add(attr);
+	    }
+	}
+    }
+
+    public void comment(String comment) throws TransletException { 
+	if (_startTagOpen) {
+	    closeStartTag();
+	}
+	appendComment(comment);
+    }
+
+    public void processingInstruction(String target, String data)
+	throws TransletException 
+    { 
+	if (_startTagOpen) {
+	    closeStartTag();
+	}
+
+	// Handle document type declaration 
+	if (_firstElement) {
+	    if (_doctypeSystem != null || _doctypePublic != null) {
+		appendDTD("html");
+	    }
+	    _firstElement = false;
+	}
+
+	// A PI in HTML ends with ">" instead of "?>"
+	_buffer.append("<?").append(target).append(' ')
+	    .append(data).append('>');
+    }
+
+    public boolean setEscaping(boolean escape) throws TransletException 
+    { 
+	final boolean temp = _escaping;
+	_escaping = escape;
+	return temp; 
+    }
+
+    public void close() { 
+	try {
+	    _writer.close();
+	}
+	catch (Exception e) {
+	    // ignore
+	}
+    }
+
+    public void namespace(String prefix, String uri) throws TransletException 
+    { 
+	// ignore when method type is HTML
+    }
+
+    public void setCdataElements(Hashtable elements) { 
+	// ignore when method type is HTML
+    }
+
+    public void setType(int type) { 
+	// ignore: default is HTML
+    }
+
+    /**
+     * Set the output media type - only relevant for HTML output
+     */
+    public void setMediaType(String mediaType) {
+	_mediaType = mediaType;
+    }
+
+    /**
+     * Escape non ASCII characters (> u007F) as &#XXX; entities.
+     */
+    private String escapeNonURL(String base) {
+	final int length = base.length();
+	final StringBuffer result = new StringBuffer();
+
+        for (int i = 0; i < length; i++){
+	    final char ch = base.charAt(i);
+
+	    if ((ch >= '\u007F' && ch < '\u00A0') ||
+		(_is8859Encoded && ch > '\u00FF'))
+	    {
+	        result.append(CHAR_ESC_START)
+		      .append(Integer.toString((int) ch))
+		      .append(';');
+	    }
+	    else {
+	        result.append(ch); 
+	    } 
+  	}
+	return result.toString();
+    }
+
+    /**
+     * This method escapes special characters used in HTML attribute values
+     */
+    private String escapeURL(String base) {
+	final char[] chs = base.toCharArray();
+	final StringBuffer result = new StringBuffer();
+
+	final int length = chs.length;
+        for (int i = 0; i < length; i++) {
+	    final char ch = chs[i];
+
+	    if (ch <= 0x20) {
+		result.append('%').append(makeHHString(ch));
+	    } 
+	    else if (ch > '\u007F') {
+		result.append('%')
+		      .append(makeHHString((ch >> 6) | 0xC0))
+		      .append('%')
+		      .append(makeHHString((ch & 0x3F) | 0x80));
+	    }
+	    else {
+		// These chars are reserved or unsafe in URLs
+	        switch (ch) {
+		    case '\u007F' :
+		    case '\u007B' :
+		    case '\u007D' :
+		    case '\u007C' :
+		    case '\\'     :
+		    case '\t'     :
+		    case '\u005E' :
+		    case '\u007E' :
+		    case '\u005B' :
+		    case '\u005D' :
+		    case '\u0060' :
+		    case '\u0020' :
+		        result.append('%')
+		              .append(Integer.toHexString((int) ch));
+		        break;
+		    case '"':
+			result.append("%22");
+			break;
+		    default:	
+		        result.append(ch); 
+			break;
+	        }
+	    } 
+  	}
+	return result.toString();
+    }
+
+    private String makeHHString(int i) {
+	final String s = Integer.toHexString(i).toUpperCase();
+	return (s.length() == 1) ? "0" + s : s;
+    }
+
+    /**
+     * Emit HTML meta info
+     */
+    private void appendHeader() {
+	_buffer.append("<meta http-equiv=\"Content-Type\" content=\"")
+	       .append(_mediaType).append("; charset=")
+	       .append(_encoding).append("\">");
+    }
+
+    protected void closeStartTag() throws TransletException {
+	super.closeStartTag();
+
+	// Insert <META> tag directly after <HEAD> element in HTML output
+	if (_headTagOpen) {
+	    appendHeader();
+	    _headTagOpen = false;
+	}
+    } 
+}
diff --git a/src/org/apache/xalan/xsltc/runtime/output/StreamOutput.java b/src/org/apache/xalan/xsltc/runtime/output/StreamOutput.java
new file mode 100644
index 0000000..fc1739f
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/runtime/output/StreamOutput.java
@@ -0,0 +1,346 @@
+/*
+ * @(#)$Id$
+ *
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF
+ * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 2001, Sun
+ * Microsystems., http://www.sun.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * @author Santiago Pericas-Geertsen
+ * @author G. Todd Miller 
+ *
+ */
+
+package org.apache.xalan.xsltc.runtime.output;
+
+import java.io.Writer;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import java.util.Vector;
+
+import org.apache.xalan.xsltc.TransletException;
+
+abstract class StreamOutput extends OutputBase {
+
+    protected static final String AMP      = "&amp;";
+    protected static final String LT       = "&lt;";
+    protected static final String GT       = "&gt;";
+    protected static final String CRLF     = "&#xA;";
+    protected static final String QUOTE    = "&quot;";
+    protected static final String NBSP     = "&nbsp;";
+
+    protected static final String CHAR_ESC_START  = "&#";
+
+    protected static final char[] INDENT = "                    ".toCharArray();
+    protected static final int MAX_INDENT_LEVEL = (INDENT.length >> 1);
+    protected static final int MAX_INDENT       = INDENT.length;
+
+    protected static final int BUFFER_SIZE = 64 * 1024;
+    protected static final int OUTPUT_BUFFER_SIZE = 4 * 1024;
+
+    protected Writer  _writer;
+    protected StringBuffer _buffer;
+
+    protected boolean _is8859Encoded = false;
+    protected boolean _indent     = false;
+    protected boolean _omitHeader = false;
+    protected String  _standalone = null;
+    protected String  _version    = "1.0";
+
+    protected boolean _lineFeedNextStartTag = false;
+    protected boolean _linefeedNextEndTag   = false;
+    protected boolean _indentNextEndTag     = false;
+    protected int     _indentLevel          = 0;
+
+    protected boolean _escaping     = true;
+    protected String  _encoding     = "UTF-8";
+
+    protected int     _indentNumber = 2;
+
+    // protected HashSet _attributes = new HashSet();
+    protected Vector _attributes = new Vector();
+
+    static class Attribute {
+	public String name, value;
+
+	Attribute(String name, String value) {
+	    this.name = name; 
+	    this.value = value;
+	}
+
+	public int hashCode() {
+	    return name.hashCode();
+	}
+
+	public boolean equals(Object obj) {
+	    try {
+		return name.equalsIgnoreCase(((Attribute) obj).name);
+	    }
+	    catch (ClassCastException e) {
+		return false;
+	    }
+	}
+    }
+
+    protected StreamOutput(StreamOutput output) {
+	_writer = output._writer;
+	_encoding = output._encoding;
+	_is8859Encoded = output._is8859Encoded;
+	_buffer = output._buffer;
+	_indentNumber = output._indentNumber;
+    }
+
+    protected StreamOutput(Writer writer, String encoding) {
+	_writer = writer;
+	_encoding = encoding;
+	_is8859Encoded = encoding.equalsIgnoreCase("iso-8859-1");
+	_buffer = new StringBuffer(BUFFER_SIZE);
+    }
+
+    protected StreamOutput(OutputStream out, String encoding) 
+	throws IOException
+    {
+	try {
+	    _writer = new OutputStreamWriter(out, _encoding = encoding);
+	    _is8859Encoded = encoding.equalsIgnoreCase("iso-8859-1");
+	}
+	catch (UnsupportedEncodingException e) {
+	    _writer = new OutputStreamWriter(out, _encoding = "utf-8");
+	}
+	_buffer = new StringBuffer(BUFFER_SIZE);
+    }
+
+    public void setIndentNumber(int value) {
+	_indentNumber = value;
+    }
+
+    /**
+     * Set the output document system/public identifiers
+     */
+    public void setDoctype(String system, String pub) {
+	_doctypeSystem = system;
+	_doctypePublic = pub;
+    }
+
+    public void setIndent(boolean indent) { 
+// System.out.println("StreamOutput.setIndent() indent = " + indent);
+	_indent = indent;
+    }
+
+    public void omitHeader(boolean value) {
+        _omitHeader = value;
+    }
+
+    public void setStandalone(String standalone) {
+	_standalone = standalone;
+    }
+
+    public void setVersion(String version) { 
+	_version = version;
+    }
+
+    protected void outputBuffer() {
+	try {
+	    int n = 0;
+	    final int length = _buffer.length();
+	    final String output = _buffer.toString();
+
+	    // Output buffer in chunks of OUTPUT_BUFFER_SIZE 
+	    if (length > OUTPUT_BUFFER_SIZE) {
+		do {
+		    _writer.write(output, n, OUTPUT_BUFFER_SIZE);
+		    n += OUTPUT_BUFFER_SIZE;
+		} while (n + OUTPUT_BUFFER_SIZE < length);
+	    }
+	    _writer.write(output, n, length - n);
+	    _writer.flush();
+	}
+	catch (IOException e) {
+	    // ignore
+	}
+    }
+
+    protected void appendDTD(String name) {
+	_buffer.append("<!DOCTYPE ").append(name);
+	if (_doctypePublic == null) {
+	    _buffer.append(" SYSTEM");
+	}
+	else {
+	    _buffer.append(" PUBLIC \"").append(_doctypePublic).append("\"");
+	}
+	if (_doctypeSystem != null) {
+	    _buffer.append(" \"").append(_doctypeSystem).append("\">\n");
+	}
+	else {
+	    _buffer.append(">\n");
+	}
+    }
+
+    /**
+     * Adds a newline in the output stream and indents to correct level
+     */
+    protected void indent(boolean linefeed) {
+        if (linefeed) {
+            _buffer.append('\n');
+	}
+
+	_buffer.append(INDENT, 0, 
+	    _indentLevel < MAX_INDENT_LEVEL ? _indentLevel * _indentNumber 
+		: MAX_INDENT);
+    }
+
+    protected void escapeCharacters(char[] ch, int off, int len) {
+	int limit = off + len;
+	int offset = off;
+
+	if (limit > ch.length) {
+	    limit = ch.length;
+	}
+
+	// Step through characters and escape all special characters
+	for (int i = off; i < limit; i++) {
+	    final char current = ch[i];
+
+	    switch (current) {
+	    case '&':
+		_buffer.append(ch, offset, i - offset);
+		_buffer.append(AMP);
+		offset = i + 1;
+		break;
+	    case '<':
+		_buffer.append(ch, offset, i - offset);
+		_buffer.append(LT);
+		offset = i + 1;
+		break;
+	    case '>':
+		_buffer.append(ch, offset, i - offset);
+		_buffer.append(GT);
+		offset = i + 1;
+		break;
+	    case '\u00a0':
+		_buffer.append(ch, offset, i - offset);
+		_buffer.append(NBSP);
+		offset = i + 1;
+		break;
+	    default:
+		if ((current >= '\u007F' && current < '\u00A0') ||
+		    (_is8859Encoded && current > '\u00FF'))
+		{
+		    _buffer.append(ch, offset, i - offset);
+		    _buffer.append(CHAR_ESC_START);
+		    _buffer.append(Integer.toString((int)ch[i]));
+		    _buffer.append(';');
+		    offset = i + 1;
+		}
+	    }
+	}
+	// Output remaining characters (that do not need escaping).
+	if (offset < limit) {
+	    _buffer.append(ch, offset, limit - offset);
+	}
+    }
+
+    protected void appendAttributes() {
+	// Append attributes to output buffer
+	if (!_attributes.isEmpty()) {
+	    int i = 0;
+	    final int length = _attributes.size();
+
+	    do {
+		final Attribute attr = (Attribute) _attributes.elementAt(i);
+		_buffer.append(' ').append(attr.name).append("=\"")
+		       .append(attr.value).append('"');
+	    } while (++i < length);
+
+	    _attributes.clear();
+	}
+    }
+
+    protected void closeStartTag() throws TransletException {
+	appendAttributes();
+	_buffer.append('>');
+	_startTagOpen = false;
+    }
+
+    /**
+     * Ensure that comments do not include the sequence "--" and
+     * that they do not end with "-".
+     */
+    protected void appendComment(String comment) 
+	throws TransletException 
+    {
+	boolean lastIsDash = false;
+	final int n = comment.length();
+
+	_buffer.append("<!--");
+	for (int i = 0; i < n; i++) {
+	    final char ch = comment.charAt(i);
+	    final boolean isDash = (ch == '-');
+
+	    if (lastIsDash && isDash) {
+		_buffer.append(" -");
+	    }
+	    else {
+		_buffer.append(ch);
+	    }
+	    lastIsDash = isDash;
+	}
+	if (lastIsDash) {
+	    _buffer.append(' ');
+	}
+	_buffer.append("-->");
+    }
+}
diff --git a/src/org/apache/xalan/xsltc/compiler/LongExpr.java b/src/org/apache/xalan/xsltc/runtime/output/StreamTextOutput.java
similarity index 63%
copy from src/org/apache/xalan/xsltc/compiler/LongExpr.java
copy to src/org/apache/xalan/xsltc/runtime/output/StreamTextOutput.java
index e650658..b15323d 100644
--- a/src/org/apache/xalan/xsltc/compiler/LongExpr.java
+++ b/src/org/apache/xalan/xsltc/runtime/output/StreamTextOutput.java
@@ -41,8 +41,8 @@
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF
+ * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
@@ -56,34 +56,70 @@
  * information on the Apache Software Foundation, please see
  * <http://www.apache.org/>.
  *
- * @author G. Todd Miller 
+ * @author Santiago Pericas-Geertsen
  *
  */
 
-package org.apache.xalan.xsltc.compiler;
+package org.apache.xalan.xsltc.runtime.output;
 
-import org.apache.xalan.xsltc.compiler.util.Type;
-import org.apache.bcel.generic.*;
-import org.apache.xalan.xsltc.compiler.util.*;
+import java.io.Writer;
+import java.io.IOException;
+import java.io.OutputStream;
 
-final class LongExpr extends Expression {
-    private final long _value;
+import org.apache.xalan.xsltc.TransletException;
 
-    public LongExpr(long value) {
-        _value = value;
+public class StreamTextOutput extends StreamOutput {
+
+    public StreamTextOutput(Writer writer, String encoding) {
+	super(writer, encoding);
     }
 
-    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
-	return _type = Type.Lng;
+    public StreamTextOutput(OutputStream out, String encoding) 
+	throws IOException
+    {
+	super(out, encoding);
     }
 
-    public String toString() {
-	return "long-expr(" + _value + ')';
+    public void startDocument() throws TransletException { 
     }
 
-    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
-	ConstantPoolGen cpg = classGen.getConstantPool();
-	InstructionList il = methodGen.getInstructionList();
-	il.append(new PUSH(cpg, _value));
+    public void endDocument() throws TransletException { 
+	outputBuffer();
+    }
+
+    public void startElement(String elementName) 
+	throws TransletException 
+    {
+    }
+
+    public void endElement(String elementName) 
+	throws TransletException 
+    {
+    }
+
+    public void characters(String characters) 
+	throws TransletException 
+    { 
+	_buffer.append(characters);
+    }
+
+    public void characters(char[] characters, int offset, int length)
+	throws TransletException 
+    { 
+	_buffer.append(characters, offset, length);
+    }
+
+    public void comment(String comment) throws TransletException {
+    }
+
+    public void attribute(String name, String value) 
+	throws TransletException 
+    {
+    }
+
+    public void processingInstruction(String target, String data) 
+	throws TransletException
+    {
     }
 }
+
diff --git a/src/org/apache/xalan/xsltc/runtime/output/StreamUnknownOutput.java b/src/org/apache/xalan/xsltc/runtime/output/StreamUnknownOutput.java
new file mode 100644
index 0000000..7e62e0a
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/runtime/output/StreamUnknownOutput.java
@@ -0,0 +1,341 @@
+/*
+ * @(#)$Id$
+ *
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF
+ * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 2001, Sun
+ * Microsystems., http://www.sun.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * @author Santiago Pericas-Geertsen
+ * @author G. Todd Miller 
+ *
+ */
+
+package org.apache.xalan.xsltc.runtime.output;
+
+import java.util.ArrayList;
+
+import java.io.Writer;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.xalan.xsltc.*;
+import org.apache.xalan.xsltc.runtime.*;
+import org.apache.xalan.xsltc.runtime.Hashtable;
+
+public class StreamUnknownOutput extends StreamOutput {
+
+    private StreamOutput _handler;
+
+    private boolean      _isHtmlOutput = false;
+    private boolean      _firstTagOpen = false;
+    private boolean      _firstElement = true;
+    private String       _firstTagPrefix, _firstTag;
+
+    private ArrayList    _attributes = null;
+    private ArrayList    _namespaces = null;
+
+    // Cache calls to output properties events
+    private String       _mediaType          = null;
+    private boolean      _callStartDocument  = false;
+    private boolean      _callSetVersion     = false;
+    private boolean      _callSetDoctype     = false;
+
+    static class Pair {
+	public String name, value;
+
+	public Pair(String name, String value) {
+	    this.name = name;
+	    this.value = value;
+	}
+    }
+
+    public StreamUnknownOutput(Writer writer, String encoding) {
+	super(writer, encoding);
+	_handler = new StreamXMLOutput(writer, encoding);
+// System.out.println("StreamUnknownOutput.<init>");
+    }
+
+    public StreamUnknownOutput(OutputStream out, String encoding) 
+	throws IOException
+    {
+	super(out, encoding);
+	_handler = new StreamXMLOutput(out, encoding);
+// System.out.println("StreamUnknownOutput.<init>");
+    }
+
+    public void startDocument() 
+	throws TransletException 
+    { 
+	_callStartDocument = true;
+    }
+
+    public void endDocument() 
+	throws TransletException 
+    { 
+	if (_firstTagOpen) {
+	    initStreamOutput();
+	}
+	else if (_callStartDocument) {
+	    _handler.startDocument();
+	}
+	_handler.endDocument();
+    }
+
+    public void startElement(String elementName) 
+	throws TransletException 
+    { 
+// System.out.println("startElement() = " + elementName);
+	if (_firstElement) {
+	    _firstElement = false;
+
+	    _firstTag = elementName;
+	    _firstTagPrefix = BasisLibrary.getPrefix(elementName);
+	    if (_firstTagPrefix == null) {
+		_firstTagPrefix = EMPTYSTRING;
+	    }
+
+	    _firstTagOpen = true;
+	    _isHtmlOutput = BasisLibrary.getLocalName(elementName)
+				        .equalsIgnoreCase("html");
+	}
+	else {
+	    if (_firstTagOpen) {
+		initStreamOutput();
+	    }
+	    _handler.startElement(elementName);
+	}
+    }
+
+    public void endElement(String elementName) 
+	throws TransletException 
+    { 
+	if (_firstTagOpen) {
+	    initStreamOutput();
+	}
+	_handler.endElement(elementName);
+    }
+
+    public void characters(String characters) 
+	throws TransletException 
+    { 
+	if (_firstTagOpen) {
+	    initStreamOutput();
+	}
+	_handler.characters(characters);
+    }
+
+    public void characters(char[] characters, int offset, int length)
+	throws TransletException 
+    { 
+	if (_firstTagOpen) {
+	    initStreamOutput();
+	}
+	_handler.characters(characters, offset, length);
+    }
+
+    public void attribute(String name, String value)
+	throws TransletException 
+    { 
+	if (_firstTagOpen) {
+	    if (_attributes == null) {
+		_attributes = new ArrayList();
+	    }
+	    _attributes.add(new Pair(name, value));
+	}
+	else {
+	    _handler.attribute(name, value);
+	}
+    }
+
+    public void namespace(String prefix, String uri)
+	throws TransletException 
+    {
+// System.out.println("namespace() = " + prefix + " " + uri);
+	if (_firstTagOpen) {
+	    if (_namespaces == null) {
+		_namespaces = new ArrayList();
+	    }
+	    _namespaces.add(new Pair(prefix, uri));
+
+	    // Check if output is XHTML instead of HTML
+	    if (_firstTagPrefix.equals(prefix) && !uri.equals(EMPTYSTRING)) {
+		_isHtmlOutput = false;
+	    }
+	}
+	else {
+	    _handler.namespace(prefix, uri);
+	}
+    }
+
+    public void comment(String comment) 
+	throws TransletException 
+    { 
+	if (_firstTagOpen) {
+	    initStreamOutput();
+	}
+	_handler.comment(comment);
+    }
+
+    public void processingInstruction(String target, String data)
+	throws TransletException 
+    { 
+	if (_firstTagOpen) {
+	    initStreamOutput();
+	}
+	_handler.processingInstruction(target, data);
+    }
+
+    public void setDoctype(String system, String pub) {
+	_handler.setDoctype(system, pub);
+
+	// Cache call to setDoctype()
+	super.setDoctype(system, pub);
+	_callSetDoctype = true;
+    }
+
+    /**
+     * This method cannot be cached because default is different in 
+     * HTML and XML (we need more than a boolean).
+     */
+    public void setIndent(boolean indent) { 
+	_handler.setIndent(indent);
+    }
+
+    public void setVersion(String version) { 
+	_handler.setVersion(version);
+
+	// Cache call to setVersion()
+	super.setVersion(version);
+	_callSetVersion = true;
+    }
+
+    public void omitHeader(boolean value) {
+	_handler.omitHeader(value);
+    }
+
+    public void setStandalone(String standalone) {
+	_handler.setStandalone(standalone);
+    }
+
+    public void setMediaType(String mediaType) { 
+	_handler.setMediaType(mediaType);
+	_mediaType = mediaType;
+    }
+
+    public boolean setEscaping(boolean escape) 
+	throws TransletException 
+    { 
+	return _handler.setEscaping(escape);
+    }
+
+    public void setCdataElements(Hashtable elements) { 
+	_handler.setCdataElements(elements);
+    }
+
+    public void setIndentNumber(int value) {
+	_handler.setIndentNumber(value);
+    }
+
+    private void initStreamOutput() 
+	throws TransletException 
+    {
+// System.out.println("initStreamOutput() _isHtmlOutput = " + _isHtmlOutput);
+	// Create a new handler if output is HTML
+	if (_isHtmlOutput) {
+	    _handler = new StreamHTMLOutput(_handler);
+
+	    if (_callSetVersion) {
+		_handler.setVersion(_version);
+	    }
+	    if (_callSetDoctype) {
+		_handler.setDoctype(_doctypeSystem, _doctypePublic);
+	    }
+	    if (_mediaType != null) {
+		_handler.setMediaType(_mediaType);
+	    }
+	}
+
+	// Call startDocument() if necessary
+	if (_callStartDocument) {
+	    _handler.startDocument();
+	    _callStartDocument = false;
+	}
+
+	// Output first tag
+	_handler.startElement(_firstTag);
+
+	// Output namespaces of first tag
+	if (_namespaces != null) {
+	    final int n = _namespaces.size();
+	    for (int i = 0; i < n; i++) {
+		final Pair pair = (Pair) _namespaces.get(i);
+		_handler.namespace(pair.name, pair.value);
+	    }
+	}
+
+	// Output attributes of first tag
+	if (_attributes != null) {
+	    final int n = _attributes.size();
+	    for (int i = 0; i < n; i++) {
+		final Pair pair = (Pair) _attributes.get(i);
+		_handler.attribute(pair.name, pair.value);
+	    }
+	}
+
+	// Close first tag
+	_firstTagOpen = false;
+    }
+}
diff --git a/src/org/apache/xalan/xsltc/runtime/output/StreamXMLOutput.java b/src/org/apache/xalan/xsltc/runtime/output/StreamXMLOutput.java
new file mode 100644
index 0000000..fe5e02d
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/runtime/output/StreamXMLOutput.java
@@ -0,0 +1,415 @@
+/*
+ * @(#)$Id$
+ *
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF
+ * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 2001, Sun
+ * Microsystems., http://www.sun.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * @author Santiago Pericas-Geertsen
+ * @author G. Todd Miller 
+ *
+ */
+
+package org.apache.xalan.xsltc.runtime.output;
+
+import java.util.Stack;
+import java.util.Vector;
+
+import java.io.Writer;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.xalan.xsltc.*;
+import org.apache.xalan.xsltc.runtime.*;
+import org.apache.xalan.xsltc.runtime.Hashtable;
+
+public class StreamXMLOutput extends StreamOutput {
+
+    private static final String BEGCDATA = "<![CDATA[";
+    private static final String ENDCDATA = "]]>";
+    private static final String CNTCDATA = "]]]]><![CDATA[>";
+    private static final String BEGCOMM  = "<!--";
+    private static final String ENDCOMM  = "-->";
+    private static final String CDATA_ESC_START = "]]>&#";
+    private static final String CDATA_ESC_END   = ";<![CDATA[";
+
+    private String _elementName;
+
+    public StreamXMLOutput(Writer writer, String encoding) {
+	super(writer, encoding);
+	initCDATA();
+	initNamespaces();
+//System.out.println("StreamXMLOutput.<init>");
+    }
+
+    public StreamXMLOutput(OutputStream out, String encoding) 
+	throws IOException
+    {
+	super(out, encoding);
+	initCDATA();
+	initNamespaces();
+//System.out.println("StreamXMLOutput.<init>");
+    }
+
+    public void startDocument() throws TransletException { 
+//System.out.println("startDocument");
+	if (!_omitHeader) {
+	    final StringBuffer header = new StringBuffer("<?xml version=\"");
+	    header.append(_version).append("\" encoding=\"").append(_encoding);
+	    if (_standalone != null) {
+		header.append("\" standalone=\"").append(_standalone);
+	    }
+	    header.append("\"?>\n");
+
+	    // Always insert header at the beginning 
+	    _buffer.insert(0, header.toString());
+	}
+    }
+
+    public void endDocument() throws TransletException { 
+// System.out.println("endDocument");
+	// Finally, output buffer to writer
+	outputBuffer();
+    }
+
+    public void startElement(String elementName) throws TransletException { 
+// System.out.println("startElement = " + elementName);
+	if (_startTagOpen) {
+	    closeStartTag();
+	}
+	else if (_cdataTagOpen) {
+	    closeCDATA();
+	}
+
+	// Handle document type declaration (for first element only)
+	if (_firstElement) {
+	    if (_doctypeSystem != null) {
+		appendDTD(elementName);
+	    }
+	    _firstElement = false;
+	}
+
+	if (_indent) {
+	    indent(_lineFeedNextStartTag);
+	    _lineFeedNextStartTag = true;
+	    _indentNextEndTag = false;
+	    _indentLevel++;
+	}
+
+	_buffer.append('<').append(elementName);
+
+	_depth++;
+	_startTagOpen = true;
+	_elementName = elementName;
+    }
+
+    public void endElement(String elementName) throws TransletException { 
+// System.out.println("endElement = " + elementName);
+	if (_cdataTagOpen) {
+	    closeCDATA();
+	}
+
+	if (_startTagOpen) {
+	    appendAttributes();
+	    _buffer.append("/>");
+	    _startTagOpen = false;
+
+	    if (_indent) {
+		_indentLevel--;
+		_indentNextEndTag = true;
+	    }
+	}
+	else {
+	    if (_indent) {
+		_indentLevel--;
+
+		if (_indentNextEndTag) {
+		    indent(_indentNextEndTag);
+		    _indentNextEndTag = true;
+		    _lineFeedNextStartTag = true;
+		}
+	    }
+	    _buffer.append("</").append(elementName).append('>');
+	    _indentNextEndTag = true;
+	}
+
+	if (((Integer) _cdataStack.peek()).intValue() == _depth) {
+	    _cdataStack.pop();
+	}
+
+	popNamespaces();
+	_depth--;
+    }
+
+    public void characters(String characters) throws TransletException { 
+// System.out.println("characters() string '" + characters + "'");
+	characters(characters.toCharArray(), 0, characters.length());
+    }
+
+    public void characters(char[] characters, int offset, int length)
+	throws TransletException 
+    {
+	if (length <= 0) return;
+
+	if (_startTagOpen) {
+	    closeStartTag();
+	}
+
+	final Integer I = (Integer) _cdataStack.peek();
+	if (I.intValue() == _depth && !_cdataTagOpen) {
+	    startCDATA(characters, offset, length);
+	} 
+	else if (_escaping) {
+	    if (_cdataTagOpen) {
+		escapeCDATA(characters, offset, length);
+	    } 
+	    else {
+		escapeCharacters(characters, offset, length);
+	    }
+	} 
+	else {
+	    _buffer.append(characters, offset, length);
+	}
+    }
+
+    public void attribute(String name, String value)
+	throws TransletException 
+    { 
+// System.out.println("attribute = " + name + " " + value);
+	if (_startTagOpen) {
+	    int k;
+	    final Attribute attr = 
+		new Attribute(patchName(name), escapeString(value));
+
+	    if ((k = _attributes.indexOf(attr)) >= 0) {
+		_attributes.setElementAt(attr, k);
+	    }
+	    else {
+		_attributes.add(attr);
+	    }
+	}
+    }
+
+    public void comment(String comment) throws TransletException { 
+	if (_startTagOpen) {
+	    closeStartTag();
+	}
+	else if (_cdataTagOpen) {
+	    closeCDATA();
+	}
+	appendComment(comment);
+    }
+
+    public void processingInstruction(String target, String data)
+	throws TransletException 
+    { 
+// System.out.println("PI target = " + target + " data = " + data);
+	if (_startTagOpen) {
+	    closeStartTag();
+	}
+	else if (_cdataTagOpen) {
+	    closeCDATA();
+	}
+
+	_buffer.append("<?").append(target).append(' ')
+	       .append(data).append("?>");
+    }
+
+    public boolean setEscaping(boolean escape) throws TransletException 
+    { 
+	final boolean temp = _escaping;
+	_escaping = escape;
+	return temp; 
+    }
+
+   public void namespace(final String prefix, final String uri)
+	throws TransletException 
+    {
+// System.out.println("namespace prefix = " + prefix + " uri = " + uri);
+	String escaped = escapeString(uri);
+	if (_startTagOpen) {
+	    if (pushNamespace(prefix, escaped)) {
+		_buffer.append(' ').append(XMLNS_PREFIX);
+		if (prefix != null && prefix != EMPTYSTRING) {
+		    _buffer.append(':').append(prefix);
+		}
+		_buffer.append("=\"").append(escaped).append('"');
+	    }
+	}
+	else if (prefix != EMPTYSTRING || uri != EMPTYSTRING) {
+	    BasisLibrary.runTimeError(BasisLibrary.STRAY_NAMESPACE_ERR,
+				      prefix, escaped);
+	}
+    }
+
+    protected void closeStartTag() throws TransletException {
+	super.closeStartTag();
+
+	if (_cdata != null) {
+	    final String localName = getLocalName(_elementName);
+	    final String uri = getNamespaceURI(_elementName, true);
+
+	    final StringBuffer expandedName = (uri == EMPTYSTRING) ? 
+		new StringBuffer(_elementName) :
+		new StringBuffer(uri).append(':').append(localName);
+
+	    if (_cdata.containsKey(expandedName.toString())) {
+		_cdataStack.push(new Integer(_depth));
+	    }
+	}
+    }
+
+    /**
+     * Utility method - pass a whole charactes as CDATA to SAX handler
+     */
+    private void startCDATA(char[] ch, int off, int len) {
+	final int limit = off + len;
+	int offset = off;
+
+	// Output start bracket - "<![CDATA["
+	_buffer.append(BEGCDATA);
+
+	// Detect any occurence of "]]>" in the character array
+	for (int i = offset; i < limit - 2; i++) {
+	    if (ch[i] == ']' && ch[i + 1] == ']' && ch[i + 2] == '>') {
+		_buffer.append(ch, offset, i - offset)
+		       .append(CNTCDATA);
+		offset = i + 3;
+		i += 2; 	// Skip next chars ']' and '>'.
+	    }
+	}
+
+	// Output the remaining characters
+	if (offset < limit) {
+	    _buffer.append(ch, offset, limit - offset);
+	}
+	_cdataTagOpen = true;
+    }
+
+    private void closeCDATA() {
+	_buffer.append(ENDCDATA);
+	_cdataTagOpen = false;
+    }
+
+    /**
+     * Utility method - escape special characters and pass to SAX handler
+     */
+    private void escapeCDATA(char[] ch, int off, int len) {
+	int offset = off;
+	int limit = off + len;
+
+	if (limit > ch.length) {
+	    limit = ch.length;
+	}
+
+	// Step through characters and escape all special characters
+	for (int i = off; i < limit; i++) {
+	    final char current = ch[i];
+
+	    if (current > '\u00ff') {
+		_buffer.append(ch, offset, i - offset)
+		       .append(CDATA_ESC_START)
+		       .append(Integer.toString((int) current))
+		       .append(CDATA_ESC_END);
+		offset = i + 1;
+	    }
+	}
+	// Output remaining characters 
+	if (offset < limit) {
+	    _buffer.append(ch, offset, limit - offset);
+	}
+    }
+
+    /**
+     * This method escapes special characters used in attribute values
+     */
+    private String escapeString(String value) {
+	final char[] ch = value.toCharArray();
+	final int limit = ch.length;
+	StringBuffer result = new StringBuffer();
+	
+	int offset = 0;
+	for (int i = 0; i < limit; i++) {
+	    switch (ch[i]) {
+	    case '&':
+		result.append(ch, offset, i - offset).append(AMP);
+		offset = i + 1;
+		break;
+	    case '"':
+		result.append(ch, offset, i - offset).append(QUOTE);
+		offset = i + 1;
+		break;
+	    case '<':
+		result.append(ch, offset, i - offset).append(LT);
+		offset = i + 1;
+		break;
+	    case '>':
+		result.append(ch, offset, i - offset).append(GT);
+		offset = i + 1;
+		break;
+	    case '\n':
+		result.append(ch, offset, i - offset).append(CRLF);
+		offset = i + 1;
+		break;
+	    }
+	}
+
+	if (offset < limit) {
+	    result.append(ch, offset, limit - offset);
+	}
+	return result.toString();
+    }
+}
diff --git a/src/org/apache/xalan/xsltc/runtime/output/TransletOutputHandlerFactory.java b/src/org/apache/xalan/xsltc/runtime/output/TransletOutputHandlerFactory.java
new file mode 100644
index 0000000..ad021fd
--- /dev/null
+++ b/src/org/apache/xalan/xsltc/runtime/output/TransletOutputHandlerFactory.java
@@ -0,0 +1,212 @@
+/*
+ * @(#)$Id$
+ *
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF
+ * USE, DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 2001, Sun
+ * Microsystems., http://www.sun.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * @author Santiago Pericas-Geertsen
+ *
+ */
+
+package org.apache.xalan.xsltc.runtime.output;
+
+import java.io.Writer;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ext.LexicalHandler;
+import org.apache.xalan.xsltc.runtime.*;
+import org.apache.xalan.xsltc.TransletException;
+import org.apache.xalan.xsltc.TransletOutputHandler;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.xalan.xsltc.trax.SAX2DOM;
+
+public class TransletOutputHandlerFactory {
+
+    public static final int STREAM = 0;
+    public static final int SAX    = 1;
+    public static final int DOM    = 2;
+
+    private String _encoding       = "utf-8";
+    private String _method         = null;
+    private int    _outputType     = STREAM;
+    private OutputStream _ostream  = System.out;
+    private Writer _writer         = null;
+    private Node           _node   = null;
+    private int _indentNumber      = -1;
+    private ContentHandler _handler    = null;
+    private LexicalHandler _lexHandler = null;
+
+    static public TransletOutputHandlerFactory newInstance() {
+	return new TransletOutputHandlerFactory();
+    }
+
+    public void setOutputType(int outputType) {
+	_outputType = outputType;
+    }
+
+    public void setEncoding(String encoding) {
+	if (encoding != null) {
+	    _encoding = encoding;
+	}
+    }
+
+    public void setOutputMethod(String method) {
+	_method = method;
+    }
+
+    public void setOutputStream(OutputStream ostream) {
+	_ostream = ostream;
+    }
+
+    public void setWriter(Writer writer) {
+	_writer = writer;
+    }
+
+    public void setHandler(ContentHandler handler) {
+        _handler = handler;
+    }
+
+    public void setLexicalHandler(LexicalHandler lex) {
+	_lexHandler = lex;
+    }
+
+    public void setNode(Node node) {
+	_node = node;
+    }
+
+    public Node getNode() {
+	return (_handler instanceof SAX2DOM) ? ((SAX2DOM)_handler).getDOM() 
+	   : null;
+    }
+
+    public void setIndentNumber(int value) {
+	_indentNumber = value;
+    }
+
+    public TransletOutputHandler getTransletOutputHandler() 
+	throws IOException, ParserConfigurationException 
+    {
+	switch (_outputType) {
+	    case STREAM:
+		StreamOutput result = null;
+
+		if (_method == null) {
+		    result = (_writer == null) ? 
+			new StreamUnknownOutput(_ostream, _encoding) :
+			new StreamUnknownOutput(_writer, _encoding);
+		}
+		else if (_method.equalsIgnoreCase("xml")) {
+		    result = (_writer == null) ? 
+			new StreamXMLOutput(_ostream, _encoding) :
+			new StreamXMLOutput(_writer, _encoding);
+		}
+		else if (_method.equalsIgnoreCase("html")) {
+		    result = (_writer == null) ? 
+			new StreamHTMLOutput(_ostream, _encoding) :
+			new StreamHTMLOutput(_writer, _encoding);
+		}
+		else if (_method.equalsIgnoreCase("text")) {
+		    result = (_writer == null) ? 
+			new StreamTextOutput(_ostream, _encoding) :
+			new StreamTextOutput(_writer, _encoding);
+		}
+
+		if (result != null && _indentNumber >= 0) {
+		    result.setIndentNumber(_indentNumber);
+		}
+		return result;
+	    case DOM:
+		_handler = (_node != null) ? new SAX2DOM(_node) : 
+					     new SAX2DOM();
+		_lexHandler = (LexicalHandler)_handler;
+		// falls through
+	    case SAX:
+		if (_method == null) {
+		    _method = "xml";    // default case
+		}
+
+		if (_method.equalsIgnoreCase("xml")) {
+		    return (_lexHandler == null) ? 
+			new SAXXMLOutput(_handler, _encoding) :
+			new SAXXMLOutput(_handler, _lexHandler, _encoding);
+		}
+		else if (_method.equalsIgnoreCase("html")) {
+		    return (_lexHandler == null) ? 
+			new SAXHTMLOutput(_handler, _encoding) :
+			new SAXHTMLOutput(_handler, _lexHandler, _encoding);
+		}
+		else if (_method.equalsIgnoreCase("text")) {
+		    return (_lexHandler == null) ? 
+			new SAXTextOutput(_handler, _encoding) :
+			new SAXTextOutput(_handler, _lexHandler, _encoding);
+		}
+	    break;
+	}
+	return null;
+    }
+
+    // Temporary - returns an instance of TextOutput
+    public TransletOutputHandler getOldTransletOutputHandler() throws IOException {
+	DefaultSAXOutputHandler saxHandler =
+	    new DefaultSAXOutputHandler(_ostream, _encoding);
+	return new TextOutput((ContentHandler)saxHandler,
+			      (LexicalHandler)saxHandler, _encoding);
+    }
+}
diff --git a/src/org/apache/xalan/xsltc/trax/DOM2SAX.java b/src/org/apache/xalan/xsltc/trax/DOM2SAX.java
index af2ddb7..48ee609 100644
--- a/src/org/apache/xalan/xsltc/trax/DOM2SAX.java
+++ b/src/org/apache/xalan/xsltc/trax/DOM2SAX.java
@@ -63,8 +63,13 @@
 
 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.ext.LexicalHandler;
 import org.xml.sax.DTDHandler;
 import org.xml.sax.Locator;
 import org.xml.sax.ErrorHandler;
@@ -74,6 +79,9 @@
 import org.xml.sax.SAXNotSupportedException;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.AttributeList;
+import org.xml.sax.helpers.AttributeListImpl;
+
 import org.w3c.dom.Node;
 import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
@@ -81,54 +89,114 @@
 import org.w3c.dom.Entity;
 import org.w3c.dom.Notation;
 
-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 LexicalHandler _lex = null;
+    private Hashtable _nsPrefixes = new Hashtable();
+
     public DOM2SAX(Node root) {
-	_dom = (Document)root;
+	_dom = root;
     }
 
     public ContentHandler getContentHandler() { 
 	return _sax;
     }
 
-    public DTDHandler getDTDHandler() { 
-	return null;
-    }
-
-    public ErrorHandler getErrorHandler() {
-	return null;
-    }
-
-    public boolean getFeature(String name) throws SAXNotRecognizedException,
-	SAXNotSupportedException
+    public void setContentHandler(ContentHandler handler) throws 
+	NullPointerException 
     {
-	return false;
+	_sax = handler;
+	if (handler instanceof LexicalHandler) {
+	    _lex = (LexicalHandler) handler;
+	}
     }
 
-    public void setFeature(String name, boolean value) throws 
-	SAXNotRecognizedException, SAXNotSupportedException 
+    /**
+     * Begin the scope of namespace prefix. Forward the event to the 
+     * SAX handler only if the prefix is unknown or it is mapped to a 
+     * different URI.
+     */
+    private boolean startPrefixMapping(String prefix, String uri) 
+	throws SAXException 
     {
-	
+	boolean pushed = true;
+	Stack uriStack = (Stack) _nsPrefixes.get(prefix);
+
+	if (uriStack != null) {
+	    if (uriStack.isEmpty()) {
+		_sax.startPrefixMapping(prefix, uri);
+		uriStack.push(uri);
+	    }
+	    else {
+		final String lastUri = (String) uriStack.peek();
+		if (!lastUri.equals(uri)) {
+		    _sax.startPrefixMapping(prefix, uri);
+		    uriStack.push(uri);
+		}
+		else {
+		    pushed = false;
+		}
+	    }	
+	}
+	else {
+	    _sax.startPrefixMapping(prefix, uri);
+	    _nsPrefixes.put(prefix, uriStack = new Stack());
+	    uriStack.push(uri);
+	}
+	return pushed;
+    }
+
+    /*
+     * End the scope of a name prefix by popping it from the stack and 
+     * passing the event to the SAX Handler.
+     */
+    private void endPrefixMapping(String prefix) 
+	throws SAXException
+    {
+	final Stack uriStack = (Stack) _nsPrefixes.get(prefix);
+
+	if (uriStack != null) {
+	    _sax.endPrefixMapping(prefix);
+	    uriStack.pop();
+	}
+    }
+
+    /**
+     * If the DOM was created using a DOM 1.0 API, the local name may be 
+     * null. If so, get the local name from the qualified name before 
+     * generating the SAX event. 
+     */
+    private static String getLocalName(Node node) {
+	final String localName = node.getLocalName();
+
+	if (localName == null) {
+	    final String qname = node.getNodeName();
+	    final int col = qname.lastIndexOf(':');
+	    return (col > 0) ? qname.substring(col + 1) : qname;
+	}
+	return localName;
     }
 
     public void parse(InputSource unused) throws IOException, SAXException {
-        Node currNode = _dom;
-        parse(currNode);
+        parse(_dom);
     }
 
+    /**
+     * Traverse the DOM and generate SAX events for a handler. A 
+     * startElement() event passes all attributes, including namespace 
+     * declarations. 
+     */
     private void parse(Node node) throws IOException, SAXException {
         Node first = null;
- 	if (node == null ) return;
+ 	if (node == null) return;
 
         switch (node.getNodeType()) {
 	case Node.ATTRIBUTE_NODE:         // handled by ELEMENT_NODE
-	case Node.COMMENT_NODE:           // should be handled!!!
-	case Node.CDATA_SECTION_NODE:
 	case Node.DOCUMENT_FRAGMENT_NODE:
 	case Node.DOCUMENT_TYPE_NODE :
 	case Node.ENTITY_NODE :
@@ -136,9 +204,29 @@
 	case Node.NOTATION_NODE :
 	    // These node types are ignored!!!
 	    break;
+	case Node.CDATA_SECTION_NODE:
+	    final String cdata = node.getNodeValue();
+	    if (_lex != null) {
+		_lex.startCDATA();
+	        _sax.characters(cdata.toCharArray(), 0, cdata.length());
+		_lex.endCDATA();
+ 	    } 
+	    else {
+		// in the case where there is no lex handler, we still
+		// want the text of the cdate to make its way through.
+	        _sax.characters(cdata.toCharArray(), 0, cdata.length());
+	    }	
+	    break;
 
+	case Node.COMMENT_NODE:           // should be handled!!!
+	    if (_lex != null) {
+		final String value = node.getNodeValue();
+		_lex.comment(value.toCharArray(), 0, value.length());
+	    }
+	    break;
 	case Node.DOCUMENT_NODE:
 	    _sax.setDocumentLocator(this);
+
 	    _sax.startDocument();
 	    Node next = node.getFirstChild();
 	    while (next != null) {
@@ -149,29 +237,85 @@
 	    break;
 
 	case Node.ELEMENT_NODE:
-	    // Gather all attribute node of the element
-	    AttributeList attrs = new AttributeList();
-	    NamedNodeMap map = node.getAttributes();
-	    int length = map.getLength();
-	    for (int i=0; i<length; i++ ) {
-		Node attr = map.item(i);
-		attrs.add(attr.getNodeName(), attr.getNodeValue());
+	    String prefix;
+	    Vector pushedPrefixes = new Vector();
+	    final AttributesImpl attrs = new AttributesImpl();
+	    final NamedNodeMap map = node.getAttributes();
+	    final int length = map.getLength();
+
+	    // Process all namespace declarations
+	    for (int i = 0; i < length; i++) {
+		final Node attr = map.item(i);
+		final String qnameAttr = attr.getNodeName();
+
+		// Ignore everything but NS declarations here
+		if (qnameAttr.startsWith(XMLNS_PREFIX)) {
+		    final String uriAttr = attr.getNodeValue();
+		    final int colon = qnameAttr.lastIndexOf(':');
+		    prefix = (colon > 0) ? qnameAttr.substring(colon + 1) : EMPTYSTRING;
+		    if (startPrefixMapping(prefix, uriAttr)) {
+			pushedPrefixes.addElement(prefix);
+		    }
+		}
+	    }
+
+	    // Process all other attributes
+	    for (int i = 0; i < length; i++) {
+		final Node attr = map.item(i);
+		final String qnameAttr = attr.getNodeName();
+
+		// Ignore NS declarations here
+		if (!qnameAttr.startsWith(XMLNS_PREFIX)) {
+		    final String uriAttr = attr.getNamespaceURI();
+		    final String localNameAttr = getLocalName(attr);
+
+		    // Uri may be implicitly declared
+		    if (uriAttr != null) {	
+			final int colon = qnameAttr.lastIndexOf(':');
+			prefix = (colon > 0) ? qnameAttr.substring(0, colon) : EMPTYSTRING;
+			if (startPrefixMapping(prefix, uriAttr)) {
+			    pushedPrefixes.addElement(prefix);
+			}
+		    }
+
+		    // Add attribute to list
+		    attrs.addAttribute(attr.getNamespaceURI(), getLocalName(attr), 
+			qnameAttr, "CDATA", attr.getNodeValue());
+		}
+	    }
+
+	    // Now process the element itself
+	    final String qname = node.getNodeName();
+	    final String uri = node.getNamespaceURI();
+	    final String localName = getLocalName(node);
+
+	    // Uri may be implicitly declared
+	    if (uri != null) {	
+		final int colon = qname.lastIndexOf(':');
+		prefix = (colon > 0) ? qname.substring(0, colon) : EMPTYSTRING;
+		if (startPrefixMapping(prefix, uri)) {
+		    pushedPrefixes.addElement(prefix);
+		}
 	    }
 
 	    // Generate SAX event to start element
-	    _sax.startElement(node.getNamespaceURI(), node.getLocalName(),
-			      node.getNodeName(), attrs);
+	    _sax.startElement(uri, localName, qname, attrs);
 
 	    // Traverse all child nodes of the element (if any)
 	    next = node.getFirstChild();
-	    while ( next != null ) {
+	    while (next != null) {
 		parse(next);
 		next = next.getNextSibling();
 	    }
 
 	    // Generate SAX event to close element
-	    _sax.endElement(node.getNamespaceURI(),
-				    node.getLocalName(), node.getNodeName());
+	    _sax.endElement(uri, localName, qname);
+
+	    // Generate endPrefixMapping() for all pushed prefixes
+	    final int nPushedPrefixes = pushedPrefixes.size();
+	    for (int i = 0; i < nPushedPrefixes; i++) {
+		endPrefixMapping((String) pushedPrefixes.elementAt(i));
+	    }
 	    break;
 
 	case Node.PROCESSING_INSTRUCTION_NODE:
@@ -186,48 +330,133 @@
 	}
     }
 
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public DTDHandler getDTDHandler() { 
+	return null;
+    }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public ErrorHandler getErrorHandler() {
+	return null;
+    }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public boolean getFeature(String name) throws SAXNotRecognizedException,
+	SAXNotSupportedException
+    {
+	return false;
+    }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public void setFeature(String name, boolean value) throws 
+	SAXNotRecognizedException, SAXNotSupportedException 
+    {
+    }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void parse(String sysId) throws IOException, SAXException {
 	throw new IOException("This method is not yet implemented.");
     }
-    public void setContentHandler(ContentHandler handler) throws 
-	NullPointerException 
-    {
-	if (handler == null ) throw new NullPointerException();
-	_sax = handler;
-    }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void setDTDHandler(DTDHandler handler) throws NullPointerException {
-	if (handler == null )  throw new NullPointerException();
     }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void setEntityResolver(EntityResolver resolver) throws 
 	NullPointerException 
     {
-	if (resolver == null )  throw new NullPointerException();
     }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public EntityResolver getEntityResolver() {
 	return null;
     }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void setErrorHandler(ErrorHandler handler) throws 
 	NullPointerException
     {
-	if (handler == null )  throw new NullPointerException();
     }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public void setProperty(String name, Object value) throws
 	SAXNotRecognizedException, SAXNotSupportedException {
     }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
     public Object getProperty(String name) throws SAXNotRecognizedException,
 	SAXNotSupportedException
     {
 	return null;
     }
 
-    // Locator methods
-    public int getColumnNumber() { return 0; }
-    public int getLineNumber() { return 0; }
-    public String getPublicId() { return null; }
-    public String getSystemId() { return null; }
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public int getColumnNumber() { 
+	return 0; 
+    }
+    
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public int getLineNumber() { 
+	return 0; 
+    }
 
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public String getPublicId() { 
+	return null; 
+    }
 
-    // private 
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public String getSystemId() { 
+	return null; 
+    }
+
+    // Debugging 
     private String getNodeTypeFromCode(short code) {
 	String retval = null;
 	switch (code) {
diff --git a/src/org/apache/xalan/xsltc/trax/SAX2DOM.java b/src/org/apache/xalan/xsltc/trax/SAX2DOM.java
index 82177b7..20b8d71 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;
@@ -71,168 +73,168 @@
 import javax.xml.parsers.ParserConfigurationException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Comment;
 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.xml.sax.ext.LexicalHandler;
+import org.xml.sax.SAXException;
 
+import org.apache.xalan.xsltc.runtime.Constants;
 
-class SAX2DOM implements ContentHandler {
+public class SAX2DOM implements ContentHandler, LexicalHandler, Constants {
 
-    private Document _document = null;
-    private DocumentBuilder _builder = null;
-    private Stack _nodeStk = null;
- 
+    private Document _root = null;
+    private Stack _nodeStk = new Stack();
+    private Vector _namespaceDecls = null;
+
     public SAX2DOM() throws ParserConfigurationException {
-	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-	_builder = factory.newDocumentBuilder();
-	_nodeStk = new Stack();
+	final DocumentBuilderFactory factory = 
+		DocumentBuilderFactory.newInstance();
+	_root = factory.newDocumentBuilder().newDocument();
+    }
+
+    public SAX2DOM(Node root) throws ParserConfigurationException {
+	if (root != null) {
+	    _root = (Document) root;   // TODO: add support for frags and elems
+	}
+	else {
+	    final DocumentBuilderFactory factory = 
+		DocumentBuilderFactory.newInstance();
+	    _root = factory.newDocumentBuilder().newDocument();
+	}
     }
 
     public Node getDOM() {
-	return _document;
+	return _root;
     }
 
     public void characters(char[] ch, int start, int length) {
-	Text text = _document.createTextNode(new String(ch, start, length));
-	Node last = (Node)_nodeStk.peek();
-	last.appendChild(text);
+	final Node last = (Node)_nodeStk.peek();
+
+	// No text nodes can be children of root (DOM006 exception)
+	if (last != _root) {
+	    final String text = new String(ch, start, length);
+	    last.appendChild(_root.createTextNode(text));
+	}
     }
 
     public void startDocument() {
-	_document = _builder.newDocument();
-	Element root = (Element)_document.createElement("root");
-	_document.appendChild(root);
-	_nodeStk.push(root);
+	_nodeStk.push(_root);
     }
 
     public void endDocument() {
-	//printDOM();
     }
 
     public void startElement(String namespace, String localName, String qName,
-	Attributes attrs ) 
+	Attributes attrs) 
     {
-	// create new element
-	Element tmp = (Element)_document.createElementNS(namespace, qName);
-	int nattrs = attrs.getLength();
-	for (int i=0; i<nattrs; i++ ) {
-	    String namespaceuri = attrs.getURI(i);
-	    String value = attrs.getValue(i);
-	    String qname = attrs.getQName(i);
-	    if ((namespaceuri == null) || (namespaceuri.equals("")))
-		tmp.setAttribute(qname, value);
-	    else
-		tmp.setAttributeNS(namespaceuri, qname, value);
+	final Element tmp = (Element)_root.createElementNS(namespace, qName);
+
+	// Add namespace declarations first
+	if (_namespaceDecls != null) {
+	    final int nDecls = _namespaceDecls.size();
+	    for (int i = 0; i < nDecls; i++) {
+		final String prefix = (String) _namespaceDecls.elementAt(i++);
+
+		if (prefix == null || prefix.equals(EMPTYSTRING)) {
+		    tmp.setAttributeNS(XMLNS_URI, XMLNS_PREFIX,
+			(String) _namespaceDecls.elementAt(i));
+		}
+		else {
+		    tmp.setAttributeNS(XMLNS_URI, XMLNS_STRING + prefix, 
+			(String) _namespaceDecls.elementAt(i));
+		}
+	    }
+	    _namespaceDecls.clear();
 	}
-	// append this new node onto current stack node
+
+	// Add attributes to element
+	final int nattrs = attrs.getLength();
+	for (int i = 0; i < nattrs; i++) {
+	    if (attrs.getLocalName(i) == null) {
+		tmp.setAttribute(attrs.getQName(i), attrs.getValue(i));
+	    }
+	    else {
+		tmp.setAttributeNS(attrs.getURI(i), attrs.getQName(i), 
+		    attrs.getValue(i));
+	    }
+	}
+
+	// Append this new node onto current stack node
 	Node last = (Node)_nodeStk.peek();
 	last.appendChild(tmp);
-	// push this node onto stack
+
+	// Push this node onto stack
 	_nodeStk.push(tmp);
     }
 
     public void endElement(String namespace, String localName, String qName) {
-	Node lastActive = (Node)_nodeStk.pop();  
-    }
-
-
-    public void ignorableWhitespace(char[] ch, int start, int length) {
-    }
-
-    public void processingInstruction(String target, String data) {
-    }
-
-    public void setDocumentLocator(Locator locator) {
-    }
-
-    public void skippedEntity(String name) {
+	_nodeStk.pop();  
     }
 
     public void startPrefixMapping(String prefix, String uri) {
+	if (_namespaceDecls == null) {
+	    _namespaceDecls = new Vector(2);
+	}
+	_namespaceDecls.addElement(prefix);
+	_namespaceDecls.addElement(uri);
     }
 
     public void endPrefixMapping(String prefix) {
+	// do nothing
+    }
+
+    /**
+     * This class is only used internally so this method should never 
+     * be called.
+     */
+    public void ignorableWhitespace(char[] ch, int start, int length) {
+    }
+
+    /**
+     * adds processing instruction node to DOM.
+     */
+    public void processingInstruction(String target, String data) {
+	final Node last = (Node)_nodeStk.peek();
+	ProcessingInstruction pi = _root.createProcessingInstruction(
+		target, data);
+	if (pi != null)  last.appendChild(pi);
+    }
+
+    /**
+     * 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) {
     }
 
 
-    // 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;
-            }
+    /**
+     * Lexical Handler method to create comment node in DOM tree.
+     */
+    public void comment(char[] ch, int start, int length) {
+	final Node last = (Node)_nodeStk.peek();
+	Comment comment = _root.createComment(new String(ch,start,length));
+	if (comment != null) last.appendChild(comment);
+    }
 
-            // 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();
-            }
-        }
-   }
+    // Lexical Handler methods- not implemented
+    public void startCDATA() { }
+    public void endCDATA() { }
+    public void startEntity(java.lang.String name) { }
+    public void endDTD() { }
+    public void endEntity(String name) { }
+    public void startDTD(String name, String publicId, String systemId)
+        throws SAXException { }
 
 }
diff --git a/src/org/apache/xalan/xsltc/trax/TemplatesHandlerImpl.java b/src/org/apache/xalan/xsltc/trax/TemplatesHandlerImpl.java
index 3c8f8f0..0af479d 100644
--- a/src/org/apache/xalan/xsltc/trax/TemplatesHandlerImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TemplatesHandlerImpl.java
@@ -65,6 +65,7 @@
 import javax.xml.transform.*;
 import javax.xml.transform.sax.*;
 
+import org.xml.sax.Locator;
 import org.apache.xalan.xsltc.Translet;
 import org.apache.xalan.xsltc.runtime.AbstractTranslet;
 import org.apache.xalan.xsltc.compiler.*;
@@ -76,12 +77,18 @@
 public class TemplatesHandlerImpl extends Parser implements TemplatesHandler {
 
     private String _systemId;
+    private int    _indentNumber;
+
+    // Temporary
+    private boolean _oldOutputSystem;
 
     /**
      * Default constructor
      */
-    protected TemplatesHandlerImpl() {
+    protected TemplatesHandlerImpl(int indentNumber, boolean oldOutputSystem) {
 	super(null);
+	_indentNumber = indentNumber;
+	_oldOutputSystem = oldOutputSystem;
     }
 
     /**
@@ -91,8 +98,9 @@
 	// Create and initialize a stylesheet compiler
 	final XSLTC xsltc = new XSLTC();
 	super.setXSLTC(xsltc);
-	xsltc.setParser(this);
 	xsltc.init();
+	super.init();
+	xsltc.setParser(this);
 	xsltc.setOutputType(XSLTC.BYTEARRAY_OUTPUT);
     }
 
@@ -126,51 +134,61 @@
      *         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();
 
 	    // Set the translet class name if not already set
 	    String transletName = TransformerFactoryImpl._defaultTransletName;
-	    if (_systemId != null) transletName = Util.baseName(_systemId);
+	    if (_systemId != null) {
+		transletName = Util.baseName(_systemId);
+	    }
 	    xsltc.setClassName(transletName);
 
+	    // Get java-legal class name from XSLTC module
+	    transletName = xsltc.getClassName();
+
 	    Stylesheet stylesheet = null;
 	    SyntaxTreeNode root = getDocumentRoot();
 
 	    // Compile the translet - this is where the work is done!
-	    if ((!errorsFound()) && (root != null)) {
+	    if (!errorsFound() && root != null) {
 		// Create a Stylesheet element from the root node
 		stylesheet = makeStylesheet(root);
 		stylesheet.setSystemId(_systemId);
 		stylesheet.setParentStylesheet(null);
 		setCurrentStylesheet(stylesheet);
-		// Create AST under the Stylesheet element (parse & type-check)
+		// Create AST under the Stylesheet element 
 		createAST(stylesheet);
 	    }
 
 	    // Generate the bytecodes and output the translet class(es)
-	    if ((!errorsFound()) && (stylesheet != null)) {
+	    if (!errorsFound() && stylesheet != null) {
 		stylesheet.setMultiDocument(xsltc.isMultiDocument());
 		stylesheet.translate();
 	    }
 
-	    xsltc.printWarnings();
-
-	    // Check that the transformation went well before returning
-	    if (bytecodes == null) {
-		xsltc.printErrors();
-		return null;
+	    if (!errorsFound()) {
+		// Check that the transformation went well before returning
+		final byte[][] bytecodes = xsltc.getBytecodes();
+		if (bytecodes != null) {
+		    return new TemplatesImpl(xsltc.getBytecodes(), transletName, 
+			 getOutputProperties(), _indentNumber, _oldOutputSystem);
+		}
 	    }
-
-	    return(new TemplatesImpl(bytecodes, transletName));
 	}
 	catch (CompilerException e) {
-	    return null;
+	    // falls through
 	}
+	return null;
+    }
+
+    /**
+     * recieve an object for locating the origin of SAX document events.
+     * Most SAX parsers will use this method to inform content handler
+     * of the location of the parsed document. 
+     */
+    public void setDocumentLocator(Locator locator) {
+  	setSystemId(locator.getSystemId());
     }
 }
 
diff --git a/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java b/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java
index e1c099c..d0a2a95 100644
--- a/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TemplatesImpl.java
@@ -59,6 +59,7 @@
  * @author Morten Jorgensen
  * @author G. Todd Millerj
  * @author Jochen Cordes <Jochen.Cordes@t-online.de>
+ * @author Santiago Pericas-Geertsen 
  *
  */
 
@@ -96,6 +97,13 @@
     // and _bytecodes arrays (above).
     private int _transletIndex = -1;
     
+    private Properties _outputProperties; 
+
+    private int _indentNumber;
+
+    // Temporary
+    private boolean _oldOutputSystem;
+
     // Our own private class loader - builds Class definitions from bytecodes
     private class TransletClassLoader extends ClassLoader {
 
@@ -126,9 +134,15 @@
      * The bytecodes for the translet and auxiliary classes, plus the name of
      * the main translet class, must be supplied
      */
-    protected TemplatesImpl(byte[][] bytecodes, String transletName) {
+    protected TemplatesImpl(byte[][] bytecodes, String transletName,
+	Properties outputProperties, int indentNumber,
+	boolean oldOutputSystem) 
+    {
 	_bytecodes = bytecodes;
 	_name      = transletName;
+	_outputProperties = outputProperties;
+	_indentNumber = indentNumber;
+	_oldOutputSystem = oldOutputSystem;
     }
 
     /**
@@ -176,8 +190,13 @@
 	    (TransletClassLoader) AccessController.doPrivileged(
 		new PrivilegedAction() {
 			public Object run() {
-			    ClassLoader current = getClass().getClassLoader();
-			    return new TransletClassLoader(current);
+			    /* 
+			     * Get the loader from the current thread instead of
+			     * the class. This is important for translets that load
+			     * external Java classes and run in multi-threaded envs.
+			     */
+			    return new TransletClassLoader(
+				Thread.currentThread().getContextClassLoader());
 			}
 		    }
 		);
@@ -250,7 +269,8 @@
      */
     public Transformer newTransformer()
 	throws TransformerConfigurationException {
-        return(new TransformerImpl(getTransletInstance()));
+        return new TransformerImpl(getTransletInstance(), _outputProperties,
+	    _indentNumber, _oldOutputSystem);
     }
 
     /**
diff --git a/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java b/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
index 2f2cc9b..29dbaa4 100644
--- a/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TransformerFactoryImpl.java
@@ -140,8 +140,11 @@
 	}
     }
 
-    // This flag is passed to the compiler - will produce stack traces etc.
+    // This flags are passed to the compiler
     private boolean _debug = false;
+    private boolean _disableInlining = false;
+    private boolean _oldOutputSystem = false;
+    private int     _indentNumber    = -1;
 
     /**
      * javax.xml.transform.sax.TransformerFactory implementation.
@@ -206,20 +209,64 @@
      * @throws IllegalArgumentException
      */
     public void setAttribute(String name, Object value) 
-	throws IllegalArgumentException { 
+	throws IllegalArgumentException 
+    { 
 	// Set the default translet name (ie. class name), which will be used
 	// for translets that cannot be given a name from their system-id.
-	if ((name.equals("translet-name")) && (value instanceof String)) {
-	    _defaultTransletName = (String)value;
+	if (name.equals("translet-name") && value instanceof String) {
+	    _defaultTransletName = (String) value;
+	    return;
 	}
 	else if (name.equals("debug")) {
-	    _debug = true;
+	    if (value instanceof Boolean) {
+		_debug = ((Boolean) value).booleanValue();
+		return;
+	    }
+	    else if (value instanceof String) {
+		_debug = ((String) value).equalsIgnoreCase("true");
+		return;
+	    }
 	}
-	else {
-	    // Throw an exception for all other attributes
-	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_ERR, name);
-	    throw new IllegalArgumentException(err.toString());
+	else if (name.equals("disable-inlining")) {
+	    if (value instanceof Boolean) {
+		_disableInlining = ((Boolean) value).booleanValue();
+		return;
+	    }
+	    else if (value instanceof String) {
+		_disableInlining = ((String) value).equalsIgnoreCase("true");
+		return;
+	    }
 	}
+	else if (name.equals("old-output")) {
+	    if (value instanceof Boolean) {
+		_oldOutputSystem = ((Boolean) value).booleanValue();
+		return;
+	    }
+	    else if (value instanceof String) {
+		_oldOutputSystem = ((String) value).equalsIgnoreCase("true");
+		return;
+	    }
+	}
+	else if (name.equals("indent-number")) {
+	    if (value instanceof String) {
+		try {
+		    _indentNumber = Integer.parseInt((String) value);
+		    return;
+		}
+		catch (NumberFormatException e) {
+		    // Falls through
+		}
+	    }
+	    else if (value instanceof Integer) {
+		_indentNumber = ((Integer) value).intValue();
+		return;
+	    }
+	}
+
+	// Throw an exception for all other attributes
+	final ErrorMsg err 
+	    = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_ERR, name);
+	throw new IllegalArgumentException(err.toString());
     }
 
     /**
@@ -320,6 +367,7 @@
 
 	XSLTC xsltc = new XSLTC();
 	if (_debug) xsltc.setDebug(true);
+	if (_disableInlining) xsltc.setTemplateInlining(false);
 	xsltc.init();
 
 	// Compile the default copy-stylesheet
@@ -336,10 +384,14 @@
 	}
 
 	// Create a Transformer object and store for other calls
-	Templates templates = new TemplatesImpl(bytecodes,_defaultTransletName);
+	Templates templates = new TemplatesImpl(bytecodes, _defaultTransletName,
+	    xsltc.getOutputProperties(), _indentNumber, _oldOutputSystem);
+
 	_copyTransformer = templates.newTransformer();
-	if (_uriResolver != null) _copyTransformer.setURIResolver(_uriResolver);
-	return(_copyTransformer);
+	if (_uriResolver != null) {
+	    _copyTransformer.setURIResolver(_uriResolver);
+	}
+	return _copyTransformer;
     }
 
     /**
@@ -363,21 +415,18 @@
     /**
      * Pass warning messages from the compiler to the error listener
      */
-    private void passWarningsToListener(Vector messages) {
-	try {
-	    // Nothing to do if there is no registered error listener
-	    if (_errorListener == null) return;
-	    // Nothing to do if there are not warning messages
-	    if (messages == null) return;
-	    // Pass messages to listener, one by one
-	    final int count = messages.size();
-	    for (int pos=0; pos<count; pos++) {
-		String message = messages.elementAt(pos).toString();
-		_errorListener.warning(new TransformerException(message));
-	    }
+    private void passWarningsToListener(Vector messages) 
+	throws TransformerException 
+    {
+	if (_errorListener == null || messages == null ) {
+	    return;
 	}
-	catch (TransformerException e) {
-	    // nada
+	// Pass messages to listener, one by one
+	final int count = messages.size();
+	for (int pos = 0; pos < count; pos++) {
+	    String message = messages.elementAt(pos).toString();
+	    _errorListener.error(
+		new TransformerConfigurationException(message));
 	}
     }
 
@@ -429,6 +478,9 @@
 		xsltc.setXMLReader(dom2sax);  
 	        // try to get SAX InputSource from DOM Source.
 		input = SAXSource.sourceToInputSource(source);
+		if (input == null){
+			input = new InputSource(domsrc.getSystemId());
+		}
 	    }
 	    // Try to get InputStream or Reader from StreamSource
 	    else if (source instanceof StreamSource) {
@@ -474,10 +526,10 @@
      */
     public Templates newTemplates(Source source)
 	throws TransformerConfigurationException {
-
 	// Create and initialize a stylesheet compiler
 	final XSLTC xsltc = new XSLTC();
 	if (_debug) xsltc.setDebug(true);
+	if (_disableInlining) xsltc.setTemplateInlining(false);
 	xsltc.init();
 
 	// Set a document loader (for xsl:include/import) if defined
@@ -499,10 +551,17 @@
 	final String transletName = xsltc.getClassName();
 
 	// Pass compiler warnings to the error listener
-	if (_errorListener != null)
-	    passWarningsToListener(xsltc.getWarnings());
-	else
+	if (_errorListener != this) {
+	    try {
+		passWarningsToListener(xsltc.getWarnings());
+	    }
+	    catch (TransformerException e) {
+		throw new TransformerConfigurationException(e);
+	    }
+	}
+	else {
 	    xsltc.printWarnings();
+	}
 
 	// Check that the transformation went well before returning
 	if (bytecodes == null) {
@@ -514,7 +573,8 @@
 	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_COMPILE_ERR);
 	    throw new TransformerConfigurationException(err.toString());
 	}
-	return(new TemplatesImpl(bytecodes, transletName));
+	return new TemplatesImpl(bytecodes, transletName, 
+	    xsltc.getOutputProperties(), _indentNumber, _oldOutputSystem);
     }
 
     /**
@@ -527,7 +587,10 @@
      */
     public TemplatesHandler newTemplatesHandler() 
 	throws TransformerConfigurationException { 
-	return(new TemplatesHandlerImpl());
+	final TemplatesHandlerImpl handler = 
+	    new TemplatesHandlerImpl(_indentNumber, _oldOutputSystem);
+	handler.init();
+	return handler;
     }
 
     /**
diff --git a/src/org/apache/xalan/xsltc/trax/TransformerHandlerImpl.java b/src/org/apache/xalan/xsltc/trax/TransformerHandlerImpl.java
index b1a87b7..6000457 100644
--- a/src/org/apache/xalan/xsltc/trax/TransformerHandlerImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TransformerHandlerImpl.java
@@ -63,12 +63,14 @@
 package org.apache.xalan.xsltc.trax;
 
 import org.xml.sax.*;
+import org.xml.sax.ext.DeclHandler;
 
 import javax.xml.transform.*;
 import javax.xml.transform.sax.*;
 
 import org.apache.xalan.xsltc.Translet;
 import org.apache.xalan.xsltc.dom.DOMImpl;
+import org.apache.xalan.xsltc.dom.DOMBuilder;
 import org.apache.xalan.xsltc.dom.DTDMonitor;
 import org.apache.xalan.xsltc.runtime.AbstractTranslet;
 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
@@ -76,13 +78,13 @@
 /**
  * Implementation of a JAXP1.1 TransformerHandler
  */
-public class TransformerHandlerImpl implements TransformerHandler {
+public class TransformerHandlerImpl implements TransformerHandler, DeclHandler {
 
     private TransformerImpl  _transformer;
     private AbstractTranslet _translet = null;
     private String           _systemId;
     private DOMImpl          _dom = null;
-    private ContentHandler   _handler = null;
+    private DOMBuilder       _handler = null;
     private DTDMonitor       _dtd = null;
     private Result           _result = null;
 
@@ -97,6 +99,13 @@
 
 	// Get a reference to the translet wrapped inside the transformer
 	_translet = _transformer.getTranslet();
+
+	// Create a DOMBuilder object and get the handler
+	_dom = new DOMImpl();
+	_handler = _dom.getBuilder();
+
+	// Create a new DTD monitor
+	_dtd = new DTDMonitor();
     }
 
     /**
@@ -126,7 +135,7 @@
      * @return The Transformer object
      */
     public Transformer getTransformer() {
-	return(_transformer);
+	return _transformer;
     }
 
     /**
@@ -157,7 +166,8 @@
      * Receive notification of character data.
      */
     public void characters(char[] ch, int start, int length) 
-	throws SAXException {
+	throws SAXException 
+    {
 	_handler.characters(ch, start, length);
     }
 
@@ -172,9 +182,8 @@
 	    throw new SAXException(err.toString());
 	}
 
-	// Create an internal DOM (not W3C) and get SAX2 input handler
-	_dom = new DOMImpl();
-	_handler = _dom.getBuilder();
+	// Set document URI
+	_dom.setDocumentURI(_systemId);
 
 	// Proxy call
 	_handler.startDocument();
@@ -187,12 +196,12 @@
     public void endDocument() throws SAXException {
 	// Signal to the DOMBuilder that the document is complete
 	_handler.endDocument();
-	// Pass unparsed entity declarations (if any) to the translet 
-	if (_dtd != null) _translet.setDTDMonitor(_dtd);
+
 	// Run the transformation now if we have a reference to a Result object
 	if (_result != null) {
 	    try {
 		_transformer.setDOM(_dom);
+		_transformer.setDTDMonitor(_dtd);	// for id/key
 		_transformer.transform(null, _result);
 	    }
 	    catch (TransformerException e) {
@@ -235,31 +244,54 @@
     }
 
     /**
+     * Implements org.xml.sax.ext.LexicalHandler.startCDATA()
+     */
+    public void startCDATA() throws SAXException { 
+	_handler.startCDATA();
+    }
+
+    /**
+     * Implements org.xml.sax.ext.LexicalHandler.endCDATA()
+     */
+    public void endCDATA() throws SAXException { 
+	_handler.endCDATA();
+    }
+
+    /**
+     * Implements org.xml.sax.ext.LexicalHandler.comment()
+     * Receieve notification of a comment
+     */
+    public void comment(char[] ch, int start, int length) 
+	throws SAXException 
+    { 
+	_handler.comment(ch, start, length);
+    }
+
+    /**
      * Implements org.xml.sax.ContentHandler.ignorableWhitespace()
      * Receive notification of ignorable whitespace in element
      * content. Similar to characters(char[], int, int).
      */
     public void ignorableWhitespace(char[] ch, int start, int length)
-	throws SAXException {
+	throws SAXException 
+    {
 	_handler.ignorableWhitespace(ch, start, length);
     }
 
     /**
      * Implements org.xml.sax.ContentHandler.setDocumentLocator()
      * Receive an object for locating the origin of SAX document events. 
-     * We do not handle this method, and the input is quietly ignored
      */
     public void setDocumentLocator(Locator locator) {
-	// Not handled by DOMBuilder - ignored
+	_handler.setDocumentLocator(locator);
     }
 
     /**
      * Implements org.xml.sax.ContentHandler.skippedEntity()
      * Receive notification of a skipped entity.
-     * We do not handle this method, and the input is quietly ignored
      */
-    public void skippedEntity(String name) {
-	// Not handled by DOMBuilder - ignored
+    public void skippedEntity(String name) throws SAXException {
+	_handler.skippedEntity(name);
     }
 
     /**
@@ -280,66 +312,86 @@
     }
 
     /**
-     * Implements org.xml.sax.DTDHandler.notationDecl()
-     * End the scope of a prefix-URI Namespace mapping.
-     * We do not handle this method, and the input is quietly ignored.
+     * Implements org.xml.sax.ext.LexicalHandler.startDTD()
      */
-    public void notationDecl(String name, String publicId, String systemId) {
-	// Not handled by DTDMonitor - ignored
+    public void startDTD(String name, String publicId, String systemId) 
+	throws SAXException
+    { 
+	_handler.startDTD(name, publicId, systemId);
+    }
+
+    /**
+     * Implements org.xml.sax.ext.LexicalHandler.endDTD()
+     */
+    public void endDTD() throws SAXException {
+	_handler.endDTD();
+    }
+
+    /**
+     * Implements org.xml.sax.ext.LexicalHandler.startEntity()
+     */
+    public void startEntity(String name) throws SAXException { 
+	_handler.startEntity(name);
+    }
+
+    /**
+     * Implements org.xml.sax.ext.LexicalHandler.endEntity()
+     */
+    public void endEntity(String name) throws SAXException { 
+	_handler.endEntity(name);
     }
 
     /**
      * Implements org.xml.sax.DTDHandler.unparsedEntityDecl()
-     * End the scope of a prefix-URI Namespace mapping.
      */
-    public void unparsedEntityDecl(String name, String publicId,
-				   String systemId, String notationName)
-	throws SAXException {
-	// Create new contained for unparsed entities
-	if (_dtd == null) _dtd = new DTDMonitor();
+    public void unparsedEntityDecl(String name, String publicId, 
+	String systemId, String notationName) throws SAXException 
+    {
 	_dtd.unparsedEntityDecl(name, publicId, systemId, notationName);
     }
 
     /**
-     * Implements org.xml.sax.ext.LexicalHandler.startDTD()
-     * We do not handle this method, and the input is quietly ignored
+     * Implements org.xml.sax.DTDHandler.notationDecl()
      */
-    public void startDTD(String name, String publicId, String systemId) { }
+    public void notationDecl(String name, String publicId, String systemId) 
+	throws SAXException
+    {
+	_dtd.notationDecl(name, publicId, systemId);
+    }
 
     /**
-     * Implements org.xml.sax.ext.LexicalHandler.endDTD()
-     * We do not handle this method, and the input is quietly ignored
+     * Implements org.xml.sax.ext.DeclHandler.attributeDecl()
      */
-    public void endDTD() { }
+    public void attributeDecl(String eName, String aName, String type, 
+	String valueDefault, String value) throws SAXException 
+    {
+	_dtd.attributeDecl(eName, aName, type, valueDefault, value);
+    }
 
     /**
-     * Implements org.xml.sax.ext.LexicalHandler.startEntity()
-     * We do not handle this method, and the input is quietly ignored
+     * Implements org.xml.sax.ext.DeclHandler.elementDecl()
      */
-    public void startEntity(String name) { }
+    public void elementDecl(String name, String model) 
+	throws SAXException
+    {
+	_dtd.elementDecl(name, model);
+    }
 
     /**
-     * Implements org.xml.sax.ext.LexicalHandler.endEntity()
-     * We do not handle this method, and the input is quietly ignored
+     * Implements org.xml.sax.ext.DeclHandler.externalEntityDecl()
      */
-    public void endEntity(String name) { }
+    public void externalEntityDecl(String name, String publicId, String systemId) 
+	throws SAXException
+    {
+	_dtd.externalEntityDecl(name, publicId, systemId);
+    }
 
     /**
-     * Implements org.xml.sax.ext.LexicalHandler.startCDATA()
-     * We do not handle this method, and the input is quietly ignored
+     * Implements org.xml.sax.ext.DeclHandler.externalEntityDecl()
      */
-    public void startCDATA() { }
-
-    /**
-     * Implements org.xml.sax.ext.LexicalHandler.endCDATA()
-     * We do not handle this method, and the input is quietly ignored
-     */
-    public void endCDATA() { }
-
-    /**
-     * Implements org.xml.sax.ext.LexicalHandler.comment()
-     * We do not handle this method, and the input is quietly ignored
-     */
-    public void comment(char[] ch, int start, int length) { }
-
+    public void internalEntityDecl(String name, String value) 
+	throws SAXException
+    {
+	_dtd.internalEntityDecl(name, value);
+    }
 }
diff --git a/src/org/apache/xalan/xsltc/trax/TransformerImpl.java b/src/org/apache/xalan/xsltc/trax/TransformerImpl.java
index 24e66cf..9e4e531 100644
--- a/src/org/apache/xalan/xsltc/trax/TransformerImpl.java
+++ b/src/org/apache/xalan/xsltc/trax/TransformerImpl.java
@@ -101,9 +101,12 @@
 
 import org.apache.xalan.xsltc.Translet;
 import org.apache.xalan.xsltc.TransletException;
+import org.apache.xalan.xsltc.TransletOutputHandler;
 import org.apache.xalan.xsltc.DOMCache;
 import org.apache.xalan.xsltc.dom.*;
+import org.apache.xalan.xsltc.compiler.Constants;
 import org.apache.xalan.xsltc.runtime.*;
+import org.apache.xalan.xsltc.runtime.output.*;
 import org.apache.xalan.xsltc.compiler.*;
 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
 
@@ -113,12 +116,13 @@
     implements DOMCache, ErrorListener {
 
     private AbstractTranslet _translet = null;
+    private String           _method   = null;
     private String           _encoding = null;
-    private ContentHandler   _handler = null;
+    private ContentHandler   _handler  = null;
 
     private ErrorListener _errorListener = this;
     private URIResolver   _uriResolver = null;
-    private Properties    _properties = null;
+    private Properties    _properties, _propertiesClone;
 
     // Used for default output property settings
     private final static String EMPTY_STRING = "";
@@ -129,25 +133,39 @@
     // Pre-set DOMImpl to use as input (used only with TransformerHandlerImpl)
     private DOMImpl _dom = null;
 
+    private DTDMonitor _dtdMonitor = null;
+
     private final static String LEXICAL_HANDLER_PROPERTY =
 	"http://xml.org/sax/properties/lexical-handler";
     private static final String NAMESPACE_FEATURE =
 	"http://xml.org/sax/features/namespaces";
     
+    private TransletOutputHandlerFactory _tohFactory = null;
+
+    private int _indentNumber;
+
+    // Temporary
+    private boolean _oldOutputSystem;
+
     /**
      * Implements JAXP's Transformer constructor
      * Our Transformer objects always need a translet to do the actual work
      */
-    protected TransformerImpl(Translet translet) {
-	_translet = (AbstractTranslet)translet;
-	_properties = createOutputProperties();
+    protected TransformerImpl(Translet translet, Properties outputProperties,
+	int indentNumber, boolean oldOutputSystem) 
+    {
+	_translet = (AbstractTranslet) translet;
+	_properties = createOutputProperties(outputProperties);
+	_oldOutputSystem = oldOutputSystem;
+	_propertiesClone = (Properties) _properties.clone();
+	_indentNumber = indentNumber;
     }
 
     /**
      * Returns the translet wrapped inside this Transformer
      */
     protected AbstractTranslet getTranslet() {
-	return(_translet);
+	return _translet;
     }
 
     /**
@@ -158,31 +176,168 @@
      * @throws TransformerException
      */
     public void transform(Source source, Result result)
-	throws TransformerException {
-
+	throws TransformerException 
+    {
 	if (_translet == null) {
 	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_TRANSLET_ERR);
 	    throw new TransformerException(err.toString());
 	}
 
-	_handler = getOutputHandler(result);
-	if (_handler == null) {
-	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_HANDLER_ERR);
-	    throw new TransformerException(err.toString());
+	// Pass output properties to the translet
+	setOutputProperties(_translet, _properties);
+	    
+	if (!_oldOutputSystem) {
+	    final TransletOutputHandler toHandler = getOutputHandler(result);
+
+	    if (toHandler == null) {
+		ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_HANDLER_ERR);
+		throw new TransformerException(err.toString());
+	    }
+
+	    if (_uriResolver != null) {
+		_translet.setDOMCache(this);
+	    }
+
+	    transform(source, toHandler, _encoding);
+
+	    if (result instanceof DOMResult) {
+		((DOMResult)result).setNode(_tohFactory.getNode());
+	    }
+	}
+	else {
+	    _handler = getOldOutputHandler(result);
+	    if (_handler == null) {
+		ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_HANDLER_ERR);
+		throw new TransformerException(err.toString());
+	    }
+
+	    if (_uriResolver != null) {
+		_translet.setDOMCache(this);
+	    }
+
+	    // Run the transformation
+	    transform(source, (ContentHandler)_handler, _encoding);
+
+	    // If a DOMResult, then we must set the DOM Tree so it can
+	    // be retrieved later 
+	    if (result instanceof DOMResult) {
+		((DOMResult)result).setNode(((SAX2DOM)_handler).getDOM());
+	    }
+	}
+    }
+
+    /**
+     * Create an output handler for the transformation output based on 
+     * the type and contents of the TrAX Result object passed to the 
+     * transform() method. 
+     */
+    private TransletOutputHandler getOutputHandler(Result result) 
+	throws TransformerException 
+    {
+	// Get output method using get() to ignore defaults 
+	_method = (String) _properties.get(OutputKeys.METHOD);
+
+	// Get encoding using getProperty() to use defaults
+	_encoding = (String) _properties.getProperty(OutputKeys.ENCODING);
+
+	_tohFactory = TransletOutputHandlerFactory.newInstance();
+	_tohFactory.setEncoding(_encoding);
+	if (_method != null) {
+	    _tohFactory.setOutputMethod(_method);
 	}
 
-	if (_uriResolver != null) {
-	    _translet.setDOMCache(this);
+	// Set indentation number in the factory
+	if (_indentNumber >= 0) {
+	    _tohFactory.setIndentNumber(_indentNumber);
 	}
 
-	// Run the transformation
-	transform(source, (ContentHandler)_handler, _encoding);
+	// Return the content handler for this Result object
+	try {
+	    // Result object could be SAXResult, DOMResult, or StreamResult 
+	    if (result instanceof SAXResult) {
+                final SAXResult target = (SAXResult)result;
+                final ContentHandler handler = target.getHandler();
 
-	// If a DOMResult, then we must set the DOM Tree so it can
-	// be retrieved later 
-	if (result instanceof DOMResult) {
-	    ((DOMResult)result).setNode(((SAX2DOM)_handler).getDOM());
+		_tohFactory.setHandler(handler);
+		if (handler instanceof LexicalHandler) {
+		    _tohFactory.setLexicalHandler((LexicalHandler) handler);
+		}
+		_tohFactory.setOutputType(TransletOutputHandlerFactory.SAX);
+		return _tohFactory.getTransletOutputHandler();
+            }
+	    else if (result instanceof DOMResult) {
+		_tohFactory.setNode(((DOMResult) result).getNode());
+		_tohFactory.setOutputType(TransletOutputHandlerFactory.DOM);
+		return _tohFactory.getTransletOutputHandler();
+            }
+	    else if (result instanceof StreamResult) {
+		// Get StreamResult
+		final StreamResult target = (StreamResult) result;	
+
+		// StreamResult may have been created with a java.io.File,
+		// java.io.Writer, java.io.OutputStream or just a String
+		// systemId. 
+
+		_tohFactory.setOutputType(TransletOutputHandlerFactory.STREAM);
+
+		// try to get a Writer from Result object
+		final Writer writer = target.getWriter();
+		if (writer != null) {
+		    _tohFactory.setWriter(writer);
+		    return _tohFactory.getTransletOutputHandler();
+		}
+
+		// or try to get an OutputStream from Result object
+		final OutputStream ostream = target.getOutputStream();
+		if (ostream != null) {
+		    _tohFactory.setOutputStream(ostream);
+		    return _tohFactory.getTransletOutputHandler();
+		}
+
+		// or try to get just a systemId string from Result object
+		String systemId = result.getSystemId();
+		if (systemId == null) {
+		    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_RESULT_ERR);
+                    throw new TransformerException(err.toString());
+		}
+
+		// System Id may be in one of several forms, (1) a uri
+		// that starts with 'file:', (2) uri that starts with 'http:'
+		// or (3) just a filename on the local system.
+		URL url = null;
+		if (systemId.startsWith("file:")) {
+                    url = new URL(systemId);
+		    _tohFactory.setOutputStream(
+			new FileOutputStream(url.getFile()));
+		    return _tohFactory.getTransletOutputHandler();
+                }
+                else if (systemId.startsWith("http:")) {
+                    url = new URL(systemId);
+                    final URLConnection connection = url.openConnection();
+		    _tohFactory.setOutputStream(connection.getOutputStream());
+		    return _tohFactory.getTransletOutputHandler();
+                }
+                else {
+                    // system id is just a filename
+                    url = new File(systemId).toURL();
+		    _tohFactory.setOutputStream(
+			new FileOutputStream(url.getFile()));
+		    return _tohFactory.getTransletOutputHandler();
+                }
+	    }
 	}
+        // If we cannot write to the location specified by the SystemId
+        catch (UnknownServiceException e) {
+            throw new TransformerException(e);
+        }
+        catch (ParserConfigurationException e) {
+            throw new TransformerException(e);
+        }
+        // If we cannot create the file specified by the SystemId
+        catch (IOException e) {
+            throw new TransformerException(e);
+        }
+	return null;
     }
 
     /**
@@ -190,7 +345,7 @@
      * based on the type and contents of the TrAX Result object passed to
      * the transform() method. 
      */
-    private ContentHandler getOutputHandler(Result result) throws 
+    private ContentHandler getOldOutputHandler(Result result) throws 
  	TransformerException 
     {
 	// Try to get the encoding from the translet (may not be set)
@@ -211,7 +366,7 @@
                 if (handler != null) return handler;
             }
 	    else if (result instanceof DOMResult) {
-                return (new SAX2DOM());
+                return new SAX2DOM(((DOMResult) result).getNode());
             }
 	    else if (result instanceof StreamResult) {
 		// Get StreamResult
@@ -281,80 +436,6 @@
 	return null;
     }
 
-
-/*************
-    private ContentHandler getOutputHandler(Result result) 
-	throws TransformerException {
-	// Try to get the encoding from Translet (may not be set)
-	if (_translet._encoding != null) {
-	    _encoding = _translet._encoding;
-	}
-	else {
-	    _encoding = "UTF-8"; // default output encoding
-	}
-
-	try {
-	    String systemId = result.getSystemId();
-
-	    // Handle SAXResult output handler
-	    if (result instanceof SAXResult) {
-		final SAXResult target = (SAXResult)result;
-		final ContentHandler handler = target.getHandler();
-		// Simple as feck, just pass the SAX handler back...
-		if (handler != null) return handler;
-	    }
-	    // Handle StreamResult output handler
-	    else if (result instanceof StreamResult) {
-		final StreamResult target = (StreamResult)result;
-		final OutputStream ostream = target.getOutputStream();
-		final Writer writer = target.getWriter();
-
-		if (ostream != null)
-		    return (new DefaultSAXOutputHandler(ostream, _encoding));
-		else if (writer != null)
-		    return (new DefaultSAXOutputHandler(writer, _encoding));
-		else if ((systemId != null) && systemId.startsWith("file:")) {
-		    final URL url = new URL(systemId);
-		    final OutputStream os = new FileOutputStream(url.getFile());
-		    return (new DefaultSAXOutputHandler(os, _encoding));
-		}
-	    }
-	    // Handle DOMResult output handler
-	    else if (result instanceof DOMResult) {
-		return (new SAX2DOM());
-	    }
-
-	    // Common, final handling of all input sources, only used if the
-	    // other contents of the Result object could not be used
-	    if (systemId != null) {
-		if ((new File(systemId)).exists()) systemId = "file:"+systemId;
-		final URL url = new URL(systemId);
-		final URLConnection connection = url.openConnection();
-		final OutputStream ostream = connection.getOutputStream();
-		return(new DefaultSAXOutputHandler(ostream, _encoding));
-	    }
-	    else {
-		ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_RESULT_ERR);
-		throw new TransformerException(err.toString());
-	    }
-	}
-	// If we cannot write to the location specified by the SystemId
-	catch (UnknownServiceException e) {
-	    throw new TransformerException(e);
-	}
-	// If we cannot create a SAX2DOM adapter
-	catch (ParserConfigurationException e) {
-	    ErrorMsg err = new ErrorMsg(ErrorMsg.SAX2DOM_ADAPTER_ERR);
-	    throw new TransformerException(err.toString());
-	}
-	// If we cannot create the file specified by the SystemId
-	catch (IOException e) {
-	    throw new TransformerException(e);
-	}
-    }
-
-**********************/
-
     /**
      * Set the internal DOMImpl that will be used for the next transformation
      */
@@ -363,18 +444,19 @@
     }
 
     /**
+     * Set the internal DOMImpl that will be used for the next transformation
+     */
+    protected void setDTDMonitor(DTDMonitor dtdMonitor) {
+	_dtdMonitor = dtdMonitor;
+    }
+
+    /**
      * Builds an internal DOM from a TrAX Source object
      */
     private DOMImpl getDOM(Source source, int mask)
-	throws TransformerException {
+	throws TransformerException 
+    {
 	try {
-	    // Use the pre-defined DOM if present
-	    if (_dom != null) {
-		DOMImpl dom = _dom;
-		_dom = null; // use only once, so reset to 'null'
-		return(dom);
-	    }
-
 	    DOMImpl dom = null;
 	    DTDMonitor dtd = null;
 
@@ -382,10 +464,18 @@
 	    if (source instanceof SAXSource) {
 		// Get all info from the input SAXSource object
 		final SAXSource   sax    = (SAXSource)source;
-		final XMLReader   reader = sax.getXMLReader();
+		XMLReader   reader = sax.getXMLReader();
 		final InputSource input  = sax.getInputSource();
 		final String      systemId = sax.getSystemId();
 
+		// if reader was not set with setXMLReader by user,
+		// then we must create one ourselves.
+		if (reader == null) {
+		    SAXParserFactory pfactory= SAXParserFactory.newInstance();
+		    pfactory.setNamespaceAware(true);
+		    reader = pfactory.newSAXParser().getXMLReader();
+		}
+
 		// Create a DTD monitor to trap all DTD/declarative events
 		dtd = new DTDMonitor();
 		dtd.handleDTD(reader);
@@ -409,8 +499,14 @@
 	    // Handle DOMSource input
 	    else if (source instanceof DOMSource) {
 		final DOMSource   domsrc = (DOMSource)source;
-		final Document    tree = (Document)domsrc.getNode();
-		final DOM2SAX     dom2sax = new DOM2SAX(tree);
+		final org.w3c.dom.Node node = domsrc.getNode();
+
+		boolean isComplete = true;
+		if (node.getNodeType() != org.w3c.dom.Node.DOCUMENT_NODE) {
+		    isComplete = false;
+		}
+
+		final DOM2SAX     dom2sax = new DOM2SAX(node);
 		final InputSource input = null; 
 		final String      systemId = domsrc.getSystemId(); 
 
@@ -425,7 +521,13 @@
 		dom2sax.setContentHandler(builder);
 
 		// Parse the input and build the internal DOM
+		if (!isComplete) {
+		    builder.startDocument();
+		}
 		dom2sax.parse(input); // need this parameter?
+		if (!isComplete) {
+		    builder.endDocument();
+		}
 		dom.setDocumentURI(systemId);
 	    }
 	    // Handle StreamSource input
@@ -465,13 +567,15 @@
 		reader.setContentHandler(builder);
 
 		InputSource input;
-		if (streamInput != null)
+		if (streamInput != null) {
 		    input = new InputSource(streamInput);
-		else if (streamReader != null)
+		    input.setSystemId(systemId); 
+		} else if (streamReader != null) {
 		    input = new InputSource(streamReader);
-		else if (systemId != null)
+		    input.setSystemId(systemId); 
+		} else if (systemId != null) {
 		    input = new InputSource(systemId);
-		else {
+		} else {
 		    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_SOURCE_ERR);
 		    throw new TransformerException(err.toString());
 		}
@@ -486,6 +590,11 @@
 		dtd = xsltcsrc.getDTD();
 		dom = xsltcsrc.getDOM();
 	    }
+	    // DOM already set via a call to setDOM()
+	    else if (_dom != null) {
+		dtd = _dtdMonitor;	   // must be set via setDTDMonitor()
+		dom = _dom; _dom = null;   // use only once, so reset to 'null'
+	    }
 	    else {
 		return null;
 	    }
@@ -519,23 +628,45 @@
     /**
      * Internal transformation method - uses the internal APIs of XSLTC
      */
+    private void transform(Source src, TransletOutputHandler handler, 
+	String encoding) throws TransformerException 
+    {
+	try {
+	    _translet.transform(getDOM(src, 0), handler);
+	}
+	catch (TransletException e) {
+	    if (_errorListener != null)	postErrorToListener(e.getMessage());
+	    throw new TransformerException(e);
+	}
+	catch (RuntimeException e) {
+	    if (_errorListener != null)	postErrorToListener(e.getMessage());
+	    throw new TransformerException(e);
+	}
+	catch (Exception e) {
+	    if (_errorListener != null)	postErrorToListener(e.getMessage());
+	    throw new TransformerException(e);
+	}
+    }
+
+    /**
+     * Internal transformation method - uses the internal APIs of XSLTC
+     */
     private void transform(Source src, ContentHandler sax, String encoding)
 	throws TransformerException {
 	try {
 	    // Build an iternal DOMImpl from the TrAX Source
 	    DOMImpl dom = getDOM(src, 0);
 
-	    // Pass output properties to the translet
-	    setOutputProperties(_translet, _properties);
-	    
 	    // This handler will post-process the translet output
 	    TextOutput handler;
 
 	    // Check if the ContentHandler also implements LexicalHandler
-	    if (sax instanceof LexicalHandler)
+	    if (sax instanceof LexicalHandler) {
 		handler = new TextOutput(sax, (LexicalHandler)sax, encoding);
-	    else
+	    }
+	    else {
 		handler = new TextOutput(sax, encoding);
+	    }
 	    _translet.transform(dom, handler);
 	}
 	catch (TransletException e) {
@@ -640,7 +771,7 @@
      * @return Properties in effect for this Transformer
      */
     public Properties getOutputProperties() {
-	return(_properties);
+	return (Properties) _properties.clone();
     }
 
     /**
@@ -653,12 +784,13 @@
      * @throws IllegalArgumentException if the property name is not known
      */
     public String getOutputProperty(String name)
-	throws IllegalArgumentException {
+	throws IllegalArgumentException 
+    {
 	if (!validOutputProperty(name)) {
 	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
 	    throw new IllegalArgumentException(err.toString());
 	}
-	return(_properties.getProperty(name));
+	return _properties.getProperty(name);
     }
 
     /**
@@ -671,8 +803,29 @@
      * @throws IllegalArgumentException Never, errors are ignored
      */
     public void setOutputProperties(Properties properties)
-	throws IllegalArgumentException {
-	_properties.putAll(properties);
+	throws IllegalArgumentException 
+    {
+	if (properties != null) {
+	    final Enumeration names = properties.propertyNames();
+
+	    while (names.hasMoreElements()) {
+		final String name = (String) names.nextElement();
+
+		// Ignore lower layer properties
+		if (isDefaultProperty(name, properties)) continue;
+
+		if (validOutputProperty(name)) {
+		    _properties.setProperty(name, properties.getProperty(name));
+		}
+		else {
+		    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
+		    throw new IllegalArgumentException(err.toString());
+		}
+	    }
+	}
+	else {
+	    _properties = _propertiesClone;
+	}
     }
 
     /**
@@ -686,7 +839,8 @@
      * @throws IllegalArgumentException Never, errors are ignored
      */
     public void setOutputProperty(String name, String value)
-	throws IllegalArgumentException {
+	throws IllegalArgumentException 
+    {
 	if (!validOutputProperty(name)) {
 	    ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNKNOWN_PROP_ERR, name);
 	    throw new IllegalArgumentException(err.toString());
@@ -699,43 +853,50 @@
      * initiating the transformation
      */
     private void setOutputProperties(AbstractTranslet translet,
-				     Properties properties) {
+				     Properties properties) 
+    {
 	// Return right now if no properties are set
 	if (properties == null) return;
 
 	// Get a list of all the defined properties
 	Enumeration names = properties.propertyNames();
 	while (names.hasMoreElements()) {
-	    // Get the next property name and value
-	    String name  = (String)names.nextElement();
-	    String value = (String)properties.get(name);
+	    // Note the use of get() instead of getProperty()
+	    String name  = (String) names.nextElement();
+	    String value = (String) properties.get(name);
+
+	    // Ignore default properties
+	    if (value == null) continue;
 
 	    // Pass property value to translet - override previous setting
-	    if (name.equals(OutputKeys.ENCODING))
+	    if (name.equals(OutputKeys.ENCODING)) {
 		translet._encoding = value;
-	    else if (name.equals(OutputKeys.METHOD))
+	    }
+	    else if (name.equals(OutputKeys.METHOD)) {
 		translet._method = value;
-	    else if (name.equals(OutputKeys.DOCTYPE_PUBLIC))
+	    }
+	    else if (name.equals(OutputKeys.DOCTYPE_PUBLIC)) {
 		translet._doctypePublic = value;
-	    else if (name.equals(OutputKeys.DOCTYPE_SYSTEM))
+	    }
+	    else if (name.equals(OutputKeys.DOCTYPE_SYSTEM)) {
 		translet._doctypeSystem = value;
-	    else if (name.equals(OutputKeys.MEDIA_TYPE))
+	    }
+	    else if (name.equals(OutputKeys.MEDIA_TYPE)) {
 		translet._mediaType = value;
-	    else if (name.equals(OutputKeys.STANDALONE))
+	    }
+	    else if (name.equals(OutputKeys.STANDALONE)) {
 		translet._standalone = value;
-	    else if (name.equals(OutputKeys.VERSION))
+	    }
+	    else if (name.equals(OutputKeys.VERSION)) {
 		translet._version = value;
+	    }
 	    else if (name.equals(OutputKeys.OMIT_XML_DECLARATION)) {
-		if ((value != null) && (value.toLowerCase().equals("yes")))
-		    translet._omitHeader = true;
-		else
-		    translet._omitHeader = false;
+		translet._omitHeader = 
+		    (value != null && value.toLowerCase().equals("yes"));
 	    }
 	    else if (name.equals(OutputKeys.INDENT)) {
-		if ((value != null) && (value.toLowerCase().equals("yes")))
-		    translet._indent = true;
-		else
-		    translet._indent = false;
+		translet._indent = 
+		    (value != null && value.toLowerCase().equals("yes"));
 	    }
 	    else if (name.equals(OutputKeys.CDATA_SECTION_ELEMENTS)) {
 		if (value != null) {
@@ -750,68 +911,45 @@
     }
 
     /**
-     * Internal method to pass any properties to the translet prior to
-     * initiating the transformation
+     * Internal method to create the initial set of properties. There
+     * are two layers of properties: the default layer and the base layer.
+     * The latter contains properties defined in the stylesheet or by
+     * the user using this API.
      */
-    private Properties createOutputProperties() {
-	
-	// Level3: Return the default property value
-	Properties third = new Properties();
-	third.setProperty(OutputKeys.ENCODING, "UTF-8");
-	third.setProperty(OutputKeys.METHOD, XML_STRING);
-	third.setProperty(OutputKeys.INDENT, NO_STRING);
-	third.setProperty(OutputKeys.DOCTYPE_PUBLIC, EMPTY_STRING);
-	third.setProperty(OutputKeys.DOCTYPE_SYSTEM, EMPTY_STRING);
-	third.setProperty(OutputKeys.CDATA_SECTION_ELEMENTS, EMPTY_STRING);
-	third.setProperty(OutputKeys.MEDIA_TYPE, "text/xml");
-	third.setProperty(OutputKeys.OMIT_XML_DECLARATION, NO_STRING);
-	third.setProperty(OutputKeys.STANDALONE, NO_STRING);
-	third.setProperty(OutputKeys.VERSION, "1.0");
+    private Properties createOutputProperties(Properties outputProperties) {
+	final Properties defaults = new Properties();
+	defaults.setProperty(OutputKeys.ENCODING, "UTF-8");
+	defaults.setProperty(OutputKeys.METHOD, XML_STRING);
+	defaults.setProperty(OutputKeys.INDENT, NO_STRING);
+	defaults.setProperty(OutputKeys.MEDIA_TYPE, "text/xml");
+	defaults.setProperty(OutputKeys.OMIT_XML_DECLARATION, NO_STRING);
+	defaults.setProperty(OutputKeys.STANDALONE, NO_STRING);
+	defaults.setProperty(OutputKeys.VERSION, "1.0");
 
-	// Level2: Return the property value is set in the translet
-	// Creating these properties with the third-level properties as default
-	Properties second = new Properties(third);
-	if (_translet != null) {
-	    String value = _translet._encoding;
-	    if (value != null) second.setProperty(OutputKeys.ENCODING, value);
-
-	    value = _translet._method;
-	    if (value != null) second.setProperty(OutputKeys.METHOD, value);
-
-	    if (_translet._indent)
-		second.setProperty(OutputKeys.INDENT, "yes");
-	    else
-		second.setProperty(OutputKeys.INDENT, "no");
-
-	    value = _translet._doctypePublic;
-	    if (value != null) 
-		second.setProperty(OutputKeys.DOCTYPE_PUBLIC, value);
-
-	    value = _translet._doctypeSystem;
-	    if (value != null) 
-		second.setProperty(OutputKeys.DOCTYPE_SYSTEM, value);
-
-	    value = makeCDATAString(_translet._cdata);
-	    if (value != null) 
-		second.setProperty(OutputKeys.CDATA_SECTION_ELEMENTS,value);
-
-	    value = _translet._mediaType;
-	    if (value != null) second.setProperty(OutputKeys.MEDIA_TYPE, value);
-
-	    if (_translet._omitHeader)
-		second.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
-	    else
-		second.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
-
-	    value = _translet._standalone;
-	    if (value != null) second.setProperty(OutputKeys.STANDALONE, value);
-
-	    value = _translet._version;
-	    if (value != null) second.setProperty(OutputKeys.VERSION, value);
+	// Copy propeties set in stylesheet to base
+	final Properties base = new Properties(defaults);
+	if (outputProperties != null) {
+	    final Enumeration names = outputProperties.propertyNames();
+	    while (names.hasMoreElements()) {
+		final String name = (String) names.nextElement();
+		base.setProperty(name, outputProperties.getProperty(name));
+	    }
 	}
 
-	// Creating the properties with the second-level properties as default
-	return(new Properties(second));
+	// Update defaults based on output method
+	final String method = base.getProperty(OutputKeys.METHOD);
+	if (method != null) {
+	    if (method.equals("html")) {
+		defaults.setProperty(OutputKeys.INDENT, "yes");
+		defaults.setProperty(OutputKeys.VERSION, "4.0");
+		defaults.setProperty(OutputKeys.MEDIA_TYPE, "text/html");
+	    }
+	    else if (method.equals("text")) {
+		defaults.setProperty(OutputKeys.MEDIA_TYPE, "text/plain");
+	    }
+	}
+
+	return base; 
     }
 
     /**
@@ -819,18 +957,24 @@
      * the JAXP 1.1 / TrAX spec
      */
     private boolean validOutputProperty(String name) {
-	if (name.equals(OutputKeys.ENCODING)) return true;
-	if (name.equals(OutputKeys.METHOD)) return true;
-	if (name.equals(OutputKeys.INDENT)) return true;
-	if (name.equals(OutputKeys.DOCTYPE_PUBLIC)) return true;
-	if (name.equals(OutputKeys.DOCTYPE_SYSTEM)) return true;
-	if (name.equals(OutputKeys.CDATA_SECTION_ELEMENTS)) return true;
-	if (name.equals(OutputKeys.MEDIA_TYPE)) return true;
-	if (name.equals(OutputKeys.OMIT_XML_DECLARATION)) return true;
-	if (name.equals(OutputKeys.STANDALONE)) return true;
-	if (name.equals(OutputKeys.VERSION)) return true;
-	if (name.charAt(0) == '{') return true;
-	return false;
+	return (name.equals(OutputKeys.ENCODING) ||
+		name.equals(OutputKeys.METHOD) ||
+		name.equals(OutputKeys.INDENT) ||
+		name.equals(OutputKeys.DOCTYPE_PUBLIC) ||
+		name.equals(OutputKeys.DOCTYPE_SYSTEM) ||
+		name.equals(OutputKeys.CDATA_SECTION_ELEMENTS) ||
+		name.equals(OutputKeys.MEDIA_TYPE) ||
+		name.equals(OutputKeys.OMIT_XML_DECLARATION)   ||
+		name.equals(OutputKeys.STANDALONE) ||
+		name.equals(OutputKeys.VERSION) ||
+		name.charAt(0) == '{');
+    }
+
+    /**
+     * Checks if a given output property is default (2nd layer only)
+     */
+    private boolean isDefaultProperty(String name, Properties properties) {
+	return (properties.get(name) == null);
     }
 
     /**
@@ -924,8 +1068,9 @@
      * the transformation (always does in our case).
      */
     public void error(TransformerException e)
-	throws TransformerException {
-	System.err.println("ERROR: "+e.getMessageAndLocation());
+	throws TransformerException 
+    {
+	System.err.println("ERROR: " + e.getMessageAndLocation());
 	throw(e); 	
     }
 
@@ -943,11 +1088,13 @@
      * the transformation (always does in our case).
      */
     public void fatalError(TransformerException e)
-	throws TransformerException {
-	System.err.println("FATAL: "+e.getMessageAndLocation());
+	throws TransformerException 
+    {
+	System.err.println("FATAL: " + e.getMessageAndLocation());
 	Throwable wrapped = e.getException();
-	if (wrapped != null)
+	if (wrapped != null) {
 	    System.err.println("     : "+wrapped.getMessage());
+	}
 	throw(e);
     }
 
@@ -965,11 +1112,13 @@
      * the transformation (never does in our case).
      */
     public void warning(TransformerException e)
-	throws TransformerException {
-	System.err.println("WARNING: "+e.getMessageAndLocation());
+	throws TransformerException 
+    {
+	System.err.println("WARNING: " + e.getMessageAndLocation());
 	Throwable wrapped = e.getException();
-	if (wrapped != null)
+	if (wrapped != null) {
 	    System.err.println("       : "+wrapped.getMessage());
+	}
     }
 
 }
diff --git a/src/org/apache/xalan/xsltc/util/IntegerArray.java b/src/org/apache/xalan/xsltc/util/IntegerArray.java
index c3a2297..f416018 100644
--- a/src/org/apache/xalan/xsltc/util/IntegerArray.java
+++ b/src/org/apache/xalan/xsltc/util/IntegerArray.java
@@ -87,7 +87,9 @@
     }
 
     public Object clone() {
-	return new IntegerArray(_array);
+	final IntegerArray clone = new IntegerArray(_array);
+	clone._free = _free;
+	return clone;
     }
 
     public int[] toIntArray() {
@@ -105,23 +107,24 @@
     }
 
     public int indexOf(int n) {
-	for (int i = 0; i < _free; i++)
-	    if (n == _array[i])
-		return i;
+	for (int i = 0; i < _free; i++) {
+	    if (n == _array[i]) return i;
+	}
 	return -1;
     }
 
     public final void add(int value) {
-	if (_free == _size)
+	if (_free == _size) {
 	    growArray(_size * 2);
+	}
 	_array[_free++] = value;
     }
   
     /** adds new int at the end if not already present */
     public void addNew(int value) {
-	for (int i = 0; i < _free; i++)
-	    if (_array[i] == value)	// already in array
-		return;
+	for (int i = 0; i < _free; i++) {
+	    if (_array[i] == value) return;  // already in array
+	}
 	add(value);
     }
 
@@ -163,7 +166,8 @@
 	    }
 	    out.println(_array[_free - 1]);
 	}
-	else
+	else {
 	    out.println("IntegerArray: empty");
+	}
     }
 }
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