You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mk...@apache.org on 2003/04/01 21:24:58 UTC

cvs commit: xml-xalan/java/src/org/apache/xml/serializer AttributesImplSerializer.java CharInfo.java DOMSerializer.java ElemDesc.java EmptySerializer.java EncodingInfo.java Encodings.java Encodings.properties ExtendedContentHandler.java ExtendedLexicalHandler.java HTMLEntities.res Method.java NamespaceMappings.java OutputPropertiesFactory.java OutputPropertyUtils.java SerializationHandler.java Serializer.java SerializerBase.java SerializerConstants.java SerializerFactory.java SerializerTrace.java SerializerTraceWriter.java ToHTMLSAXHandler.java ToHTMLStream.java ToSAXHandler.java ToStream.java ToTextSAXHandler.java ToTextStream.java ToUnknownStream.java ToXMLSAXHandler.java ToXMLStream.java TransformStateSetter.java WriterToASCI.java WriterToUTF8.java WriterToUTF8Buffered.java XMLEntities.res XSLOutputAttributes.java output_html.properties output_text.properties output_unknown.properties output_xml.properties package.html

mkwan       2003/04/01 11:24:57

  Added:       java/src/org/apache/xml/serializer
                        AttributesImplSerializer.java CharInfo.java
                        DOMSerializer.java ElemDesc.java
                        EmptySerializer.java EncodingInfo.java
                        Encodings.java Encodings.properties
                        ExtendedContentHandler.java
                        ExtendedLexicalHandler.java HTMLEntities.res
                        Method.java NamespaceMappings.java
                        OutputPropertiesFactory.java
                        OutputPropertyUtils.java SerializationHandler.java
                        Serializer.java SerializerBase.java
                        SerializerConstants.java SerializerFactory.java
                        SerializerTrace.java SerializerTraceWriter.java
                        ToHTMLSAXHandler.java ToHTMLStream.java
                        ToSAXHandler.java ToStream.java
                        ToTextSAXHandler.java ToTextStream.java
                        ToUnknownStream.java ToXMLSAXHandler.java
                        ToXMLStream.java TransformStateSetter.java
                        WriterToASCI.java WriterToUTF8.java
                        WriterToUTF8Buffered.java XMLEntities.res
                        XSLOutputAttributes.java output_html.properties
                        output_text.properties output_unknown.properties
                        output_xml.properties package.html
  Log:
  Merging XSLTC_DTM and common serializer to the head
  
  Add new serializer classes under package org.apache.xml.serializer.
  
  Log from Brian Minchau (minchau@ca.ibm.com):
  
  In the past Xalan-J interpretive (Xalan) and XSLTC both implemented their own
  serialization stages.  Much of the code provides the same functionality.
  In order to improve the maintainability of the code, and to eliminate any
  functional differences, these two serializers are now merged in the
  org.apache.xml.serializer package.
  
  The best performing features of both have been used.  The class hierarchy
  of serializers used by XSLTC is re-used for this reason. At the highest
  level the serializer classes split based on whether the output of the
  serializer is a "Stream" or whether it is a "SAX" handler.  After that
  both major branches split based on the output type (e.g. XML, HTML or TEXT).
  
  The external user interface of the old Xalan serializer has been kept.
  Other classes and interfaces have been absorbed into the serializer
  package to keep it independent of both Xalan and XSLTC. The primary
  interface, SerializationHandler, accepts SAX and SAX-like calls, but
  it also absorbs other interfaces from the old Xalan serializer.
  
  Revision  Changes    Path
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/AttributesImplSerializer.java
  
  Index: AttributesImplSerializer.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2003 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) 2003, International Business
   * Machines, Inc., http://www.ibm.com.  For more information on the Apache
   * Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.xml.serializer;
  
  import java.util.Hashtable;
  
  import org.xml.sax.Attributes;
  import org.xml.sax.helpers.AttributesImpl;
  
  /**
   * This class extends org.xml.sax.helpers.AttributesImpl which implements org.
   * xml.sax.Attributes. But for optimization this class adds a Hashtable for
   * faster lookup of an index by qName, which is commonly done in the stream
   * serializer.
   * 
   * @see org.xml.sax.Attributes
   */
  public class AttributesImplSerializer extends AttributesImpl
  {
      /**
       * Hash table of qName/index values to quickly lookup the index
       * of an attributes qName.  qNames are in uppercase in the hash table
       * to make the search case insensitive.
       */
      private Hashtable m_indexFromQName = new Hashtable();
      
      /**
       * This method gets the index of an attribute given its qName.
       * @param qname the qualified name of the attribute, e.g. "prefix1:locName1"
       * @return the integer index of the attribute.
       * @see org.xml.sax.Attributes#getIndex(String)
       */
      public int getIndex(String qname)
      {
          int index;
          Integer i = (Integer) m_indexFromQName.get(qname);
          if (i==null)
              index = -1;
          else
              index = i.intValue();
          return index;
      }
      /**
       * This method adds the attribute, but also records its qName/index pair in
       * the hashtable for fast lookup by getIndex(qName).
       * @param uri the URI of the attribute
       * @param local the local name of the attribute
       * @param qname the qualified name of the attribute
       * @param type the type of the attribute
       * @param val the value of the attribute
       *
       * @see org.xml.sax.helpers.AttributesImpl#addAttribute(String, String, String, String, String)
       * @see getIndex(String)
       */
      public void addAttribute(
      String uri, String local, String qname, String type, String val)
      {
          int index = super.getLength();
          super.addAttribute(uri,local,qname,type,val);
          
          /* we have just added the attibute, its index is the old length */
          Integer i = new Integer(index);
          m_indexFromQName.put(qname, i);
      }
      
  
      /**
       * This method clears the accumulated attributes.
       *
       * @see org.xml.sax.helpers.AttributesImpl#clear()
       */
      public void clear()
      {
          m_indexFromQName.clear();
          super.clear();
      }    
      
      /**
       * This method sets the attributes, previous attributes are cleared,
       * it also keeps the hashtable up to date for quick lookup via
       * getIndex(qName).
       * @param atts the attributes to copy into these attributes.
       * @see org.xml.sax.helpers.AttributesImpl#setAttributes(Attributes)
       * @see getIndex(String)
       */
      public void setAttributes(Attributes atts)
      {
          super.setAttributes(atts);
          
          // we've let the super class add the attributes, but
          // we need to keep the hash table up to date ourselves for the
          // potentially new qName/index pairs for quick lookup. 
          int numAtts = atts.getLength();
          for (int i=0; i < numAtts; i++)
          {
              String qName = atts.getQName(i);
              int index = super.getIndex(qName);
              Integer io = new Integer(index);
              m_indexFromQName.put(qName, io);            
              
          }
      }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/CharInfo.java
  
  Index: CharInfo.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.io.BufferedReader;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.net.URL;
  import java.util.BitSet;
  import java.util.Hashtable;
  
  import org.apache.xml.res.XMLErrorResources;
  import org.apache.xml.res.XMLMessages;
  import org.apache.xml.utils.CharKey;
  import org.apache.xml.utils.SystemIDResolver;
  import org.apache.xml.utils.SystemIDResolver;
  
  /**
   * This class provides services that tell if a character should have
   * special treatement, such as entity reference substitution or normalization
   * of a newline character.  It also provides character to entity reference
   * lookup.
   *
   * DEVELOPERS: See Known Issue in the constructor.
   */
  public class CharInfo
  {
  
      /** Bit map that tells if a given character should have special treatment. */
      BitSet m_specialsMap = new BitSet(65535);
  
      /** Lookup table for characters to entity references. */
      private Hashtable m_charToEntityRef = new Hashtable();
  
      /**
       * The name of the HTML entities file.
       * If specified, the file will be resource loaded with the default class loader.
       */
      public static String HTML_ENTITIES_RESOURCE = "HTMLEntities.res";
  
      /**
       * The name of the XML entities file.
       * If specified, the file will be resource loaded with the default class loader.
       */
      public static String XML_ENTITIES_RESOURCE = "XMLEntities.res";
  
      /** The linefeed character, which the parser should always normalize. */
      public static final char S_LINEFEED = 0x0A;
  
      /** The carriage return character, which the parser should always normalize. */
      public static char S_CARRIAGERETURN = 0x0D;
  
      /**
       * Constructor that reads in a resource file that describes the mapping of
       * characters to entity references.
       *
       * Resource files must be encoded in UTF-8 and have a format like:
       * <pre>
       * # First char # is a comment
       * Entity numericValue
       * quot 34
       * amp 38
       * </pre>
       * (Note: Why don't we just switch to .properties files? Oct-01 -sc)
       *
       * @param entitiesResource Name of entities resource file that should
       * be loaded, which describes that mapping of characters to entity references.
       */
      public CharInfo(String entitiesResource)
      {
  
          InputStream is = null;
          BufferedReader reader = null;
          int index;
          String name;
          String value;
          int code;
          String line;
  
          try
          {
              try
              {
                  // Maintenance note: we should evaluate replacing getting the 
                  //  ClassLoader with javax.xml.transform.FactoryFinder.findClassLoader()
                  //  or similar code
                  ClassLoader cl = CharInfo.class.getClassLoader();
  
                  if (cl == null)
                  {
                      is =
                          ClassLoader.getSystemResourceAsStream(entitiesResource);
                  }
                  else
                  {
                      is = cl.getResourceAsStream(entitiesResource);
                  }
              }
              catch (Exception e)
              {
              }
  
              if (is == null)
                  is = CharInfo.class.getResourceAsStream(entitiesResource);
  
              if (is == null)
              {
                  URL url = new URL(entitiesResource);
  
                  is = url.openStream();
              }
  
              if (is == null)
                  throw new RuntimeException(
                      XMLMessages.createXMLMessage(
                          XMLErrorResources.ER_RESOURCE_COULD_NOT_FIND,
                          new Object[] { entitiesResource, entitiesResource }));
  
              // Fix Bugzilla#4000: force reading in UTF-8
              //  This creates the de facto standard that Xalan's resource 
              //  files must be encoded in UTF-8. This should work in all JVMs.
              //
              // %REVIEW% KNOWN ISSUE: IT FAILS IN MICROSOFT VJ++, which
              // didn't implement the UTF-8 encoding. Theoretically, we should
              // simply let it fail in that case, since the JVM is obviously
              // broken if it doesn't support such a basic standard.  But
              // since there are still some users attempting to use VJ++ for
              // development, we have dropped in a fallback which makes a
              // second attempt using the platform's default encoding. In VJ++
              // this is apparently ASCII, which is subset of UTF-8... and
              // since the strings we'll be reading here are also primarily
              // limited to the 7-bit ASCII range (at least, in English
              // versions of Xalan), this should work well enough to keep us
              // on the air until we're ready to officially decommit from
              // VJ++.
              try
              {
                  reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
              }
              catch (java.io.UnsupportedEncodingException e)
              {
                  reader = new BufferedReader(new InputStreamReader(is));
              }
  
              line = reader.readLine();
  
              while (line != null)
              {
                  if (line.length() == 0 || line.charAt(0) == '#')
                  {
                      line = reader.readLine();
  
                      continue;
                  }
  
                  index = line.indexOf(' ');
  
                  if (index > 1)
                  {
                      name = line.substring(0, index);
  
                      ++index;
  
                      if (index < line.length())
                      {
                          value = line.substring(index);
                          index = value.indexOf(' ');
  
                          if (index > 0)
                              value = value.substring(0, index);
  
                          code = Integer.parseInt(value);
  
                          defineEntity(name, (char) code);
                      }
                  }
  
                  line = reader.readLine();
              }
  
              is.close();
              m_specialsMap.set(S_LINEFEED);
              m_specialsMap.set(S_CARRIAGERETURN);
          }
          catch (Exception except)
          {
              throw new RuntimeException(
                  XMLMessages.createXMLMessage(
                      XMLErrorResources.ER_RESOURCE_COULD_NOT_LOAD,
                      new Object[] {
                          entitiesResource,
                          except.toString(),
                          entitiesResource,
                          except.toString()}));
          }
          finally
          {
              if (is != null)
              {
                  try
                  {
                      is.close();
                  }
                  catch (Exception except)
                  {
                  }
              }
          }
      }
  
      /**
       * Defines a new character reference. The reference's name and value are
       * supplied. Nothing happens if the character reference is already defined.
       * <p>Unlike internal entities, character references are a string to single
       * character mapping. They are used to map non-ASCII characters both on
       * parsing and printing, primarily for HTML documents. '&lt;amp;' is an
       * example of a character reference.</p>
       *
       * @param name The entity's name
       * @param value The entity's value
       */
      protected void defineEntity(String name, char value)
      {
          CharKey character = new CharKey(value);
  
          m_charToEntityRef.put(character, name);
          m_specialsMap.set(value);
      }
  
      private CharKey m_charKey = new CharKey();
  
      /**
       * Resolve a character to an entity reference name.
       *
       * This is reusing a stored key object, in an effort to avoid
       * heap activity. Unfortunately, that introduces a threading risk.
       * Simplest fix for now is to make it a synchronized method, or to give
       * up the reuse; I see very little performance difference between them.
       * Long-term solution would be to replace the hashtable with a sparse array
       * keyed directly from the character's integer value; see DTM's
       * string pool for a related solution.
       *
       * @param value character value that should be resolved to a name.
       *
       * @return name of character entity, or null if not found.
       */
      synchronized public String getEntityNameForChar(char value)
      {
          // CharKey m_charKey = new CharKey(); //Alternative to synchronized
          m_charKey.setChar(value);
          return (String) m_charToEntityRef.get(m_charKey);
      }
  
      /**
       * Tell if the character argument should have special treatment.
       *
       * @param value character value.
       *
       * @return true if the character should have any special treatment, such as
       * when writing out attribute values, or entity references.
       */
      public boolean isSpecial(char value)
      {
          return m_specialsMap.get(value);
      }
  
      /** Table of user-specified char infos. */
      private static Hashtable m_getCharInfo_cache = null;
  
      /**
       * Factory that reads in a resource file that describes the mapping of
       * characters to entity references.
       *
       * Resource files must be encoded in UTF-8 and have a format like:
       * <pre>
       * # First char # is a comment
       * Entity numericValue
       * quot 34
       * amp 38
       * </pre>
       * (Note: Why don't we just switch to .properties files? Oct-01 -sc)
       *
       * @param entitiesResource Name of entities resource file that should
       * be loaded, which describes that mapping of characters to entity references.
       */
      public static CharInfo getCharInfo(String entitiesFileName)
      {
          CharInfo retobj = null;
          if (null == m_getCharInfo_cache)
          {
              // synchronize on any object, just to have a lock while creating the cache.
              synchronized (XML_ENTITIES_RESOURCE)
              {
                  if (null == m_getCharInfo_cache) // secondary check
                      m_getCharInfo_cache = new Hashtable();
              }
          }
          else
          {
              // the cache already exists, so lets try to find it.
              retobj = (CharInfo) m_getCharInfo_cache.get(entitiesFileName);
          }
          if (retobj == null)
          {
              // try to load it.
              try
              {
                  retobj = new CharInfo(entitiesFileName);
                  m_getCharInfo_cache.put(entitiesFileName, retobj);
              }
              catch (Exception e)
              {
                  retobj = null;
              }
          }
          if (null == retobj)
          {
              String absoluteEntitiesFileName;
  
              if (entitiesFileName.indexOf(':') < 0)
              {
                  absoluteEntitiesFileName =
                      SystemIDResolver.getAbsoluteURIFromRelative(
                          entitiesFileName);
              }
              else
              {
                  try
                  {
                      absoluteEntitiesFileName =
                          SystemIDResolver.getAbsoluteURI(entitiesFileName, null);
                  }
                  catch (javax.xml.transform.TransformerException te)
                  {
                      throw new org.apache.xml.utils.WrappedRuntimeException(te);
                  }
              }
              retobj = new CharInfo(absoluteEntitiesFileName);
              m_getCharInfo_cache.put(entitiesFileName, retobj);
          }
          return retobj;
      }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/DOMSerializer.java
  
  Index: DOMSerializer.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.io.IOException;
  
  import org.w3c.dom.Node;
  
  /**
   * Interface for a DOM serializer implementation.
   * <p>
   * The DOM serializer is a facet of a serializer. A serializer may or may
   * not support a DOM serializer.
   * <p>
   * Example:
   * <pre>
   * Document     doc;
   * Serializer   ser;
   * OutputStream os;
   *
   * ser.setOutputStream( os );
   * ser.asDOMSerializer( doc );
   * </pre>
   *
   *
   * @version Alpha
   * @author <a href="mailto:Scott_Boag/CAM/Lotus@lotus.com">Scott Boag</a>
   * @author <a href="mailto:arkin@exoffice.com">Assaf Arkin</a>
   */
  public interface DOMSerializer
  {
      /**
       * Serializes the DOM node. Throws an exception only if an I/O
       * exception occured while serializing.
       *
       * @param elem The element to serialize
       * @throws IOException An I/O exception occured while serializing
       */
      public void serialize(Node node) throws IOException;
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ElemDesc.java
  
  Index: ElemDesc.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import org.apache.xml.utils.StringToIntTable;
  
  /**
   * This class has a series of flags (bit values) that describe an HTML element
   */
  class ElemDesc
  {
      /** Bit flags to tell about this element type. */
      int m_flags;
  
      /**
       * Table of attribute names to integers, which contain bit flags telling about
       *  the attributes.
       */
      StringToIntTable m_attrs = null;
  
      /** Bit position if this element type is empty. */
      static final int EMPTY = (1 << 1);
  
      /** Bit position if this element type is a flow. */
      static final int FLOW = (1 << 2);
  
      /** Bit position if this element type is a block. */
      static final int BLOCK = (1 << 3);
  
      /** Bit position if this element type is a block form. */
      static final int BLOCKFORM = (1 << 4);
  
      /** Bit position if this element type is a block form field set (?? -sb). */
      static final int BLOCKFORMFIELDSET = (1 << 5);
  
      /** Bit position if this element type is CDATA. */
      static final int CDATA = (1 << 6);
  
      /** Bit position if this element type is PCDATA. */
      static final int PCDATA = (1 << 7);
  
      /** Bit position if this element type is should be raw characters. */
      static final int RAW = (1 << 8);
  
      /** Bit position if this element type should be inlined. */
      static final int INLINE = (1 << 9);
  
      /** Bit position if this element type is INLINEA (?? -sb). */
      static final int INLINEA = (1 << 10);
  
      /** Bit position if this element type is an inline label. */
      static final int INLINELABEL = (1 << 11);
  
      /** Bit position if this element type is a font style. */
      static final int FONTSTYLE = (1 << 12);
  
      /** Bit position if this element type is a phrase. */
      static final int PHRASE = (1 << 13);
  
      /** Bit position if this element type is a form control. */
      static final int FORMCTRL = (1 << 14);
  
      /** Bit position if this element type is ???. */
      static final int SPECIAL = (1 << 15);
  
      /** Bit position if this element type is ???. */
      static final int ASPECIAL = (1 << 16);
  
      /** Bit position if this element type is an odd header element. */
      static final int HEADMISC = (1 << 17);
  
      /** Bit position if this element type is a head element (i.e. H1, H2, etc.) */
      static final int HEAD = (1 << 18);
  
      /** Bit position if this element type is a list. */
      static final int LIST = (1 << 19);
  
      /** Bit position if this element type is a preformatted type. */
      static final int PREFORMATTED = (1 << 20);
  
      /** Bit position if this element type is whitespace sensitive. */
      static final int WHITESPACESENSITIVE = (1 << 21);
  
      /** Bit position if this element type is a header element (i.e. HEAD). */
      static final int HEADELEM = (1 << 22);
  
      /** Bit position if this attribute type is a URL. */
      static final int ATTRURL = (1 << 1);
  
      /** Bit position if this attribute type is an empty type. */
      static final int ATTREMPTY = (1 << 2);
  
      /**
       * Construct an ElemDesc from a set of bit flags.
       *
       *
       * @param flags Bit flags that describe the basic properties of this element type.
       */
      ElemDesc(int flags)
      {
          m_flags = flags;
      }
  
      /**
       * Tell if this element type has the basic bit properties that are passed
       * as an argument.
       *
       * @param flags Bit flags that describe the basic properties of interest.
       *
       * @return true if any of the flag bits are true.
       */
      boolean is(int flags)
      {
  
          // int which = (m_flags & flags);
          return (m_flags & flags) != 0;
      }
  
      /**
       * Set an attribute name and it's bit properties.
       *
       *
       * @param name non-null name of attribute, in upper case.
       * @param flags flag bits.
       */
      void setAttr(String name, int flags)
      {
  
          if (null == m_attrs)
              m_attrs = new StringToIntTable();
  
          m_attrs.put(name, flags);
      }
  
      /**
       * Tell if any of the bits of interest are set for a named attribute type.
       *
       * @param name non-null reference to attribute name, in any case.
       * @param flags flag mask.
       *
       * @return true if any of the flags are set for the named attribute.
       */
      boolean isAttrFlagSet(String name, int flags)
      {
          return (null != m_attrs)
              ? ((m_attrs.getIgnoreCase(name) & flags) != 0)
              : false;
      }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/EmptySerializer.java
  
  Index: EmptySerializer.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2003 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) 2003, International Business
   * Machines, Inc., http://www.ibm.com.  For more information on the Apache
   * Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.Writer;
  import java.util.Hashtable;
  import java.util.Properties;
  import java.util.Vector;
  
  import javax.xml.transform.SourceLocator;
  import javax.xml.transform.Transformer;
  
  import org.w3c.dom.Node;
  import org.xml.sax.Attributes;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  import org.xml.sax.SAXParseException;
  
  /**
   * This class is an adapter class. Its only purpose is to be extended and
   * for that extended class to over-ride all methods that are to be used. 
   */
  public class EmptySerializer implements SerializationHandler
  {
      protected static final String ERR = "EmptySerializer method not over-ridden";
      /**
       * @see org.apache.xml.serializer.SerializationHandler#asContentHandler()
       */
  
      private static void throwUnimplementedException()
      {
          /* TODO: throw this exception for real.
           * Some users of this class do not over-ride all methods that 
           * they use, which is a violation of the intended use of this
           * class. Those tests used to end in error, but fail when this
           * exception is enabled.  Perhaps that is an indication of what
           * the true problem is.  Such tests include copy56,58,59,60 for 
           * both Xalan-J interpretive and for XSLTC. - bjm
           */
          // throw new RuntimeException(err);
          return;
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#asContentHandler()
       */
      public ContentHandler asContentHandler() throws IOException
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setContentHandler(org.xml.sax.ContentHandler)
       */
      public void setContentHandler(ContentHandler ch)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#close()
       */
      public void close()
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#getOutputFormat()
       */
      public Properties getOutputFormat()
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#getOutputStream()
       */
      public OutputStream getOutputStream()
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#getWriter()
       */
      public Writer getWriter()
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#reset()
       */
      public boolean reset()
      {
          throwUnimplementedException();
          return false;
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#serialize(org.w3c.dom.Node)
       */
      public void serialize(Node node) throws IOException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setCdataSectionElements(java.util.Vector)
       */
      public void setCdataSectionElements(Vector URI_and_localNames)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setEscaping(boolean)
       */
      public boolean setEscaping(boolean escape) throws SAXException
      {
          throwUnimplementedException();
          return false;
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setIndent(boolean)
       */
      public void setIndent(boolean indent)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setIndentAmount(int)
       */
      public void setIndentAmount(int spaces)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setOutputFormat(java.util.Properties)
       */
      public void setOutputFormat(Properties format)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setOutputStream(java.io.OutputStream)
       */
      public void setOutputStream(OutputStream output)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setVersion(java.lang.String)
       */
      public void setVersion(String version)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setWriter(java.io.Writer)
       */
      public void setWriter(Writer writer)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setTransformer(javax.xml.transform.Transformer)
       */
      public void setTransformer(Transformer transformer)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#getTransformer()
       */
      public Transformer getTransformer()
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#flushPending()
       */
      public void flushPending()
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
       */
      public void addAttribute(
          String uri,
          String localName,
          String rawName,
          String type,
          String value)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#addAttributes(org.xml.sax.Attributes)
       */
      public void addAttributes(Attributes atts) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(java.lang.String, java.lang.String)
       */
      public void addAttribute(String name, String value)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#characters(java.lang.String)
       */
      public void characters(String chars) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#endElement(java.lang.String)
       */
      public void endElement(String elemName) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#startDocument()
       */
      public void startDocument() throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String)
       */
      public void startElement(String uri, String localName, String qName)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#startElement(java.lang.String)
       */
      public void startElement(String qName) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#namespaceAfterStartElement(java.lang.String, java.lang.String)
       */
      public void namespaceAfterStartElement(String uri, String prefix)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#startPrefixMapping(java.lang.String, java.lang.String, boolean)
       */
      public boolean startPrefixMapping(
          String prefix,
          String uri,
          boolean shouldFlush)
          throws SAXException
      {
          throwUnimplementedException();
          return false;
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#entityReference(java.lang.String)
       */
      public void entityReference(String entityName) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#getNamespaceMappings()
       */
      public NamespaceMappings getNamespaceMappings()
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#getPrefix(java.lang.String)
       */
      public String getPrefix(String uri)
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#getNamespaceURI(java.lang.String, boolean)
       */
      public String getNamespaceURI(String name, boolean isElement)
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#getNamespaceURIFromPrefix(java.lang.String)
       */
      public String getNamespaceURIFromPrefix(String prefix)
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
       */
      public void setDocumentLocator(Locator arg0)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ContentHandler#endDocument()
       */
      public void endDocument() throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
       */
      public void startPrefixMapping(String arg0, String arg1)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
       */
      public void endPrefixMapping(String arg0) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
       */
      public void startElement(
          String arg0,
          String arg1,
          String arg2,
          Attributes arg3)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
       */
      public void endElement(String arg0, String arg1, String arg2)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ContentHandler#characters(char[], int, int)
       */
      public void characters(char[] arg0, int arg1, int arg2) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
       */
      public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
       */
      public void processingInstruction(String arg0, String arg1)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
       */
      public void skippedEntity(String arg0) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedLexicalHandler#comment(java.lang.String)
       */
      public void comment(String comment) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ext.LexicalHandler#startDTD(java.lang.String, java.lang.String, java.lang.String)
       */
      public void startDTD(String arg0, String arg1, String arg2)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ext.LexicalHandler#endDTD()
       */
      public void endDTD() throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ext.LexicalHandler#startEntity(java.lang.String)
       */
      public void startEntity(String arg0) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ext.LexicalHandler#endEntity(java.lang.String)
       */
      public void endEntity(String arg0) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ext.LexicalHandler#startCDATA()
       */
      public void startCDATA() throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ext.LexicalHandler#endCDATA()
       */
      public void endCDATA() throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int)
       */
      public void comment(char[] arg0, int arg1, int arg2) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#getDoctypePublic()
       */
      public String getDoctypePublic()
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#getDoctypeSystem()
       */
      public String getDoctypeSystem()
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#getEncoding()
       */
      public String getEncoding()
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#getIndent()
       */
      public boolean getIndent()
      {
          throwUnimplementedException();
          return false;
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#getIndentAmount()
       */
      public int getIndentAmount()
      {
          throwUnimplementedException();
          return 0;
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#getMediaType()
       */
      public String getMediaType()
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#getOmitXMLDeclaration()
       */
      public boolean getOmitXMLDeclaration()
      {
          throwUnimplementedException();
          return false;
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#getStandalone()
       */
      public String getStandalone()
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#getVersion()
       */
      public String getVersion()
      {
          throwUnimplementedException();
          return null;
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#setCdataSectionElements(java.util.Hashtable)
       */
      public void setCdataSectionElements(Hashtable h) throws Exception
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#setDoctype(java.lang.String, java.lang.String)
       */
      public void setDoctype(String system, String pub)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#setDoctypePublic(java.lang.String)
       */
      public void setDoctypePublic(String doctype)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#setDoctypeSystem(java.lang.String)
       */
      public void setDoctypeSystem(String doctype)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#setEncoding(java.lang.String)
       */
      public void setEncoding(String encoding)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#setMediaType(java.lang.String)
       */
      public void setMediaType(String mediatype)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#setOmitXMLDeclaration(boolean)
       */
      public void setOmitXMLDeclaration(boolean b)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#setStandalone(java.lang.String)
       */
      public void setStandalone(String standalone)
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ext.DeclHandler#elementDecl(java.lang.String, java.lang.String)
       */
      public void elementDecl(String arg0, String arg1) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ext.DeclHandler#attributeDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
       */
      public void attributeDecl(
          String arg0,
          String arg1,
          String arg2,
          String arg3,
          String arg4)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ext.DeclHandler#internalEntityDecl(java.lang.String, java.lang.String)
       */
      public void internalEntityDecl(String arg0, String arg1)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(java.lang.String, java.lang.String, java.lang.String)
       */
      public void externalEntityDecl(String arg0, String arg1, String arg2)
          throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
       */
      public void warning(SAXParseException arg0) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
       */
      public void error(SAXParseException arg0) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
       */
      public void fatalError(SAXParseException arg0) throws SAXException
      {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.Serializer#asDOMSerializer()
       */
      public DOMSerializer asDOMSerializer() throws IOException
      {
          throwUnimplementedException();
          return null;
      }
  
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setNamespaceMappings(NamespaceMappings)
       */
      public void setNamespaceMappings(NamespaceMappings mappings) {
          throwUnimplementedException();
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#setSourceLocator(javax.xml.transform.SourceLocator)
       */
      public void setSourceLocator(SourceLocator locator)
      {
          throwUnimplementedException();
      }
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/EncodingInfo.java
  
  Index: EncodingInfo.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  /**
   * Holds information about a given encoding, which is the Java name for the
   * encoding, the equivalent ISO name, and the integer value of the last pritable
   * character in the encoding.
   */
  public class EncodingInfo extends Object
  {
  
      /**
       * The ISO encoding name.
       */
      final String name;
  
      /**
       * The name used by the Java convertor.
       */
      final String javaName;
  
      /**
       * The last printable character.
       */
      final int lastPrintable;
  
      /**
       * Create an EncodingInfo object based on the name, java name, and the
       * max character size.
       *
       * @param name non-null reference to the ISO name.
       * @param javaName non-null reference to the Java encoding name.
       * @param lastPrintable The maximum character that can be written.
       */
      public EncodingInfo(String name, String javaName, int lastPrintable)
      {
  
          this.name = name;
          this.javaName = javaName;
          this.lastPrintable = lastPrintable;
      }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/Encodings.java
  
  Index: Encodings.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.io.OutputStreamWriter;
  import java.io.UnsupportedEncodingException;
  import java.io.Writer;
  import java.net.URL;
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Properties;
  import java.util.StringTokenizer;
  
  /**
   * Provides information about encodings. Depends on the Java runtime
   * to provides writers for the different encodings, but can be used
   * to override encoding names and provide the last printable character
   * for each encoding.
   *
   * @version $Revision: 1.1 $ $Date: 2003/04/01 19:24:54 $
   * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
   */
  public class Encodings extends Object
  {
  
      /**
       * The last printable character for unknown encodings.
       */
      static final int m_defaultLastPrintable = 0x7F;
  
      /**
       * Standard filename for properties file with encodings data.
       */
      static final String ENCODINGS_FILE =
          "org/apache/xml/serializer/Encodings.properties";
  
      /**
       * Standard filename for properties file with encodings data.
       */
      static final String ENCODINGS_PROP = "org.apache.xalan.serialize.encodings";
  
      /** a zero length Class array used in loadPropertyFile() */
      private static final Class[] NO_CLASSES = new Class[0];
  
      /** a zero length Object array used in loadPropertyFile() */
      private static final Object[] NO_OBJS = new Object[0];
  
      /**
       * Returns a writer for the specified encoding based on
       * an output stream.
       *
       * @param output The output stream
       * @param encoding The encoding
       * @return A suitable writer
       * @throws UnsupportedEncodingException There is no convertor
       *  to support this encoding
       */
      public static Writer getWriter(OutputStream output, String encoding)
          throws UnsupportedEncodingException
      {
  
          for (int i = 0; i < _encodings.length; ++i)
          {
              if (_encodings[i].name.equalsIgnoreCase(encoding))
              {
                  try
                  {
                      return new OutputStreamWriter(
                          output,
                          _encodings[i].javaName);
                  }
                  catch (java.lang.IllegalArgumentException iae) // java 1.1.8
                  {
                      // keep trying
                  }
                  catch (UnsupportedEncodingException usee)
                  {
  
                      // keep trying
                  }
              }
          }
  
          try
          {
              return new OutputStreamWriter(output, encoding);
          }
          catch (java.lang.IllegalArgumentException iae) // java 1.1.8
          {
              throw new UnsupportedEncodingException(encoding);
          }
      }
  
      /**
       * Returns an opaque CharToByte converter for the specified encoding.
       *
       * @param encoding The encoding
       * @return An object which should be a sun.io.CharToByteConverter, or null.
       */
      public static Object getCharToByteConverter(String encoding)
      {
  
          Class charToByteConverterClass = null;
          java.lang.reflect.Method getConverterMethod = null;
  
          try
          {
              charToByteConverterClass =
                  Class.forName("sun.io.CharToByteConverter");
              Class argTypes[] = new Class[1];
              argTypes[0] = String.class;
              getConverterMethod =
                  charToByteConverterClass.getMethod("getConverter", argTypes);
          }
          catch (Exception e)
          {
              System.err.println(
                  "Warning: Could not get charToByteConverterClass!");
              return null;
          }
          Object args[] = new Object[1];
          for (int i = 0; i < _encodings.length; ++i)
          {
              if (_encodings[i].name.equalsIgnoreCase(encoding))
              {
                  try
                  {
                      args[0] = _encodings[i].javaName;
                      Object converter = getConverterMethod.invoke(null, args);
                      if (null != converter)
                          return converter;
                  }
                  catch (Exception iae)
                  {
                      // keep trying
                  }
              }
          }
  
          return null;
      }
  
      /**
       * Returns the last printable character for the specified
       * encoding.
       *
       * @param encoding The encoding
       * @return The last printable character
       */
      public static int getLastPrintable(String encoding)
      {
          EncodingInfo ei;
  
          String normalizedEncoding = encoding.toUpperCase();
          ei = (EncodingInfo) _encodingTableKeyJava.get(normalizedEncoding);
          if (ei == null)
              ei = (EncodingInfo) _encodingTableKeyMime.get(normalizedEncoding);
          if (ei != null)
              return ei.lastPrintable;
          return m_defaultLastPrintable;
      }
  
      /**
       * Returns the last printable character for an unspecified
       * encoding.
       *
       * @return the default size
       */
      public static int getLastPrintable()
      {
          return m_defaultLastPrintable;
      }
  
      /** The default encoding, ISO style, ISO style.   */
      public static final String DEFAULT_MIME_ENCODING = "UTF-8";
  
      /**
       * Get the proper mime encoding.  From the XSLT recommendation: "The encoding
       * attribute specifies the preferred encoding to use for outputting the result
       * tree. XSLT processors are required to respect values of UTF-8 and UTF-16.
       * For other values, if the XSLT processor does not support the specified
       * encoding it may signal an error; if it does not signal an error it should
       * use UTF-8 or UTF-16 instead. The XSLT processor must not use an encoding
       * whose name does not match the EncName production of the XML Recommendation
       * [XML]. If no encoding attribute is specified, then the XSLT processor should
       * use either UTF-8 or UTF-16."
       *
       * @param encoding Reference to java-style encoding string, which may be null,
       * in which case a default will be found.
       *
       * @return The ISO-style encoding string, or null if failure.
       */
      public static String getMimeEncoding(String encoding)
      {
  
          if (null == encoding)
          {
              try
              {
  
                  // Get the default system character encoding.  This may be
                  // incorrect if they passed in a writer, but right now there
                  // seems to be no way to get the encoding from a writer.
                  encoding = System.getProperty("file.encoding", "UTF8");
  
                  if (null != encoding)
                  {
  
                      /*
                      * See if the mime type is equal to UTF8.  If you don't
                      * do that, then  convertJava2MimeEncoding will convert
                      * 8859_1 to "ISO-8859-1", which is not what we want,
                      * I think, and I don't think I want to alter the tables
                      * to convert everything to UTF-8.
                      */
                      String jencoding =
                          (encoding.equalsIgnoreCase("Cp1252")
                              || encoding.equalsIgnoreCase("ISO8859_1")
                              || encoding.equalsIgnoreCase("8859_1")
                              || encoding.equalsIgnoreCase("UTF8"))
                              ? DEFAULT_MIME_ENCODING
                              : convertJava2MimeEncoding(encoding);
  
                      encoding =
                          (null != jencoding) ? jencoding : DEFAULT_MIME_ENCODING;
                  }
                  else
                  {
                      encoding = DEFAULT_MIME_ENCODING;
                  }
              }
              catch (SecurityException se)
              {
                  encoding = DEFAULT_MIME_ENCODING;
              }
          }
          else
          {
              encoding = convertJava2MimeEncoding(encoding);
          }
  
          return encoding;
      }
  
      /**
       * Try the best we can to convert a Java encoding to a XML-style encoding.
       *
       * @param encoding non-null reference to encoding string, java style.
       *
       * @return ISO-style encoding string.
       */
      public static String convertJava2MimeEncoding(String encoding)
      {
          EncodingInfo enc =
              (EncodingInfo) _encodingTableKeyJava.get(encoding.toUpperCase());
          if (null != enc)
              return enc.name;
          return encoding;
      }
  
      /**
       * Try the best we can to convert a Java encoding to a XML-style encoding.
       *
       * @param encoding non-null reference to encoding string, java style.
       *
       * @return ISO-style encoding string.
       */
      public static String convertMime2JavaEncoding(String encoding)
      {
  
          for (int i = 0; i < _encodings.length; ++i)
          {
              if (_encodings[i].name.equalsIgnoreCase(encoding))
              {
                  return _encodings[i].javaName;
              }
          }
  
          return encoding;
      }
  
      /**
       * Load a list of all the supported encodings.
       *
       * System property "encodings" formatted using URL syntax may define an
       * external encodings list. Thanks to Sergey Ushakov for the code
       * contribution!
       */
      private static EncodingInfo[] loadEncodingInfo()
      {
          URL url = null;
          try
          {
              String urlString = null;
              try
              {
                  urlString = System.getProperty(ENCODINGS_PROP, "");
              }
              catch (SecurityException e)
              {
              }
  
              if (urlString != null && urlString.length() > 0)
                  url = new URL(urlString);
              if (url == null)
              {
                  ClassLoader cl = null;
                  try
                  {
                      java.lang.reflect.Method getCCL =
                          Thread.class.getMethod(
                              "getContextClassLoader",
                              NO_CLASSES);
                      if (getCCL != null)
                      {
                          cl =
                              (ClassLoader) getCCL.invoke(
                                  Thread.currentThread(),
                                  NO_OBJS);
                      }
                  }
                  catch (Exception e)
                  {
                  }
                  if (cl != null)
                  {
                      url = cl.getResource(ENCODINGS_FILE);
                  }
              }
              if (url == null)
                  url = ClassLoader.getSystemResource(ENCODINGS_FILE);
  
              Properties props = new Properties();
              if (url != null)
              {
                  InputStream is = url.openStream();
                  props.load(is);
                  is.close();
              }
              else
              {
                  // Seems to be no real need to force failure here, let the system
                  //   do its best... The issue is not really very critical, and the
                  //   output will be in any case _correct_ though maybe not always
                  //   human-friendly... :)
                  // But maybe report/log the resource problem?
                  // Any standard ways to report/log errors (in static context)?
              }
  
              int totalEntries = props.size();
              int totalMimeNames = 0;
              Enumeration keys = props.keys();
              for (int i = 0; i < totalEntries; ++i)
              {
                  String javaName = (String) keys.nextElement();
                  String val = props.getProperty(javaName);
                  totalMimeNames++;
                  int pos = val.indexOf(' ');
                  for (int j = 0; j < pos; ++j)
                      if (val.charAt(j) == ',')
                          totalMimeNames++;
              }
              EncodingInfo[] ret = new EncodingInfo[totalMimeNames];
              int j = 0;
              keys = props.keys();
              for (int i = 0; i < totalEntries; ++i)
              {
                  String javaName = (String) keys.nextElement();
                  String val = props.getProperty(javaName);
                  int pos = val.indexOf(' ');
                  String mimeName;
                  int lastPrintable;
                  if (pos < 0)
                  {
                      // Maybe report/log this problem?
                      //  "Last printable character not defined for encoding " +
                      //  mimeName + " (" + val + ")" ...
                      mimeName = val;
                      lastPrintable = 0x00FF;
                  }
                  else
                  {
                      lastPrintable =
                          Integer.decode(val.substring(pos).trim()).intValue();
                      StringTokenizer st =
                          new StringTokenizer(val.substring(0, pos), ",");
                      for (boolean first = true;
                          st.hasMoreTokens();
                          first = false)
                      {
                          mimeName = st.nextToken();
                          ret[j] =
                              new EncodingInfo(mimeName, javaName, lastPrintable);
                          _encodingTableKeyMime.put(
                              mimeName.toUpperCase(),
                              ret[j]);
                          if (first)
                              _encodingTableKeyJava.put(
                                  javaName.toUpperCase(),
                                  ret[j]);
                          j++;
                      }
                  }
              }
              return ret;
          }
          catch (java.net.MalformedURLException mue)
          {
              throw new org.apache.xml.utils.WrappedRuntimeException(mue);
          }
          catch (java.io.IOException ioe)
          {
              throw new org.apache.xml.utils.WrappedRuntimeException(ioe);
          }
      }
  
      private static final Hashtable _encodingTableKeyJava = new Hashtable();
      private static final Hashtable _encodingTableKeyMime = new Hashtable();
      private static final EncodingInfo[] _encodings = loadEncodingInfo();
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/Encodings.properties
  
  Index: Encodings.properties
  ===================================================================
  # <JAVA name encoding>, <PREFERRED name MIME>
  # Peter Smolik
  Cp1250 WINDOWS-1250 0x00FF
  # Patch attributed to havardw@underdusken.no (H�vard Wigtil)
  Cp1251 WINDOWS-1251 0x00FF
  Cp1252 WINDOWS-1252 0x00FF
  ISO8859_1 US-ASCII,ISO-8859-1 0x007F
  # Patch attributed to havardw@underdusken.no (H�vard Wigtil)
  ISO8859-1 ISO-8859-1 0x00FF
  ISO8859_2 ISO-8859-2 0x00FF
  # I'm going to apply "ISO8859-X" variant to all these, to be safe.
  ISO8859-2 ISO-8859-2 0x00FF
  ISO8859_3 ISO-8859-3 0x00FF
  ISO8859-3 ISO-8859-3 0x00FF
  ISO8859_4 ISO-8859-4 0x00FF
  ISO8859-4 ISO-8859-4 0x00FF
  ISO8859_5 ISO-8859-5 0x00FF
  ISO8859-5 ISO-8859-5 0x00FF
  ISO8859_6 ISO-8859-6 0x00FF
  ISO8859-6 ISO-8859-6 0x00FF
  ISO8859_7 ISO-8859-7 0x00FF
  ISO8859-7 ISO-8859-7 0x00FF
  ISO8859_8 ISO-8859-8 0x00FF
  ISO8859-8 ISO-8859-8 0x00FF
  ISO8859_9 ISO-8859-9 0x00FF
  ISO8859-9 ISO-8859-9 0x00FF
  # # ?
  8859_1 US-ASCII,ISO-8859-1 0x00FF
  8859_2 ISO-8859-2 0x00FF
  8859_3 ISO-8859-3 0x00FF
  8859_4 ISO-8859-4 0x00FF
  8859_5 ISO-8859-5 0x00FF
  8859_6 ISO-8859-6 0x00FF
  8859_7 ISO-8859-7 0x00FF
  8859_8 ISO-8859-8 0x00FF
  8859_9 ISO-8859-9 0x00FF
  8859-1 ISO-8859-1 0x00FF
  8859-2 ISO-8859-2 0x00FF
  8859-3 ISO-8859-3 0x00FF
  8859-4 ISO-8859-4 0x00FF
  8859-5 ISO-8859-5 0x00FF
  8859-6 ISO-8859-6 0x00FF
  8859-7 ISO-8859-7 0x00FF
  8859-8 ISO-8859-8 0x00FF
  8859-9 ISO-8859-9 0x00FF
  JIS ISO-2022-JP 0xFFFF
  ISO2022KR ISO-2022-KR 0xFFFF
  SJIS SHIFT_JIS 0xFFFF
  EUC_JP EUC-JP 0xFFFF
  EUC_KR EUC-KR 0xFFFF
  EUC_CN EUC-CN 0xFFFF
  EUC_TW EUC-TW 0xFFFF
  EUC_CN GB2312 0xFFFF
  EUC-JP EUC-JP 0xFFFF
  EUC-KR EUC-KR 0xFFFF
  EUC-CN EUC-CN 0xFFFF
  EUC-TW EUC-TW 0xFFFF
  EUC-CN GB2312 0xFFFF
  GB2312 GB2312 0xFFFF
  Big5 BIG5 0xFFFF
  EUCJIS EUC-JP 0xFFFF
  KSC5601 EUC-KR 0xFFFF
  KOI8_R KOI8-R 0xFFFF
  Cp037 EBCDIC-CP-US,EBCDIC-CP-CA,EBCDIC-CP-NL 0x00FF
  Cp277 EBCDIC-CP-DK,EBCDIC-CP-NO 0x00FF
  Cp278 EBCDIC-CP-FI,EBCDIC-CP-SE 0x00FF
  Cp280 EBCDIC-CP-IT 0x00FF
  Cp284 EBCDIC-CP-ES 0x00FF
  Cp285 EBCDIC-CP-GB 0x00FF
  Cp297 EBCDIC-CP-FR 0x00FF
  Cp420 EBCDIC-CP-AR1 0x00FF
  Cp424 EBCDIC-CP-HE 0x00FF
  Cp500 EBCDIC-CP-CH 0x00FF
  Cp870 EBCDIC-CP-ROECE,EBCDIC-CP-YU 0x00FF
  Cp871 EBCDIC-CP-IS 0x00FF
  Cp918 EBCDIC-CP-AR2 0x00FF
  Cp1047 IBM1047,IBM-1047 0x00FF
  MacTEC MacRoman 0x00FF
  ASCII ASCII,ISO-Latin-1 0x007F
  Unicode UNICODE,UTF-16 0xFFFF
  UTF8 UTF-8 0xFFFF
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ExtendedContentHandler.java
  
  Index: ExtendedContentHandler.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2003 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) 2003, International Business
   * Machines, Inc., http://www.ibm.com.  For more information on the Apache
   * Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import javax.xml.transform.SourceLocator;
  
  import org.xml.sax.SAXException;
  
  /**
   * This interface describes extensions to the SAX ContentHandler interface.
   * It is intended to be used by a serializer. The methods on this interface will
   * implement SAX- like behavior. This allows the gradual collection of
   * information rather than having it all up front. For example the call
   * <pre>
   * startElement(namespaceURI,localName,qName,atts)
   * </pre>
   * could be replaced with the calls
   * <pre>
   * startElement(namespaceURI,localName,qName)
   * addAttributes(atts)
   * </pre>
   * If there are no attributes the second call can be dropped. If attributes are
   * to be added one at a time with calls to
   * <pre>
   * addAttribute(namespaceURI, localName, qName, type, value)
   * </pre>
   */
  public interface ExtendedContentHandler extends org.xml.sax.ContentHandler
  {
      /**
       * Add at attribute to the current element
       * @param uri the namespace URI of the attribute name
       * @param localName the local name of the attribute (without prefix)
       * @param rawName the qualified name of the attribute
       * @param type the attribute type typically character data (CDATA)
       * @param value the value of the attribute
       * @throws SAXException
       */
      public void addAttribute(
          String uri,
          String localName,
          String rawName,
          String type,
          String value)
          throws SAXException;
      /**
       * Add attributes to the current element
       * @param atts the attributes to add.
       * @throws SAXException
       */
      public void addAttributes(org.xml.sax.Attributes atts)
          throws org.xml.sax.SAXException;
      /**
       * Add an attribute to the current element. The namespace URI of the
       * attribute will be calculated from the prefix of qName. The local name
       * will be derived from qName and the type will be assumed to be "CDATA".
       * @param qName
       * @param value
       */
      public void addAttribute(String qName, String value);
      /**
       * This method is used to notify of a character event, but passing the data
       * as a character String rather than the standard character array.
       * @param chars the character data
       * @throws SAXException
       */
      public void characters(String chars) throws SAXException;
      /**
       * This method is used to notify that an element has ended. Unlike the
       * standard SAX method
       * <pre>
       * endElement(namespaceURI,localName,qName)
       * </pre>
       * only the last parameter is passed. If needed the serializer can derive
       * the localName from the qualified name and derive the namespaceURI from
       * its implementation.
       * @param elemName the fully qualified element name.
       * @throws SAXException
       */
      public void endElement(String elemName) throws SAXException;
  
      /**
       * This method is used to notify that an element is starting.
       * This method is just like the standard SAX method
       * <pre>
       * startElement(uri,localName,qname,atts)
       * </pre>
       * but without the attributes.
       * @param uri the namespace URI of the element
       * @param localName the local name (without prefix) of the element
       * @param qName the qualified name of the element
       * 
       * @throws SAXException
       */
      public void startElement(String uri, String localName, String qName)
          throws org.xml.sax.SAXException;
  
      /**
       * This method is used to notify of the start of an element
       * @param qName the fully qualified name of the element
       * @throws SAXException
       */
      public void startElement(String qName) throws SAXException;
      /**
       * This method is used to notify that a prefix mapping is to start, but
       * after an element is started. The SAX method call
       * <pre>
       * startPrefixMapping(prefix,uri)
       * </pre>
       * is used just before an element starts and applies to the element to come,
       * not to the current element.  This method applies to the current element.
       * For example one could make the calls in this order:
       * <pre>
       * startElement("prfx8:elem9")
       * namespaceAfterStartElement("http://namespace8","prfx8")
       * </pre>
       * 
       * @param uri the namespace URI being declared
       * @param prefix the prefix that maps to the given namespace
       * @throws SAXException
       */
      public void namespaceAfterStartElement(String uri, String prefix)
          throws SAXException;
  
      /**
       * This method is used to notify that a prefix maping is to start, which can
       * be for the current element, or for the one to come.
       * @param prefix the prefix that maps to the given URI
       * @param uri the namespace URI of the given prefix
       * @param shouldFlush if true this call is like the SAX
       * startPrefixMapping(prefix,uri) call and the mapping applies to the
       * element to come.  If false the mapping applies to the current element.
       * @return boolean false if the prefix mapping was already in effect (in
       * other words we are just re-declaring), true if this is a new, never
       * before seen mapping for the element.
       * @throws SAXException
       */
      public boolean startPrefixMapping(
          String prefix,
          String uri,
          boolean shouldFlush)
          throws SAXException;
      /**
       * Notify of an entity reference.
       * @param entityName the name of the entity
       * @throws SAXException
       */
      public void entityReference(String entityName) throws SAXException;
  
      /**
       * This method returns an object that has the current namespace mappings in
       * effect.
       * 
       * @return NamespaceMappings an object that has the current namespace
       * mappings in effect.
       */
      public NamespaceMappings getNamespaceMappings();
      /**
       * This method returns the prefix that currently maps to the given namespace
       * URI.
       * @param uri the namespace URI
       * @return String the prefix that currently maps to the given URI.
       */
      public String getPrefix(String uri);
      /**
       * This method gets the prefix associated with a current element or
       * attribute name.
       * @param name the qualified name of an element, or attribute
       * @param isElement true if it is an element name, false if it is an
       * atttribute name
       * @return String the namespace URI associated with the element or
       * attribute.
       */
      public String getNamespaceURI(String name, boolean isElement);
      /**
       * This method returns the namespace URI currently associated with the
       * prefix.
       * @param prefix a prefix of an element or attribute.
       * @return String the namespace URI currently associated with the prefix.
       */
      public String getNamespaceURIFromPrefix(String prefix);
  
      /**
       * This method is used to set the source locator, which might be used to
       * generated an error message.
       * @param locator the source locator
       */
      public void setSourceLocator(SourceLocator locator);
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ExtendedLexicalHandler.java
  
  Index: ExtendedLexicalHandler.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2003 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) 2003, International Business
   * Machines, Inc., http://www.ibm.com.  For more information on the Apache
   * Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import org.xml.sax.SAXException;
  
  /**
   * This interface has extensions to the standard SAX LexicalHandler interface.
   * This interface is intended to be used by a serializer.
   */
  public interface ExtendedLexicalHandler extends org.xml.sax.ext.LexicalHandler
  {
      /**
       * This method is used to notify of a comment
       * @param comment the comment, but unlike the SAX comment() method this
       * method takes a String rather than a character array.
       * @throws SAXException
       */
      public void comment(String comment) throws SAXException;
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/HTMLEntities.res
  
  Index: HTMLEntities.res
  ===================================================================
  # $Id: HTMLEntities.res,v 1.1 2003/04/01 19:24:54 mkwan Exp $
  # in ./java/src/org/apache/xml/serializer
  #
  # @version $Revision: 1.1 $ $Date: 2003/04/01 19:24:54 $
  # @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
  # This file must be encoded in UTF-8; see org.apache.xml.serializer.CharInfo
  #
  # Character entity references for markup-significant
  #
  quot 34
  amp 38
  lt 60
  gt 62
  nbsp 160
  #
  # Character entity references for ISO 8859-1 characters
  #
  iexcl 161
  cent 162
  pound 163
  curren 164
  yen 165
  brvbar 166
  sect 167
  uml 168
  copy 169
  ordf 170
  laquo 171
  not 172
  shy 173
  reg 174
  macr 175
  deg 176
  plusmn 177
  sup2 178
  sup3 179
  acute 180
  micro 181
  para 182
  middot 183
  cedil 184
  sup1 185
  ordm 186
  raquo 187
  frac14 188
  frac12 189
  frac34 190
  iquest 191
  Agrave 192
  Aacute 193
  Acirc 194
  Atilde 195
  Auml 196
  Aring 197
  AElig 198
  Ccedil 199
  Egrave 200
  Eacute 201
  Ecirc 202
  Euml 203
  Igrave 204
  Iacute 205
  Icirc 206
  Iuml 207
  ETH 208
  Ntilde 209
  Ograve 210
  Oacute 211
  Ocirc 212
  Otilde 213
  Ouml 214
  times 215
  Oslash 216
  Ugrave 217
  Uacute 218
  Ucirc 219
  Uuml 220
  Yacute 221
  THORN 222
  szlig 223
  agrave 224
  aacute 225
  acirc 226
  atilde 227
  auml 228
  aring 229
  aelig 230
  ccedil 231
  egrave 232
  eacute 233
  ecirc 234
  euml 235
  igrave 236
  iacute 237
  icirc 238
  iuml 239
  eth 240
  ntilde 241
  ograve 242
  oacute 243
  ocirc 244
  otilde 245
  ouml 246
  divide 247
  oslash 248
  ugrave 249
  uacute 250
  ucirc 251
  uuml 252
  yacute 253
  thorn 254
  yuml 255
  #
  # Character entity references for symbols, mathematical symbols, and Greek letters
  #
  # Latin Extended -- Netscape can't handle
  # fnof 402
  #
  # Greek - Netscape can't handle these
  # Alpha 913
  # Beta 914
  # Gamma 915
  # Delta 916
  # Epsilon 917
  # Zeta 918
  # Eta 919
  # Theta 920
  # Iota 921
  # Kappa 922
  # Lambda 923
  # Mu 924
  # Nu 925
  # Xi 926
  # Omicron 927
  # Pi 928
  # Rho 929
  # Sigma 931
  # Tau 932
  # Upsilon 933
  # Phi 934
  # Chi 935
  # Psi 936
  # Omega 937
  # alpha 945
  # beta 946
  # gamma 947
  # delta 948
  # epsilon 949
  # zeta 950
  # eta 951
  # theta 952
  # iota 953
  # kappa 954
  # lambda 955
  # mu 956
  # nu 957
  # xi 958
  # omicron 959
  # pi 960
  # rho 961
  # sigmaf 962
  # sigma 963
  # tau 964
  # upsilon 965
  # phi 966
  # chi 967
  # psi 968
  # omega 969
  # thetasym 977
  # upsih 978
  # piv 982
  #
  # General Punctuation
  bull 8226
  hellip 8230
  prime 8242
  Prime 8243
  oline 8254
  frasl 8260
  #
  # Letterlike Symbols
  weierp 8472
  image 8465
  real 8476
  trade 8482
  alefsym 8501
  #
  # Arrows
  larr 8592
  uarr 8593
  rarr 8594
  darr 8595
  harr 8596
  crarr 8629
  lArr 8656
  uArr 8657
  rArr 8658
  dArr 8659
  hArr 8660
  #
  # Mathematical Operators
  forall 8704
  part 8706
  exist 8707
  empty 8709
  nabla 8711
  isin 8712
  notin 8713
  ni 8715
  prod 8719
  sum 8721
  minus 8722
  lowast 8727
  radic 8730
  prop 8733
  infin 8734
  ang 8736
  and 8743
  or 8744
  cap 8745
  cup 8746
  int 8747
  there4 8756
  sim 8764
  cong 8773
  asymp 8776
  ne 8800
  equiv 8801
  le 8804
  ge 8805
  sub 8834
  sup 8835
  nsub 8836
  sube 8838
  supe 8839
  oplus 8853
  otimes 8855
  perp 8869
  sdot 8901
  #
  # Miscellaneous Technical
  lceil 8968
  rceil 8969
  lfloor 8970
  rfloor 8971
  lang 9001
  rang 9002
  #
  # Geometric Shapes
  loz 9674
  #
  # Miscellaneous Symbols
  spades 9824
  clubs 9827
  hearts 9829
  diams 9830
  #
  # Character entity references for internationalization characters
  #
  # Latin Extended-A
  # Netscape can't handle!
  # OElig 338
  # oelig 339
  
  #-- NN 4.7 does not seem to support these, so they might ought to be commented.
  # Scaron 352
  # scaron 353
  # Yuml 376
  #
  # Spacing Modifier Letters -- Netscape can't handle
  # circ 710
  # tilde 732
  #
  # General Punctuation
  ensp 8194
  emsp 8195
  thinsp 8201
  zwnj 8204
  zwj 8205
  lrm 8206
  rlm 8207
  ndash 8211
  mdash 8212
  lsquo 8216
  rsquo 8217
  sbquo 8218
  ldquo 8220
  rdquo 8221
  bdquo 8222
  dagger 8224
  Dagger 8225
  permil 8240
  lsaquo 8249
  rsaquo 8250
  euro 8364
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/Method.java
  
  Index: Method.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  /**
   * This class defines the constants which are the names of the four default
   * output methods.
   * <p>
   * Four default output methods are defined: XML, HTML, XHTML and TEXT.
   * Serializers may support additional output methods. The names of
   * these output methods should be encoded as <tt>namespace:local</tt>.
   *
   * @version Alpha
   * @author <a href="mailto:arkin@exoffice.com">Assaf Arkin</a>
   */
  public final class Method
  {
  
    /**
     * The output method for XML documents: <tt>xml</tt>.
     */
    public static final String XML = "xml";
  
    /**
     * The output method for HTML documents: <tt>html</tt>.
     */
    public static final String HTML = "html";
  
    /**
     * The output method for XHTML documents: <tt>xhtml</tt>.
     */
    public static final String XHTML = "xhtml";
  
    /**
     * The output method for text documents: <tt>text</tt>.
     */
    public static final String TEXT = "text";
    
    /**
     * The "internal" method, just used when no method is 
     * specified in the style sheet, and a serializer of this type wraps either an
     * XML or HTML type (depending on the first tag in the output being html or
     * not)
     */  
    public static final String UNKNOWN = "";
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/NamespaceMappings.java
  
  Index: NamespaceMappings.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2003 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) 2003, International Business
   * Machines, Inc., http://www.ibm.com.  For more information on the Apache
   * Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Stack;
  
  /**
   * This class keeps track of the currently defined namespaces. Conceptually the
   * prefix/uri/depth triplets are pushed on a stack pushed on a stack. The depth
   * indicates the nesting depth of the element for which the mapping was made.
   * 
   * <p>For example:
   * <pre>
   * <chapter xmlns:p1="def">
   *   <paragraph xmlns:p2="ghi">
   *      <sentance xmlns:p3="jkl">
   *      </sentance>
   *    </paragraph>
   *    <paragraph xlmns:p4="mno">
   *    </paragraph>
   * </chapter>
   * </pre>
   * 
   * When the <chapter> element is encounted the prefix "p1" associated with uri
   * "def" is pushed on the stack with depth 1.
   * When the first <paragraph> is encountered "p2" and "ghi" are pushed with
   * depth 2.
   * When the <sentance> is encountered "p3" and "jkl" are pushed with depth 3.
   * When </sentance> occurs the popNamespaces(3) will pop "p3"/"jkl" off the
   * stack.  Of course popNamespaces(2) would pop anything with depth 2 or
   * greater.
   * 
   * So prefix/uri pairs are pushed and poped off the stack as elements are
   * processed.  At any given moment of processing the currently visible prefixes
   * are on the stack and a prefix can be found given a uri, or a uri can be found
   * given a prefix.
   */
  public class NamespaceMappings
  {
      /**
       * This member is continually incremented when new prefixes need to be
       * generated. ("ns0"  "ns1" ...)
       */
      private int count = 0;
  
      /**
       * Stack of prefixes that have mappings
       * The top of this stack is the prefix that was last mapped to an URI
       * 
       * For every prefix pushed on this stack a corresponding integer is pushed
       * on the m_nodeStack. That way all prefixes pushed at the current depth can
       * be removed at the same time.      
       */
      private java.util.Stack m_prefixStack;
  
      /**
       * Each entry (prefix) in this hashtable points to a Stack of URIs
       */
      private Hashtable m_namespaces;
  
      /** 
       * The top of this stack contains the nested element depth
       * of the last declared a namespace.
       * Used to know how many prefix mappings to pop when leaving
       * the current element depth.
       * For every prefix mapping the current element depth is 
       * pushed on this stack, as well as the prefix on the m_prefixStack
       * That way all prefixes pushed at the current depth can be 
       * removed at the same time.
       * Used to ensure prefix/uri map scopes are closed correctly
       *
       */
      private Stack m_nodeStack;
  
      private static final String EMPTYSTRING = "";
      private static final String XML_PREFIX = "xml"; // was "xmlns"
  
      /**
       * Default constructor
       * @see java.lang.Object#Object()
       */
      public NamespaceMappings()
      {
          initNamespaces();
      }
  
      /**
       * This method initializes the namespace object with appropriate stacks
       * and predefines a few prefix/uri pairs which always exist.
       */
      private void initNamespaces()
      {
          // Namespaces
          m_namespaces = new Hashtable();
          m_nodeStack = new Stack();
          m_prefixStack = new Stack();
  
          // Define the default namespace (initially maps to "" uri)
          Stack stack;
          m_namespaces.put(EMPTYSTRING, stack = new Stack());
          stack.push(EMPTYSTRING);
          m_prefixStack.push(EMPTYSTRING);
  
          m_namespaces.put(XML_PREFIX, stack = new Stack());
          stack.push("http://www.w3.org/XML/1998/namespace");
          m_prefixStack.push(XML_PREFIX);
  
          m_nodeStack.push(new Integer(-1));
  
      }
  
      /**
       * Use a namespace prefix to lookup a namespace URI.
       * 
       * @param prefix String the prefix of the namespace
       * @return the URI corresponding to the prefix
       */
      public String lookupNamespace(String prefix)
      {
          final Stack stack = (Stack) m_namespaces.get(prefix);
          return stack != null && !stack.isEmpty() ? (String) stack.peek() : null;
      }
  
      /**
       * Given a namespace uri, and the namespaces mappings for the 
       * current element, return the current prefix for that uri.
       * 
       * @param uri the namespace URI to be search for
       * @return an existing prefix that maps to the given URI, null if no prefix
       * maps to the given namespace URI.
       */
      public String lookupPrefix(String uri)
      {
          String foundPrefix = null;
          Enumeration prefixes = m_namespaces.keys();
          while (prefixes.hasMoreElements())
          {
              String prefix = (String) prefixes.nextElement();
              String uri2 = lookupNamespace(prefix);
              if (uri2 != null && uri2.equals(uri))
              {
                  foundPrefix = prefix;
                  break;
              }
          }
          return foundPrefix;
      }
  
      /**
       * Undeclare the namespace that is currently pointed to by a given prefix
       */
      public boolean popNamespace(String prefix)
      {
          // Prefixes "xml" and "xmlns" cannot be redefined
          if (prefix.startsWith(XML_PREFIX))
          {
              return false;
          }
  
          Stack stack;
          if ((stack = (Stack) m_namespaces.get(prefix)) != null)
          {
              stack.pop();
              return true;
          }
          return false;
      }
  
      /**
       * Declare a prefix to point to a namespace URI
       * @param prefix a String with the prefix for a qualified name
       * @param uri a String with the uri to which the prefix is to map
       * @param elemDepth the depth of current declaration
       */
      public boolean pushNamespace(String prefix, String uri, int elemDepth)
      {
          // 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) m_namespaces.get(prefix)) == null)
          {
              m_namespaces.put(prefix, stack = new Stack());
          }
  
          if (!stack.empty() && uri.equals(stack.peek()))
          {
              return false;
          }
  
          stack.push(uri);
          m_prefixStack.push(prefix);
          m_nodeStack.push(new Integer(elemDepth));
          return true;
      }
  
      /**
       * Pop, or undeclare all namespace definitions that are currently
       * declared at the given element depth, or deepter.
       * @param elemDepth the element depth for which mappings declared at this
       * depth or deeper will no longer be valid
       */
      public void popNamespaces(int elemDepth)
      {
          while (true)
          {
              if (m_nodeStack.isEmpty())
                  return;
              Integer i = (Integer) (m_nodeStack.peek());
              if (i.intValue() < elemDepth)
                  return;
              /* the depth of the declared mapping is elemDepth or deeper
               * so get rid of it
               */
  
              m_nodeStack.pop();
              popNamespace((String) m_prefixStack.pop());
          }
      }
  
      /**
       * Generate a new namespace prefix ( ns0, ns1 ...) not used before
       * @return String a new namespace prefix ( ns0, ns1, ns2 ...)
       */
      public String generateNextPrefix()
      {
          return "ns" + (count++);
      }
  
   
      /**
       * This method makes a clone of this object.
       * @see java.lang.Object#clone()
       */
      public Object clone() throws CloneNotSupportedException {
          NamespaceMappings clone = new NamespaceMappings();
          clone.m_prefixStack = (Stack)m_prefixStack.clone();
          clone.m_nodeStack = (Stack) m_nodeStack.clone();
          clone.m_namespaces = (Hashtable) m_namespaces.clone();
          
          clone.count = count;
          return clone;
          
      }
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/OutputPropertiesFactory.java
  
  Index: OutputPropertiesFactory.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.io.BufferedInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.Enumeration;
  import java.util.Properties;
  import javax.xml.transform.OutputKeys;
  
  import org.apache.xml.res.XMLErrorResources;
  import org.apache.xml.res.XMLMessages;
  import org.apache.xml.utils.Constants;
  import org.apache.xml.utils.WrappedRuntimeException;
  
  /**
   * This class acts as a factory to generate properties for the given output type
   * ("xml", "text", "html")..
   */
  public class OutputPropertiesFactory
  {
      //************************************************************
      //*  PUBLIC CONSTANTS
      //************************************************************
      /** Built-in extensions namespace, reexpressed in {namespaceURI} syntax
       * suitable for prepending to a localname to produce a "universal
       * name".
       */
      public static final String S_BUILTIN_EXTENSIONS_UNIVERSAL =
          "{" + Constants.S_BUILTIN_EXTENSIONS_URL + "}";
  
      // Some special Xalan keys.
  
      /** The number of whitespaces to indent by, if indent="yes". */
      public static final String S_KEY_INDENT_AMOUNT =
          S_BUILTIN_EXTENSIONS_UNIVERSAL + "indent-amount";
  
      /**
       * Fully qualified name of class with a default constructor that
       *  implements the ContentHandler interface, where the result tree events
       *  will be sent to.
       */
      public static final String S_KEY_CONTENT_HANDLER =
          S_BUILTIN_EXTENSIONS_UNIVERSAL + "content-handler";
  
      /** File name of file that specifies character to entity reference mappings. */
      public static final String S_KEY_ENTITIES =
          S_BUILTIN_EXTENSIONS_UNIVERSAL + "entities";
  
      /** Use a value of "yes" if the href values for HTML serialization should
       *  use %xx escaping. */
      public static final String S_USE_URL_ESCAPING =
          S_BUILTIN_EXTENSIONS_UNIVERSAL + "use-url-escaping";
  
      /** Use a value of "yes" if the META tag should be omitted where it would
       *  otherwise be supplied.
       */
      public static final String S_OMIT_META_TAG =
          S_BUILTIN_EXTENSIONS_UNIVERSAL + "omit-meta-tag";
  
      /**
       * The old built-in extension namespace
       */
      public static final String S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL =
          "{" + Constants.S_BUILTIN_OLD_EXTENSIONS_URL + "}";
  
      /**
       * The length of the old built-in extension namespace
       */
      public static final int S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL_LEN =
          S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL.length();
  
      //************************************************************
      //*  PRIVATE CONSTANTS
      //************************************************************
  
      private static final String S_XSLT_PREFIX = "xslt.output.";
      private static final int S_XSLT_PREFIX_LEN = S_XSLT_PREFIX.length();
      private static final String S_XALAN_PREFIX = "org.apache.xslt.";
      private static final int S_XALAN_PREFIX_LEN = S_XALAN_PREFIX.length();
  
      /** a zero length Class array used in loadPropertiesFile() */
      private static final Class[] NO_CLASSES = new Class[0];
      /** Synchronization object for lazy initialization of the above tables. */
      private static Integer m_synch_object = new Integer(1);
      /** a zero length Object array used in loadPropertiesFile() */
      private static final Object[] NO_OBJS = new Object[0];
  
      /** the directory in which the various method property files are located */
      private static final String PROP_DIR = "org/apache/xml/serializer/";
      /** property file for default XML properties */
      private static final String PROP_FILE_XML = "output_xml.properties";
      /** property file for default TEXT properties */
      private static final String PROP_FILE_TEXT = "output_text.properties";
      /** property file for default HTML properties */
      private static final String PROP_FILE_HTML = "output_html.properties";
      /** property file for default UNKNOWN (Either XML or HTML, to be determined later) properties */
      private static final String PROP_FILE_UNKNOWN = "output_unknown.properties";
  
      //************************************************************
      //*  PRIVATE STATIC FIELDS
      //************************************************************
  
      /** The default properties of all output files. */
      private static Properties m_xml_properties = null;
  
      /** The default properties when method="html". */
      private static Properties m_html_properties = null;
  
      /** The default properties when method="text". */
      private static Properties m_text_properties = null;
  
      /** The properties when method="" for the "unknown" wrapper */
      private static Properties m_unknown_properties = null;
  
      /**
       * Creates an empty OutputProperties with the defaults specified by
       * a property file.  The method argument is used to construct a string of
       * the form output_[method].properties (for instance, output_html.properties).
       * The output_xml.properties file is always used as the base.
       * <p>At the moment, anything other than 'text', 'xml', and 'html', will
       * use the output_xml.properties file.</p>
       *
       * @param   method non-null reference to method name.
       *
       * @return Properties object that holds the defaults for the given method.
       */
      static public Properties getDefaultMethodProperties(String method)
      {
          String fileName = null;
          Properties defaultProperties = null;
          // According to this article : Double-check locking does not work
          // http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-toolbox.html
          try
          {
              synchronized (m_synch_object)
              {
                  if (null == m_xml_properties) // double check
                  {
                      fileName = PROP_FILE_XML;
                      m_xml_properties = loadPropertiesFile(fileName, null);
                  }
              }
  
              if (method.equals(Method.XML))
              {
                  defaultProperties = m_xml_properties;
              }
              else if (method.equals(Method.HTML))
              {
                  if (null == m_html_properties) // double check
                  {
                      fileName = PROP_FILE_HTML;
                      m_html_properties =
                          loadPropertiesFile(fileName, m_xml_properties);
                  }
  
                  defaultProperties = m_html_properties;
              }
              else if (method.equals(Method.TEXT))
              {
                  if (null == m_text_properties) // double check
                  {
                      fileName = PROP_FILE_TEXT;
                      m_text_properties =
                          loadPropertiesFile(fileName, m_xml_properties);
                      if (null
                          == m_text_properties.getProperty(OutputKeys.ENCODING))
                      {
                          String mimeEncoding = Encodings.getMimeEncoding(null);
                          m_text_properties.put(
                              OutputKeys.ENCODING,
                              mimeEncoding);
                      }
                  }
  
                  defaultProperties = m_text_properties;
              }
              else if (method.equals(org.apache.xml.serializer.Method.UNKNOWN))
              {
                  if (null == m_unknown_properties) // double check
                  {
                      fileName = PROP_FILE_UNKNOWN;
                      m_unknown_properties =
                          loadPropertiesFile(fileName, m_xml_properties);
                  }
                  defaultProperties = m_unknown_properties;
              }
              else
              {
  
                  // TODO: Calculate res file from name.
                  defaultProperties = m_xml_properties;
              }
          }
          catch (IOException ioe)
          {
              throw new WrappedRuntimeException(
                  XMLMessages.createXMLMessage(
                      XMLErrorResources.ER_COULD_NOT_LOAD_METHOD_PROPERTY,
                      new Object[] { fileName, method }),
                  ioe);
          }
  
          return defaultProperties;
      }
  
      /**
       * Load the properties file from a resource stream.  If a
       * key name such as "org.apache.xslt.xxx", fix up the start of
       * string to be a curly namespace.  If a key name starts with
       * "xslt.output.xxx", clip off "xslt.output.".  If a key name *or* a
       * key value is discovered, check for \u003a in the text, and
       * fix it up to be ":", since earlier versions of the JDK do not
       * handle the escape sequence (at least in key names).
       *
       * @param resourceName non-null reference to resource name.
       * @param defaults Default properties, which may be null.
       */
      static private Properties loadPropertiesFile(
          final String resourceName,
          Properties defaults)
          throws IOException
      {
  
          // This static method should eventually be moved to a thread-specific class
          // so that we can cache the ContextClassLoader and bottleneck all properties file
          // loading throughout Xalan.
  
          Properties props = new Properties(defaults);
  
          InputStream is = null;
          BufferedInputStream bis = null;
          Class accessControllerClass = null;
  
          try
          {
              try
              {
                  try
                  {
  
                      // This Class was introduced in JDK 1.2. With the re-architecture of
                      // security mechanism ( starting in JDK 1.2 ), we have option of
                      // giving privileges to certain part of code using doPrivileged block.
                      // In JDK1.1.X applications won't be having security manager and if
                      // there is security manager ( in applets ), code need to be signed
                      // and trusted for having access to resources.
  
                      accessControllerClass =
                          Class.forName("java.security.AccessController");
  
                      // If we are here means user is using JDK >= 1.2.
                      // Using doPrivileged to be able to read property file without opening
                      // up secured container permissions like J2EE container
  
                      is =
                          (
                              InputStream) java
                                  .security
                                  .AccessController
                                  .doPrivileged(
                                      new java
                                      .security
                                      .PrivilegedAction()
                      {
  
                          public Object run()
                          {
                              try
                              {
                                  java.lang.reflect.Method getCCL =
                                      Thread.class.getMethod(
                                          "getContextClassLoader",
                                          NO_CLASSES);
                                  if (getCCL != null)
                                  {
                                      ClassLoader contextClassLoader =
                                          (ClassLoader) getCCL.invoke(
                                              Thread.currentThread(),
                                              NO_OBJS);
                                      return (
                                          contextClassLoader.getResourceAsStream(
                                              PROP_DIR + resourceName));
                                  }
                              }
                              catch (Exception e)
                              {
                              }
  
                              return null;
  
                          }
                      });
                  }
                  catch (ClassNotFoundException e)
                  {
                      //User may be using older JDK ( JDK <1.2 ). Allow him/her to use it.
                      // But don't try to use doPrivileged
                      try
                      {
                          java.lang.reflect.Method getCCL =
                              Thread.class.getMethod(
                                  "getContextClassLoader",
                                  NO_CLASSES);
                          if (getCCL != null)
                          {
                              ClassLoader contextClassLoader =
                                  (ClassLoader) getCCL.invoke(
                                      Thread.currentThread(),
                                      NO_OBJS);
                              is =
                                  contextClassLoader.getResourceAsStream(
                                      PROP_DIR + resourceName);
                          }
                      }
                      catch (Exception exception)
                      {
                      }
                  }
              }
              catch (Exception e)
              {
              }
  
              if (is == null)
              {
                  if (accessControllerClass != null)
                  {
                      is =
                          (
                              InputStream) java
                                  .security
                                  .AccessController
                                  .doPrivileged(
                                      new java
                                      .security
                                      .PrivilegedAction()
                      {
                          public Object run()
                          {
                              return OutputPropertiesFactory
                                  .class
                                  .getResourceAsStream(
                                  resourceName);
                          }
                      });
                  }
                  else
                  {
                      // User may be using older JDK ( JDK < 1.2 )
                      is =
                          OutputPropertiesFactory.class.getResourceAsStream(
                              resourceName);
                  }
              }
  
              bis = new BufferedInputStream(is);
              props.load(bis);
          }
          catch (IOException ioe)
          {
              if (defaults == null)
              {
                  throw ioe;
              }
              else
              {
                  throw new WrappedRuntimeException(
                      XMLMessages.createXMLMessage(
                          XMLErrorResources.ER_COULD_NOT_LOAD_RESOURCE,
                          new Object[] { resourceName }),
                      ioe);
                  //"Could not load '"+resourceName+"' (check CLASSPATH), now using just the defaults ", ioe);
              }
          }
          catch (SecurityException se)
          {
              // Repeat IOException handling for sandbox/applet case -sc
              if (defaults == null)
              {
                  throw se;
              }
              else
              {
                  throw new WrappedRuntimeException(
                      XMLMessages.createXMLMessage(
                          XMLErrorResources.ER_COULD_NOT_LOAD_RESOURCE,
                          new Object[] { resourceName }),
                      se);
                  //"Could not load '"+resourceName+"' (check CLASSPATH, applet security), now using just the defaults ", se);
              }
          }
          finally
          {
              if (bis != null)
              {
                  bis.close();
              }
              if (is != null)
              {
                  is.close();
              }
          }
  
          // Note that we're working at the HashTable level here,
          // and not at the Properties level!  This is important
          // because we don't want to modify the default properties.
          // NB: If fixupPropertyString ends up changing the property
          // name or value, we need to remove the old key and re-add
          // with the new key and value.  However, then our Enumeration
          // could lose its place in the HashTable.  So, we first
          // clone the HashTable and enumerate over that since the
          // clone will not change.  When we migrate to Collections,
          // this code should be revisited and cleaned up to use
          // an Iterator which may (or may not) alleviate the need for
          // the clone.  Many thanks to Padraig O'hIceadha
          // <pa...@gradient.ie> for finding this problem.  Bugzilla 2000.
  
          Enumeration keys = ((Properties) props.clone()).keys();
          while (keys.hasMoreElements())
          {
              String key = (String) keys.nextElement();
              // Now check if the given key was specified as a
              // System property. If so, the system property
              // overides the default value in the propery file.
              String value = null;
              try
              {
                  value = System.getProperty(key);
              }
              catch (SecurityException se)
              {
                  // No-op for sandbox/applet case, leave null -sc
              }
              if (value == null)
                  value = (String) props.get(key);
  
              String newKey = fixupPropertyString(key, true);
              String newValue = null;
              try
              {
                  newValue = System.getProperty(newKey);
              }
              catch (SecurityException se)
              {
                  // No-op for sandbox/applet case, leave null -sc
              }
              if (newValue == null)
                  newValue = fixupPropertyString(value, false);
              else
                  newValue = fixupPropertyString(newValue, false);
  
              if (key != newKey || value != newValue)
              {
                  props.remove(key);
                  props.put(newKey, newValue);
              }
  
          }
  
          return props;
      }
  
      /**
       * Fix up a string in an output properties file according to
       * the rules of {@link #loadPropertiesFile}.
       *
       * @param s non-null reference to string that may need to be fixed up.
       * @return A new string if fixup occured, otherwise the s argument.
       */
      static private String fixupPropertyString(String s, boolean doClipping)
      {
          int index;
          if (doClipping && s.startsWith(S_XSLT_PREFIX))
          {
              s = s.substring(S_XSLT_PREFIX_LEN);
          }
          if (s.startsWith(S_XALAN_PREFIX))
          {
              s =
                  S_BUILTIN_EXTENSIONS_UNIVERSAL
                      + s.substring(S_XALAN_PREFIX_LEN);
          }
          if ((index = s.indexOf("\\u003a")) > 0)
          {
              String temp = s.substring(index + 6);
              s = s.substring(0, index) + ":" + temp;
  
          }
          return s;
      }
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/OutputPropertyUtils.java
  
  Index: OutputPropertyUtils.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.util.Properties;
  
  /**
   * This class contains some static methods that act as helpers when parsing a
   * Java Property object.
   * 
   * @see java.util.Properties
   */
  public class OutputPropertyUtils
  {
      /**
        * Searches for the boolean property with the specified key in the property list.
        * If the key is not found in this property list, the default property list,
        * and its defaults, recursively, are then checked. The method returns
        * <code>false</code> if the property is not found, or if the value is other
        * than "yes".
        *
        * @param   key   the property key.
        * @param   props   the list of properties that will be searched.
        * @return  the value in this property list as a boolean value, or false
        * if null or not "yes".
        */
      public static boolean getBooleanProperty(String key, Properties props)
      {
  
          String s = props.getProperty(key);
  
          if (null == s || !s.equals("yes"))
              return false;
          else
              return true;
      }
  
      /**
       * Searches for the int property with the specified key in the property list.
       * If the key is not found in this property list, the default property list,
       * and its defaults, recursively, are then checked. The method returns
       * <code>false</code> if the property is not found, or if the value is other
       * than "yes".
       *
       * @param   key   the property key.
       * @param   props   the list of properties that will be searched.
       * @return  the value in this property list as a int value, or 0
       * if null or not a number.
       */
      public static int getIntProperty(String key, Properties props)
      {
  
          String s = props.getProperty(key);
  
          if (null == s)
              return 0;
          else
              return Integer.parseInt(s);
      }
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/SerializationHandler.java
  
  Index: SerializationHandler.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2003 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) 2003, International Business
   * Machines, Inc., http://www.ibm.com.  For more information on the Apache
   * Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.Writer;
  import java.util.Properties;
  import java.util.Vector;
  
  import javax.xml.transform.Transformer;
  
  import org.apache.xml.serializer.Serializer;
  import org.w3c.dom.Node;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.ErrorHandler;
  import org.xml.sax.SAXException;
  import org.xml.sax.ext.DeclHandler;
  
  /**
   * This interface is the one that a serializer implements. It is a group of
   * other interfaces, such as ExtendedContentHandler, ExtendedLexicalHandler etc.
   * In addition there are other methods, such as reset().
   */
  public interface SerializationHandler
      extends
          ExtendedContentHandler,
          ExtendedLexicalHandler,
          XSLOutputAttributes,
          DeclHandler,
          ErrorHandler,
          Serializer
  {
      /**
       * Set the SAX Content handler that the serializer sends its output to. This
       * method only applies to a ToSAXHandler, not to a ToStream serializer.
       * 
       * @see org.apache.xml.serializer.Serializer#asContentHandler()
       * @see org.apache.xml.serializer.ToSAXHandler
       */
      public void setContentHandler(ContentHandler ch);
      
      public void close();
  
      /**
       * Notify that the serializer should take this DOM node as input to be
       * serialized.
       * 
       * @param node the DOM node to be serialized.
       * @throws IOException
       */
      public void serialize(Node node) throws IOException;
      /**
       * Turns special character escaping on/off. 
       * 
       * Note that characters will
       * never, even if this option is set to 'true', be escaped within
       * CDATA sections in output XML documents.
       * 
       * @param true if escaping is to be set on.
       */
      public boolean setEscaping(boolean escape) throws SAXException;
  
      /**
       * Set the number of spaces to indent for each indentation level.
       * @param spaces the number of spaces to indent for each indentation level.
       */
      public void setIndentAmount(int spaces);
  
      /**
       * Set the transformer associated with the serializer.
       * @param transformer the transformer associated with the serializer.
       */
      public void setTransformer(Transformer transformer);
      
      /**
       * Get the transformer associated with the serializer.
       * @return Transformer the transformer associated with the serializer.
       */
      public Transformer getTransformer();
  
      /** 
       * Used only by TransformerSnapshotImpl to restore the serialization 
       * to a previous state. 
       * 
       * @param NamespaceMappings
       */
      public void setNamespaceMappings(NamespaceMappings mappings);
  
      /**
       * Flush any pending events currently queued up in the serializer. This will
       * flush any input that the serializer has which it has not yet sent as
       * output.
       */
      public void flushPending();
  
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/Serializer.java
  
  Index: Serializer.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  import java.io.Writer;
  import java.io.OutputStream;
  import java.io.IOException;
  import java.util.Properties;
  
  import org.apache.xml.serializer.DOMSerializer; 
  
  import org.xml.sax.ContentHandler;
  
  /**
   * The Serializer interface is implemented by Serializers to publish methods to
   * get and set streams and writers, to set the output properties, and get the
   * Serializer as a ContentHandler or DOMSerializer.
   */
  public interface Serializer {
  
      /**
       * Specifies an output stream to which the document should be
       * serialized. This method should not be called while the
       * serializer is in the process of serializing a document.
       * <p>
       * The encoding specified in the output {@link Properties} is used, or
       * if no encoding was specified, the default for the selected
       * output method.
       *
       * @param output The output stream
       */
      public void setOutputStream(OutputStream output);
  
      /**
       * Get the output stream where the events will be serialized to.
       *
       * @return reference to the result stream, or null of only a writer was
       * set.
       */
      public OutputStream getOutputStream();
  
      /**
       * Specifies a writer to which the document should be serialized.
       * This method should not be called while the serializer is in
       * the process of serializing a document.
       * <p>
       * The encoding specified for the output {@link Properties} must be
       * identical to the output format used with the writer.
       *
       * @param writer The output writer stream
       */
      public void setWriter(Writer writer);
  
      /**
       * Get the character stream where the events will be serialized to.
       *
       * @return Reference to the result Writer, or null.
       */
      public Writer getWriter();
  
      /**
       * Specifies an output format for this serializer. It the
       * serializer has already been associated with an output format,
       * it will switch to the new format. This method should not be
       * called while the serializer is in the process of serializing
       * a document.
       *
       * @param format The output format to use
       */
      public void setOutputFormat(Properties format);
  
      /**
       * Returns the output format properties for this serializer.
       *
       * @return The output format in use
       */
      public Properties getOutputFormat();
  
      /**
       * Return a {@link ContentHandler} interface into this serializer.
       * If the serializer does not support the {@link ContentHandler}
       * interface, it should return null.
       *
       * @return A {@link ContentHandler} interface into this serializer,
       *  or null if the serializer is not SAX 2 capable
       * @throws IOException An I/O exception occured
       */
      public ContentHandler asContentHandler() throws IOException;
  
      /**
       * Return a {@link DOMSerializer} interface into this serializer.
       * If the serializer does not support the {@link DOMSerializer}
       * interface, it should return null.
       *
       * @return A {@link DOMSerializer} interface into this serializer,
       *  or null if the serializer is not DOM capable
       * @throws IOException An I/O exception occured
       */
      public DOMSerializer asDOMSerializer() throws IOException;
  
      /**
       * Resets the serializer. If this method returns true, the
       * serializer may be used for subsequent serialization of new
       * documents. It is possible to change the output format and
       * output stream prior to serializing, or to use the existing
       * output format and output stream.
       *
       * @return True if serializer has been reset and can be reused
       */
      public boolean reset();
  }
  
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/SerializerBase.java
  
  Index: SerializerBase.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 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.xml.serializer;
  
  import java.io.IOException;
  import java.util.Hashtable;
  import java.util.Stack;
  import java.util.Vector;
  
  import javax.xml.transform.SourceLocator;
  import javax.xml.transform.Transformer;
  
  import org.apache.xml.res.XMLErrorResources;
  import org.apache.xml.res.XMLMessages;
  import org.apache.xml.utils.BoolStack;
  import org.xml.sax.Attributes;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  import org.xml.sax.SAXParseException;
  
  
  /**
   * This class acts as a base class for the XML "serializers"
   * and the stream serializers.
   * It contains a number of common fields and methods.
   */
  abstract public class SerializerBase
      implements SerializationHandler, SerializerConstants, org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.CharacterNodeHandler
  {
      
  
      /**
       * To fire off the end element trace event
       * @param name Name of element
       */
      protected void fireEndElem(String name)
          throws org.xml.sax.SAXException
      {
          flushMyWriter();
          if (m_tracer != null)
              m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDELEMENT,name, (Attributes)null);     	        	    	
      }
  
      /**
       * Report the characters trace event
       * @param chars  content of characters
       * @param start  starting index of characters to output
       * @param length  number of characters to output
       */
      protected void fireCharEvent(char[] chars, int start, int length)
          throws org.xml.sax.SAXException
      {
          flushMyWriter();
          if (m_tracer != null)
              m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CHARACTERS, chars, start,length);     	        	    	
      }
  
      /**
       * true if we still need to call startDocumentInternal() 
  	 */
      protected boolean m_needToCallStartDocument = true; 
      
      /**
       * Set to true when a start tag is started, or open, but not all the
       * attributes or namespace information is yet collected.
       */
      protected boolean m_startTagOpen = false;
  
      /**
       * Keeps track of the nesting depth of elements inside each other.
       * This is the nesting depth of the current element being processed.
       */
      int m_currentElemDepth = 0;
  
      /**
       * The cached value of the QName of the current element
       */
      protected String m_elementName = null;
      
      /**
       * The cached value of the local name of the current element
       */
      protected String m_elementLocalName = null;
      
      /**
       * The cached value of the URI of the current element
       */
      protected String m_elementURI = null;
  
  
      /** True if a trailing "]]>" still needs to be written to be
       * written out. Used to merge adjacent CDATA sections
       */
      protected boolean m_cdataTagOpen = false;
  
      /**
       * All the attributes of the current element, collected from
       * startPrefixMapping() calls, or addAddtribute() calls, or 
       * from the SAX attributes in a startElement() call.
       */
      protected AttributesImplSerializer m_attributes = new AttributesImplSerializer();
  
      /**
       * Tells if we're in an EntityRef event.
       */
      protected boolean m_inEntityRef = false;
  
      /** This flag is set while receiving events from the external DTD */
      protected boolean m_inExternalDTD = false;
  
      /** When an element starts, if its name is in the cdata-section-names list
       * then push a True on the stack, otherwise push a False.
       * at the end of an element the value is poped.
       * It is True if the text of the element should be in CDATA section blocks. 
       */
      protected BoolStack m_cdataSectionStates = new BoolStack();
  
      /**
       * The System ID for the doc type.
       */
      private String m_doctypeSystem;
  
      /**
       * The public ID for the doc type.
       */
      private String m_doctypePublic;
  
      /**
       * Flag to tell that we need to add the doctype decl, which we can't do
       * until the first element is encountered.
       */
      boolean m_needToOutputDocTypeDecl = true;
  
      /**
       * The character encoding.  Must match the encoding used for the
       * printWriter.
       */
      private String m_encoding = null;
  
      /** 
       * 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 m_nodeStack;
  
      /** 
       * The top of this stack is the prefix that was last mapped to an URI
       */
      protected Stack m_prefixStack;
  
      /**
       * Tells if we should write the XML declaration.
       */
      private boolean m_shouldNotWriteXMLHeader = false;
  
      /**
       * The standalone value for the doctype.
       */
      private String m_standalone;
  
      /**
       * True if standalone was specified.
       */
      protected boolean m_standaloneWasSpecified = false;
  
      /**
       * Flag to tell if indenting (pretty-printing) is on.
       */
      protected boolean m_doIndent = false;
      /**
       * Amount to indent.
       */
      protected int m_indentAmount = 0;
  
      /**
       * Tells the XML version, for writing out to the XML decl.
       */
      private String m_version = null;
  
      /**
       * The mediatype.  Not used right now.
       */
      private String m_mediatype;
  
      /**
       * The transformer that was around when this output handler was created (if
       * any).
       */
      private Transformer m_transformer;
  
      /** 
       * Pairs of local names and corresponding URIs of CDATA sections. This list
       * comes from the cdata-section-elements attribute. Every second one is a
       * local name, and every other second one is the URI for the local name. 
       */
      protected Vector m_cdataSectionElements = null;
  
      /**
       * Namespace support, that keeps track of currently defined 
       * prefix/uri mappings. As processed elements come and go, so do
       * the associated mappings for that element.
       */
      protected NamespaceMappings m_prefixMap;
      
      /**
       * Handle for firing generate events.  This interface may be implemented
       * by the referenced transformer object.
       */
      protected SerializerTrace m_tracer;
      
      protected SourceLocator m_sourceLocator;
      
  
      /**
       * The writer to send output to. This field is only used in the ToStream
       * serializers, but exists here just so that the fireStartDoc() and
       * other fire... methods can flush this writer when tracing.
       */
      protected java.io.Writer m_writer = null;    
  
      /**
       * Receive notification of a comment.
       * 
       * @see org.apache.xml.serializer.ExtendedLexicalHandler#comment(String)
       */
      public void comment(String data) throws SAXException
      {
          this.comment(data.toCharArray(), 0, data.length());
      }
  
      /**
        * 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 String patchName(String qname)
      {
  
          
          final int lastColon = qname.lastIndexOf(':');
  
          if (lastColon > 0) {
              final int firstColon = qname.indexOf(':');
              final String prefix = qname.substring(0, firstColon);
              final String localName = qname.substring(lastColon + 1);
  
          // If uri is "" then ignore prefix
              final String uri = m_prefixMap.lookupNamespace(prefix);
              if (uri != null && uri.length() == 0) {
                  return localName;
              }
              else if (firstColon != lastColon) {
                  return prefix + ':' + localName;
              }
          }
          return qname;        
      }
  
      /**
       * Returns the local name of a qualified name. If the name has no prefix,
       * then it works as the identity (SAX2).
       * @param qname the qualified name 
       * @return the name, but excluding any prefix and colon.
       */
      protected static String getLocalName(String qname)
      {
          final int col = qname.lastIndexOf(':');
          return (col > 0) ? qname.substring(col + 1) : qname;
      }
  
      /**
       * Receive an object for locating the origin of SAX document events.
       *
       * @param locator An object that can return the location of any SAX document
       * event.
       * 
       * Receive an object for locating the origin of SAX document events.
       *
       * <p>SAX parsers are strongly encouraged (though not absolutely
       * required) to supply a locator: if it does so, it must supply
       * the locator to the application by invoking this method before
       * invoking any of the other methods in the DocumentHandler
       * interface.</p>
       *
       * <p>The locator allows the application to determine the end
       * position of any document-related event, even if the parser is
       * not reporting an error.  Typically, the application will
       * use this information for reporting its own errors (such as
       * character content that does not match an application's
       * business rules).  The information returned by the locator
       * is probably not sufficient for use with a search engine.</p>
       *
       * <p>Note that the locator will return correct information only
       * during the invocation of the events in this interface.  The
       * application should not attempt to use it at any other time.</p>
       */
      public void setDocumentLocator(Locator locator)
      {
          return;
  
          // I don't do anything with this yet.
      }
  
      /**
       * Adds the given attribute to the set of collected attributes , but only if
       * there is a currently open element.
       * 
       * An element is currently open if a startElement() notification has
       * occured but the start of the element has not yet been written to the
       * output.  In the stream case this means that we have not yet been forced
       * to close the elements opening tag by another notification, such as a
       * character notification.
       * 
       * @param uri the URI of the attribute
       * @param localName the local name of the attribute
       * @param rawName    the qualified name of the attribute
       * @param type the type of the attribute (probably CDATA)
       * @param value the value of the attribute
       * @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
       */
      public void addAttribute(
          String uri,
          String localName,
          String rawName,
          String type,
          String value)
          throws SAXException
      {
          if (m_startTagOpen)
          {
              addAttributeAlways(uri, localName, rawName, type, value);
          }
  
      }
      
      /**
       * Adds the given attribute to the set of attributes, even if there is
       * no currently open element. This is useful if a SAX startPrefixMapping()
       * should need to add an attribute before the element name is seen.
       * 
       * @param uri the URI of the attribute
       * @param localName the local name of the attribute
       * @param rawName   the qualified name of the attribute
       * @param type the type of the attribute (probably CDATA)
       * @param value the value of the attribute
       */
      public void addAttributeAlways(
          String uri,
          String localName,
          String rawName,
          String type,
          String value)
      {
  //            final int index =
  //                (localName == null || uri == null) ?
  //                m_attributes.getIndex(rawName):m_attributes.getIndex(uri, localName);        
              int index;
  //            if (localName == null || uri == null){
  //                index = m_attributes.getIndex(rawName);
  //            }
  //            else {
  //                index = m_attributes.getIndex(uri, localName);
  //            }
              index = m_attributes.getIndex(rawName);
              if (index >= 0)
              {
                  /* We've seen the attribute before.
                   * We may have a null uri or localName, but all
                   * we really want to re-set is the value anyway.
                   */
                  m_attributes.setValue(index,value);
              }
              else
              {
                  // the attribute doesn't exist yet, create it
                  m_attributes.addAttribute(uri, localName, rawName, type, value);
              }
          
      }
    
  
      /**
       *  Adds  the given attribute to the set of collected attributes, 
       * but only if there is a currently open element.  This method is only
       * called by XSLTC.
       *
       * @param name the attribute's qualified name
       * @param value the value of the attribute
       */
      public void addAttribute(String name, final String value)
      {
          if (m_startTagOpen)
          {
              final String patchedName = patchName(name);
              final String localName = getLocalName(patchedName);
              final String uri = getNamespaceURI(patchedName, false);
  
              addAttributeAlways(uri,localName, patchedName, "CDATA", value);
           }
      }    
  
  
      /**
       * Add the given attributes to the currently collected ones. These
       * attributes are always added, regardless of whether on not an element
       * is currently open.
       * @param atts List of attributes to add to this list
       */
      public void addAttributes(Attributes atts) throws SAXException
      {
  
          int nAtts = atts.getLength();
  
          for (int i = 0; i < nAtts; i++)
          {
              String uri = atts.getURI(i);
  
              if (null == uri)
                  uri = "";
  
              addAttributeAlways(
                  uri,
                  atts.getLocalName(i),
                  atts.getQName(i),
                  atts.getType(i),
                  atts.getValue(i));
  
          }
      }
  
      /**
       * Return a {@link ContentHandler} interface into this serializer.
       * If the serializer does not support the {@link ContentHandler}
       * interface, it should return null.
       *
       * @return A {@link ContentHandler} interface into this serializer,
       *  or null if the serializer is not SAX 2 capable
       * @throws IOException An I/O exception occured
       */
      public ContentHandler asContentHandler() throws IOException
      {
          return this;
      }
  
      /**
       * Report the end of an entity.
       *
       * @param name The name of the entity that is ending.
       * @throws org.xml.sax.SAXException The application may raise an exception.
       * @see #startEntity
       */
      public void endEntity(String name) throws org.xml.sax.SAXException
      {
          if (name.equals("[dtd]"))
              m_inExternalDTD = false;
          m_inEntityRef = false;
  
          this.fireEndEntity(name);        
      }
  
      /**
       * Flush and close the underlying java.io.Writer. This method applies to
       * ToStream serializers, not ToSAXHandler serializers.
       * @see org.apache.xml.serializer.ToStream
       */
      public void close()
      {
          // do nothing (base behavior)
      }
  
      /**
       * Initialize global variables
       */
      protected void initCDATA()
      {
          // CDATA stack
          //        _cdataStack = new Stack();
          //        _cdataStack.push(new Integer(-1)); // push dummy value
      }
  
      /**
       * Returns the character encoding to be used in the output document.
       * @return the character encoding to be used in the output document.
       */
      public String getEncoding()
      {
          return m_encoding;
      }
  
     /**
       * Sets the character encoding coming from the xsl:output encoding stylesheet attribute.
       * @param encoding the character encoding
       */
      public void setEncoding(String m_encoding)
      {
          this.m_encoding = m_encoding;
      }
  
      /**
       * Sets the value coming from the xsl:output omit-xml-declaration stylesheet attribute
       * @param b true if the XML declaration is to be omitted from the output
       * document.
       */
      public void setOmitXMLDeclaration(boolean b)
      {
          this.m_shouldNotWriteXMLHeader = b;
      }
  
  
      /**
       * @return true if the XML declaration is to be omitted from the output
       * document.
       */
      public boolean getOmitXMLDeclaration()
      {
          return m_shouldNotWriteXMLHeader;
      }
  
      /**
       * Returns the previously set value of the value to be used as the public
       * identifier in the document type declaration (DTD).
       * 
       *@return the public identifier to be used in the DOCTYPE declaration in the
       * output document.
       */    
      public String getDoctypePublic()
      {
          return m_doctypePublic;
      }
  
      /** Set the value coming from the xsl:output doctype-public stylesheet attribute.
        * @param doctypePublic the public identifier to be used in the DOCTYPE
        * declaration in the output document.
        */
      public void setDoctypePublic(String doctypePublic)
      {
          this.m_doctypePublic = doctypePublic;
      }
  
  
      /**
       * Returns the previously set value of the value to be used
       * as the system identifier in the document type declaration (DTD).
  	 * @return the system identifier to be used in the DOCTYPE declaration in
  	 * the output document.
       *
       */    
      public String getDoctypeSystem()
      {
          return m_doctypeSystem;
      }
  
      /** Set the value coming from the xsl:output doctype-system stylesheet attribute.
        * @param doctypeSystem the system identifier to be used in the DOCTYPE
        * declaration in the output document.
        */
      public void setDoctypeSystem(String doctypeSystem)
      {
          this.m_doctypeSystem = doctypeSystem;
      }
  
      /** Set the value coming from the xsl:output doctype-public and doctype-system stylesheet properties
       * @param doctypeSystem the system identifier to be used in the DOCTYPE
       * declaration in the output document.
       * @param doctypePublic the public identifier to be used in the DOCTYPE
       * declaration in the output document.
       */
      public void setDoctype(String doctypeSystem, String doctypePublic)
      {
          this.m_doctypeSystem = doctypeSystem;
          this.m_doctypePublic = doctypePublic;
      }
  
      /**
       * Sets the value coming from the xsl:output standalone stylesheet attribute.
       * @param standalone a value of "yes" indicates that the
       * <code>standalone</code> delaration is to be included in the output
       * document. This method remembers if the value was explicitly set using
       * this method, verses if the value is the default value.
       */
      public void setStandalone(String standalone)
      {
          if (standalone != null)
          {
              m_standaloneWasSpecified = true;
              setStandaloneInternal(standalone);
          }
      }
      /**
       * Sets the XSL standalone attribute, but does not remember if this is a
       * default or explicite setting.
       * @param standalone "yes" | "no"
       */    
      protected void setStandaloneInternal(String standalone)
      {
          if ("yes".equals(standalone))
              m_standalone = "yes";
          else
              m_standalone = "no";
          
      }
  
      /**
       * Gets the XSL standalone attribute
       * @return a value of "yes" if the <code>standalone</code> delaration is to
       * be included in the output document.
       *  @see   org.apache.xml.serializer.XSLOutputAttributes#getStandalone()
       */
      public String getStandalone()
      {
          return m_standalone;
      }
  
      /**
       * @return true if the output document should be indented to visually
       * indicate its structure.
       */
      public boolean getIndent()
      {
          return m_doIndent;
      }
      /**
       * Gets the mediatype the media-type or MIME type associated with the output
       * document.
       * @return the mediatype the media-type or MIME type associated with the
       * output document.
       */
      public String getMediaType()
      {
          return m_mediatype;
      }
  
      /**
       * Gets the version of the output format.
       * @return the version of the output format.
       */
      public String getVersion()
      {
          return m_version;
      }
  
      /**
       * Sets the value coming from the xsl:output version attribute.
       * @param version the version of the output format.
       * @see org.apache.xml.serializer.SerializationHandler#setVersion(String)
       */
      public void setVersion(String version)
      {
          m_version = version;
      }
  
      /**
       * Sets the value coming from the xsl:output media-type stylesheet attribute.
       * @param mediaType the non-null media-type or MIME type associated with the
       * output document.
       * @see javax.xml.transform.OutputKeys#MEDIA_TYPE
       * @see org.apache.xml.serializer.SerializationHandler#setMediaType(String)
       */
      public void setMediaType(String mediaType)
      {
          m_mediatype = mediaType;
      }
  
      /**
       * @return the number of spaces to indent for each indentation level.
       */
      public int getIndentAmount()
      {
          return m_indentAmount;
      }
  
      /**
       * Sets the indentation amount.
       * @param m_indentAmount The m_indentAmount to set
       */
      public void setIndentAmount(int m_indentAmount)
      {
          this.m_indentAmount = m_indentAmount;
      }
  
      /**
       * Sets the value coming from the xsl:output indent stylesheet
       * attribute.
       * @param doIndent true if the output document should be indented to
       * visually indicate its structure.
       * @see org.apache.xml.serializer.XSLOutputAttributes#setIndent(boolean)
       */
      public void setIndent(boolean doIndent)
      {
          m_doIndent = doIndent;
      }
  
      /**
       * This method is used when a prefix/uri namespace mapping
       * is indicated after the element was started with a 
       * startElement() and before and endElement().
       * startPrefixMapping(prefix,uri) would be used before the
       * startElement() call.
       * @param uri the URI of the namespace
       * @param prefix the prefix associated with the given URI.
       * 
       * @see org.apache.xml.serializer.ExtendedContentHandler#namespaceAfterStartElement(String, String)
       */
      public void namespaceAfterStartElement(String uri, String prefix)
          throws SAXException
      {
          // default behavior is to do nothing
      }
  
      /**
       * Return a {@link DOMSerializer} interface into this serializer. If the
       * serializer does not support the {@link DOMSerializer} interface, it should
       * return null.
       *
       * @return A {@link DOMSerializer} interface into this serializer,  or null
       * if the serializer is not DOM capable
       * @throws IOException An I/O exception occured
       * @see org.apache.xml.serializer.Serializer#asDOMSerializer()
       */
      public DOMSerializer asDOMSerializer() throws IOException
      { 
          return null;
      }
  
      /**
       * Push a boolean state based on if the name of the element
       * is found in the list of qnames.  A state is always pushed,
       * one way or the other.
       *
       * @param namespaceURI Should be a non-null reference to the namespace URL
       *        of the element that owns the state, or empty string.
       * @param localName Should be a non-null reference to the local name
       *        of the element that owns the state.
       *
       * Hidden parameters are the vector of qualified elements specified in
       * cdata-section-names attribute, and the m_cdataSectionStates stack
       * onto which whether the current element is in the list is pushed (true or
       * false). Other hidden parameters are the current elements namespaceURI,
       * localName and qName
       */
      protected void pushCdataSectionState()
      {
  
          boolean b;
  
          if (null != m_cdataSectionElements)
          {
              b = false;
              if (m_elementLocalName == null)
                  m_elementLocalName = getLocalName(m_elementName);
              if (m_elementURI == null)
              {
                  String prefix = getPrefixPart(m_elementName);
                  if (prefix != null)
                      m_elementURI = m_prefixMap.lookupNamespace(prefix);
  
              }
  
              if ((null != m_elementURI) && m_elementURI.length() == 0)
                  m_elementURI = null;
  
              int nElems = m_cdataSectionElements.size();
  
              // loop through 2 at a time, as these are pairs of URI and localName
              for (int i = 0; i < nElems; i += 2)
              {
                  String uri = (String) m_cdataSectionElements.elementAt(i);
                  String loc = (String) m_cdataSectionElements.elementAt(i + 1);
                  if (loc.equals(m_elementLocalName)
                      && subPartMatch(m_elementURI, uri))
                  {
                      b = true;
  
                      break;
                  }
              }
          }
          else
          {
              b = m_cdataSectionStates.peekOrFalse();
          }
  
          m_cdataSectionStates.push(b);
      }
  
      /**
       * Tell if two strings are equal, without worry if the first string is null.
       *
       * @param p String reference, which may be null.
       * @param t String reference, which may be null.
       *
       * @return true if strings are equal.
       */
      private static final boolean subPartMatch(String p, String t)
      {
          return (p == t) || ((null != p) && (p.equals(t)));
      }
  
      /**
       * Returns the local name of a qualified name. 
       * If the name has no prefix,
       * then it works as the identity (SAX2). 
       * 
       * @param qname a qualified name
       * @return returns the prefix of the qualified name,
       * or null if there is no prefix.
       */
      protected static final String getPrefixPart(String qname)
      {
          final int col = qname.indexOf(':');
          return (col > 0) ? qname.substring(0, col) : null;
          //return (col > 0) ? qname.substring(0,col) : "";
      }
  
      /**
       * Some users of the serializer may need the current namespace mappings
       * @return the current namespace mappings (prefix/uri)
       * @see org.apache.xml.serializer.ExtendedContentHandler#getNamespaceMappings()
       */
      public NamespaceMappings getNamespaceMappings()
      {
          return m_prefixMap;
      }
  
      /**
       * Returns the prefix currently pointing to the given URI (if any).
       * @param namespaceURI the uri of the namespace in question
       * @return a prefix pointing to the given URI (if any).
       * @see org.apache.xml.serializer.ExtendedContentHandler#getPrefix(String)
       */
      public String getPrefix(String namespaceURI)
      {
          String prefix = m_prefixMap.lookupPrefix(namespaceURI);
          return prefix;
      }
  
      /**
       * Returns the URI of an element or attribute. Note that default namespaces
       * do not apply directly to attributes.
       * @param qname a qualified name
       * @param isElement true if the qualified name is the name of 
       * an element.
       * @return returns the namespace URI associated with the qualified name.
       */
      public String getNamespaceURI(String qname, boolean isElement)
      {
          String uri = EMPTYSTRING;
          int col = qname.lastIndexOf(':');
          final String prefix = (col > 0) ? qname.substring(0, col) : EMPTYSTRING;
  
          if (!EMPTYSTRING.equals(prefix) || isElement)
          {
              if (m_prefixMap != null)
              {
                  uri = m_prefixMap.lookupNamespace(prefix);
                  if (uri == null && !prefix.equals(XMLNS_PREFIX))
                  {
                      throw new RuntimeException(
                          XMLMessages.createXMLMessage(
                              XMLErrorResources.ER_NAMESPACE_PREFIX,
                              new Object[] { qname.substring(0, col) }  ));
                  }
              }
          }
          return uri;
      }
  
      /**
       * Returns the URI of prefix (if any)
       * 
  	 * @param prefix the prefix whose URI is searched for
       * @return the namespace URI currently associated with the
       * prefix, null if the prefix is undefined.
       */
      public String getNamespaceURIFromPrefix(String prefix)
      {
          String uri = null;
          if (m_prefixMap != null)
              uri = m_prefixMap.lookupNamespace(prefix);
          return uri;
      }
  
      /**
       * Entity reference event.
       *
       * @param name Name of entity
       *
       * @throws org.xml.sax.SAXException
       */
      public void entityReference(String name) throws org.xml.sax.SAXException
      {
  
          flushPending();
  
          startEntity(name);
          endEntity(name);
  
  		fireEntityReference(name);
      }
  
      /**
       * Sets the transformer associated with this serializer
       * @param t the transformer associated with this serializer.
       * @see org.apache.xml.serializer.SerializationHandler#setTransformer(Transformer)
       */
      public void setTransformer(Transformer t)
      {
          m_transformer = t;
          
          // If this transformer object implements the SerializerTrace interface
          // then assign m_tracer to the transformer object so it can be used
          // to fire trace events.
          if ((m_transformer instanceof SerializerTrace) &&
              (((SerializerTrace) m_transformer).hasTraceListeners())) {
             m_tracer = (SerializerTrace) m_transformer;
          } else {
             m_tracer = null;
          }
      }
      /**
       * Gets the transformer associated with this serializer
       * @return returns the transformer associated with this serializer.
       * @see org.apache.xml.serializer.SerializationHandler#getTransformer()
       */
      public Transformer getTransformer()
      {
          return m_transformer;
      }
      
      /**
       * This method gets the nodes value as a String and uses that String as if
       * it were an input character notification.
       * @param node the Node to serialize
       * @throws org.xml.sax.SAXException
       */
      public void characters(org.w3c.dom.Node node)
          throws org.xml.sax.SAXException
      {
          flushPending();
  
          String data = node.getNodeValue();
          char[] ch = null;
          int length = 0;
          if (data != null)
          {
              ch = data.toCharArray();
              length = data.length();
               characters(ch, 0, length);
  
          }
      }
      
  
      /**
       * @see org.xml.sax.ErrorHandler#error(SAXParseException)
       */
      public void error(SAXParseException exc) throws SAXException {
      }
  
      /**
       * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException)
       */
      public void fatalError(SAXParseException exc) throws SAXException {
          
        m_startTagOpen = false;
  
      }
  
      /**
       * @see org.xml.sax.ErrorHandler#warning(SAXParseException)
       */
      public void warning(SAXParseException exc) throws SAXException 
      {
      }
  
      /**
       * To fire off start entity trace event
       * @param name Name of entity
       */
      protected void fireStartEntity(String name)
          throws org.xml.sax.SAXException
      {
          flushMyWriter();
          if (m_tracer != null)
              m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENTITYREF, name);     	        	    	
      }
  
      /**
       * Report the characters event
       * @param chars  content of characters
       * @param start  starting index of characters to output
       * @param length  number of characters to output
       */
  //    protected void fireCharEvent(char[] chars, int start, int length)
  //        throws org.xml.sax.SAXException
  //    {
  //        if (m_tracer != null)
  //            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CHARACTERS, chars, start,length);     	        	    	
  //    }
  //        
  
      /**
       * This method is only used internally when flushing the writer from the
       * various fire...() trace events.  Due to the writer being wrapped with 
       * SerializerTraceWriter it may cause the flush of these trace events:
       * EVENTTYPE_OUTPUT_PSEUDO_CHARACTERS 
       * EVENTTYPE_OUTPUT_CHARACTERS
       * which trace the output written to the output stream.
       * 
       */
      private void flushMyWriter()
      {
          if (m_writer != null)
          {
              try
              {
                  m_writer.flush();
              }
              catch(IOException ioe)
              {
              
              }
          }
      }
      /**
       * Report the CDATA trace event
       * @param chars  content of CDATA
       * @param start  starting index of characters to output
       * @param length  number of characters to output
       */
      protected void fireCDATAEvent(char[] chars, int start, int length)
          throws org.xml.sax.SAXException
      {
          flushMyWriter();
  		if (m_tracer != null)
  			m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CDATA, chars, start,length);     	        	    	
      }
  
      /**
       * Report the comment trace event
       * @param chars  content of comment
       * @param start  starting index of comment to output
       * @param length  number of characters to output
       */
      protected void fireCommentEvent(char[] chars, int start, int length)
          throws org.xml.sax.SAXException
      {
          flushMyWriter();
  		if (m_tracer != null)
  			m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_COMMENT, new String(chars, start, length));     	        	    	
      }
  
  
      /**
       * To fire off end entity trace event
       * @param name Name of entity
       */
      public void fireEndEntity(String name)
          throws org.xml.sax.SAXException
      {
          flushMyWriter();
      	// we do not need to handle this.
      }    
  
      /**
       * To fire off start document trace  event
       */
       protected void fireStartDoc()
          throws org.xml.sax.SAXException
      {
          flushMyWriter();
          if (m_tracer != null)
              m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_STARTDOCUMENT);     	    
      }    
  
  
      /**
       * To fire off end document trace event
       */
      protected void fireEndDoc()
          throws org.xml.sax.SAXException
      {
          flushMyWriter();
          if (m_tracer != null)
          m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDDOCUMENT);     	        	
      }    
      
      /**
       * Report the start element trace event. This trace method needs to be
       * called just before the attributes are cleared.
       * 
       * @param elemName the qualified name of the element
       * 
       */
      protected void fireStartElem(String elemName)
          throws org.xml.sax.SAXException
      {
          flushMyWriter();
          if (m_tracer != null)
              m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_STARTELEMENT,
                  elemName, m_attributes);     	        	
      }    
  
  
      /**
       * To fire off the end element event
       * @param name Name of element
       */
  //    protected void fireEndElem(String name)
  //        throws org.xml.sax.SAXException
  //    {
  //        if (m_tracer != null)
  //            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDELEMENT,name, (Attributes)null);     	        	    	
  //    }    
  
  
      /**
       * To fire off the PI trace event
       * @param name Name of PI
       */
      protected void fireEscapingEvent(String name, String data)
          throws org.xml.sax.SAXException
      {
          flushMyWriter();
          if (m_tracer != null)
              m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_PI,name, data);     	        	    	
      }    
  
  
      /**
       * To fire off the entity reference trace event
       * @param name Name of entity reference
       */
      protected void fireEntityReference(String name)
          throws org.xml.sax.SAXException
      {
          flushMyWriter();
          if (m_tracer != null)
              m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENTITYREF,name, (Attributes)null);     	        	    	
      }    
  
      /**
       * Receive notification of the beginning of a document.
       * This method is never a self generated call, 
       * but only called externally.
       *
       * <p>The SAX parser will invoke this method only once, before any
       * other methods in this interface or in DTDHandler (except for
       * setDocumentLocator).</p>
       *
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       *
       * @throws org.xml.sax.SAXException
       */
      public void startDocument() throws org.xml.sax.SAXException
      {
  
          // if we do get called with startDocument(), handle it right away       
          startDocumentInternal();
          m_needToCallStartDocument = false;
          return;
      }   
      
      /**
       * This method handles what needs to be done at a startDocument() call,
       * whether from an external caller, or internally called in the 
       * serializer.  Historically Xalan has not always called a startDocument()
       * although it always calls endDocument() on the serializer.
       * So the serializer must be flexible for that. Even if no external call is
       * made into startDocument() this method will always be called as a self
       * generated internal startDocument, it handles what needs to be done at a
       * startDocument() call.
       * 
       * This method exists just to make sure that startDocument() is only ever
       * called from an external caller, which in principle is just a matter of
       * style.
       * 
       * @throws SAXException
       */
      protected void startDocumentInternal() throws org.xml.sax.SAXException
      {
      	this.fireStartDoc();
      } 
      /**
       * This method is used to set the source locator, which might be used to
       * generated an error message.
       * @param locator the source locator
       *
       * @see org.apache.xml.serializer.ExtendedContentHandler#setSourceLocator(javax.xml.transform.SourceLocator)
       */
      public void setSourceLocator(SourceLocator locator)
      {
          m_sourceLocator = locator;    
      }
  
      
      /** 
       * Used only by TransformerSnapshotImpl to restore the serialization 
       * to a previous state. 
       * 
       * @param NamespaceMappings
       */
      public void setNamespaceMappings(NamespaceMappings mappings) {
          m_prefixMap = mappings;
      }
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/SerializerConstants.java
  
  Index: SerializerConstants.java
  ===================================================================
  /*
   * @(#)$Id: SerializerConstants.java,v 1.1 2003/04/01 19:24:54 mkwan Exp $
   *
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 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
   *
   */
  package org.apache.xml.serializer;
  
  /**
   * @author minchau
   *
   * Constants used in serialization, such as the string "xmlns"
   */
  public interface SerializerConstants
  {
  
      /** To insert ]]> in a CDATA section by ending the last CDATA section with
       * ]] and starting the next CDATA section with >
       */
      static final String CDATA_CONTINUE = "]]]]><![CDATA[>";
      /**
       * The constant "]]>"
       */
      static final String CDATA_DELIMITER_CLOSE = "]]>";
      static final String CDATA_DELIMITER_OPEN = "<![CDATA[";
  
      static final char[] CNTCDATA = CDATA_CONTINUE.toCharArray();
      static final char[] BEGCDATA = CDATA_DELIMITER_OPEN.toCharArray();
      static final char[] ENDCDATA = CDATA_DELIMITER_CLOSE.toCharArray();
  
      static final String EMPTYSTRING = "";
  
      static final String ENTITY_AMP = "&amp;";
      static final String ENTITY_CRLF = "&#xA;";
      static final String ENTITY_GT = "&gt;";
      static final String ENTITY_LT = "&lt;";
      static final String ENTITY_QUOT = "&quot;";
  
      static final String XML_PREFIX = "xml";
      static final String XMLNS_PREFIX = "xmlns";
      static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
     
      public static final String DEFAULT_SAX_SERIALIZER="org.apache.xml.serializer.ToXMLSAXHandler";
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/SerializerFactory.java
  
  Index: SerializerFactory.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.util.Hashtable;
  import java.util.Properties;
  
  import javax.xml.transform.OutputKeys;
  
  import org.apache.xml.res.XMLErrorResources;
  import org.apache.xml.res.XMLMessages;
  import org.xml.sax.ContentHandler;
  
  /**
   * Factory for creating serializers.
   */
  public abstract class SerializerFactory
  {
  
    /*
     * Associates output methods to serializer classes.
     * (Don't use this right now.  -sb
     */
  
    // private static Hashtable _serializers = new Hashtable();
  
    /**
     * Associates output methods to default output formats.
     */
    private static Hashtable m_formats = new Hashtable();
  
    /**
     * Returns a serializer for the specified output method. Returns
     * null if no implementation exists that supports the specified
     * output method. For a list of the default output methods see
     * {@link Method}.
     *
     * @param format The output format
     * @return A suitable serializer, or null
     * @throws IllegalArgumentException (apparently -sc) if method is
     * null or an appropriate serializer can't be found
     * @throws WrappedRuntimeException (apparently -sc) if an
     * exception is thrown while trying to find serializer
     */
      public static Serializer getSerializer(Properties format)
      {
  
        Serializer ser = null;
  
        try
        {
          Class cls;
          String method = format.getProperty(OutputKeys.METHOD);
  
          if (method == null)
            throw new IllegalArgumentException(
              "The output format has a null method name");
  
  
  
          String className;
  
            className =
              format.getProperty(OutputPropertiesFactory.S_KEY_CONTENT_HANDLER);
  
            if (null == className)
            {
              throw new IllegalArgumentException(
                "The output format must have a '"
                + OutputPropertiesFactory.S_KEY_CONTENT_HANDLER + "' property!");
            }
  
            cls = Class.forName(className);
  
            // _serializers.put(method, cls);
  
  
          Object obj = cls.newInstance();
  
          if (obj instanceof SerializationHandler)
          {
                // this is one of the supplied serializers
              ser = (Serializer) cls.newInstance();
              ser.setOutputFormat(format);
          }
          else
          {
                /*
                 *  This  must be a user defined Serializer.
                 *  It had better implement ContentHandler.
                 */
                 if (obj instanceof ContentHandler)
                 {
  
                    /*
                     * The user defined serializer defines ContentHandler,
                     * but we need to wrap it with ToXMLSAXHandler which
                     * will collect SAX-like events and emit true
                     * SAX ContentHandler events to the users handler.
                     */
                    className = SerializerConstants.DEFAULT_SAX_SERIALIZER;
                    cls = Class.forName(className);
                    SerializationHandler sh =
                        (SerializationHandler) cls.newInstance();
                    sh.setContentHandler( (ContentHandler) obj);
                    sh.setOutputFormat(format);
  
                    ser = sh;
  
  
                 }
                 else
                 {
                    // user defined serializer does not implement
                    // ContentHandler, ... very bad
                     throw new Exception(
                         XMLMessages.createXMLMessage(
                             XMLErrorResources.ER_SERIALIZER_NOT_CONTENTHANDLER,
                                 new Object[] { className}));
                 }
  
          }
        }
        catch (Exception e)
        {
          throw new org.apache.xml.utils.WrappedRuntimeException(e);
        }
  
        return ser;
      }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/SerializerTrace.java
  
  Index: SerializerTrace.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import org.xml.sax.Attributes;
  
  /**
   * This interface defines a set of integer constants that identify trace event
   * types.
   */
  
  public interface SerializerTrace {
      
    /**
     * Event type generated when a document begins.
     *
     */
    public static final int EVENTTYPE_STARTDOCUMENT = 1;
  
    /**
     * Event type generated when a document ends.
     */
    public static final int EVENTTYPE_ENDDOCUMENT = 2;
  
    /**
     * Event type generated when an element begins (after the attributes have been processed but before the children have been added).
     */
    public static final int EVENTTYPE_STARTELEMENT = 3;
  
    /**
     * Event type generated when an element ends, after it's children have been added.
     */
    public static final int EVENTTYPE_ENDELEMENT = 4;
  
    /**
     * Event type generated for character data (CDATA and Ignorable Whitespace have their own events).
     */
    public static final int EVENTTYPE_CHARACTERS = 5;
  
    /**
     * Event type generated for ignorable whitespace (I'm not sure how much this is actually called.
     */
    public static final int EVENTTYPE_IGNORABLEWHITESPACE = 6;
  
    /**
     * Event type generated for processing instructions.
     */
    public static final int EVENTTYPE_PI = 7;
  
    /**
     * Event type generated after a comment has been added.
     */
    public static final int EVENTTYPE_COMMENT = 8;
  
    /**
     * Event type generate after an entity ref is created.
     */
    public static final int EVENTTYPE_ENTITYREF = 9;
  
    /**
     * Event type generated after CDATA is generated.
     */
    public static final int EVENTTYPE_CDATA = 10;
    
    /**
     * Event type generated when characters might be written to an output stream,
     *  but  these characters never are. They will ultimately be written out via
     * EVENTTYPE_OUTPUT_CHARACTERS. This type is used as attributes are collected.
     * Whenever the attributes change this event type is fired. At the very end
     * however, when the attributes do not change anymore and are going to be
     * ouput to the document the real characters will be written out using the
     * EVENTTYPE_OUTPUT_CHARACTERS.
     */
    public static final int EVENTTYPE_OUTPUT_PSEUDO_CHARACTERS = 11;
    
    /**
     * Event type generated when characters are written to an output stream.
     */
    public static final int EVENTTYPE_OUTPUT_CHARACTERS = 12;
      
  
    /**
     * Tell if trace listeners are present.
     *
     * @return True if there are trace listeners
     */
    public boolean hasTraceListeners();
    
    /**
     * Fire startDocument, endDocument events.
     *
     * @param eventType One of the EVENTTYPE_XXX constants.
     */
    public void fireGenerateEvent(int eventType);
    
    /**
     * Fire startElement, endElement events.
     *
     * @param eventType One of the EVENTTYPE_XXX constants.
     * @param name The name of the element.
     * @param atts The SAX attribute list.
     */
    public void fireGenerateEvent(int eventType, String name, Attributes atts);
    
    /**
     * Fire characters, cdata events.
     *
     * @param eventType One of the EVENTTYPE_XXX constants.
     * @param ch The char array from the SAX event.
     * @param start The start offset to be used in the char array.
     * @param length The end offset to be used in the chara array.
     */
    public void fireGenerateEvent(int eventType, char ch[], int start, int length);
    
    /**
     * Fire processingInstruction events.
     *
     * @param eventType One of the EVENTTYPE_XXX constants.
     * @param name The name of the processing instruction.
     * @param data The processing instruction data.
     */
    public void fireGenerateEvent(int eventType, String name, String data);
    
  
    /**
     * Fire comment and entity ref events.
     *
     * @param eventType One of the EVENTTYPE_XXX constants.
     * @param data The comment or entity ref data.
     */
    public void fireGenerateEvent(int eventType, String data);
    
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/SerializerTraceWriter.java
  
  Index: SerializerTraceWriter.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2003 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) 2003, International Business
   * Machines, Inc., http://www.ibm.com.  For more information on the Apache
   * Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.io.IOException;
  import java.io.Writer;
  
  /**
   * This class wraps the real writer, it only purpose is to send
   * CHARACTERTOSTREAM events to the trace listener. 
   * Each method immediately sends the call to the wrapped writer unchanged, but
   * in addition it collects characters to be issued to a trace listener.
   * 
   * In this way the trace
   * listener knows what characters have been written to the output Writer.
   * 
   * There may still be differences in what the trace events say is going to the
   * output writer and what is really going there. These differences will be due
   * to the fact that this class is UTF-8 encoding before emiting the trace event
   * and the underlying writer may not be UTF-8 encoding. There may also be
   * encoding differences.  So the main pupose of this class is to provide a
   * resonable facsimile of the true output.
   *
   */
  public class SerializerTraceWriter extends Writer
  {
  
      /** The real writer to immediately write to.
       * This reference may be null, in which case nothing is written out, but
       * only the trace events are fired for output.
       */
      private final java.io.Writer m_writer;
  
      /** The tracer to send events to */
      private final SerializerTrace m_tracer;
  
      /** The size of the internal buffer, just to keep too many
       * events from being sent to the tracer
       */
      private int buf_length;
  
      /**
       * Internal buffer to collect the characters to go to the trace listener.
       * 
       */
      private byte buf[];
  
      /**
       * How many bytes have been collected and still need to go to trace
       * listener.
       */
      private int count;
  
      /**
       * Creates or replaces the internal buffer, and makes sure it has a few
       * extra bytes slight overflow of the last UTF8 encoded character.
       * @param size
       */
      private void setBufferSize(int size)
      {
          buf = new byte[size + 3];
          buf_length = size;
          count = 0;
      }
  
      /**
       * Constructor.
       * If the writer passed in is null, then this SerializerTraceWriter will
       * only signal trace events of what would have been written to that writer.
       * If the writer passed in is not null then the trace events will mirror
       * what is going to that writer. In this way tools, such as a debugger, can
       * gather information on what is being written out.
       * 
       * @param out the Writer to write to (possibly null)
       * @param tracer the tracer to inform that characters are being written
       */
      public SerializerTraceWriter(Writer out, SerializerTrace tracer)
      {
          m_writer = out;
          m_tracer = tracer;
          setBufferSize(1024);
      }
  
      /**
       * Flush out the collected characters by sending them to the trace
       * listener.  These characters are never written to the real writer
       * (m_writer) because that has already happened with every method
       * call. This method simple informs the listener of what has already
       * happened.
       * @throws IOException
       */
      private void flushBuffer() throws IOException
      {
  
          // Just for tracing purposes
          if (count > 0)
          {
              char[] chars = new char[count];
              for(int i=0; i<count; i++)
                  chars[i] = (char) buf[i];
  
              if (m_tracer != null)
                  m_tracer.fireGenerateEvent(
                      SerializerTrace.EVENTTYPE_OUTPUT_CHARACTERS,
                      chars,
                      0,
                      chars.length);
  
              count = 0;
          }
      }
  
      /**
       * Flush the internal buffer and flush the Writer
       * @see java.io.Writer#flush()
       */
      public void flush() throws java.io.IOException
      {
          // send to the real writer
          if (m_writer != null)
              m_writer.flush();
  
          // from here on just for tracing purposes
          flushBuffer();
      }
  
      /**
       * Flush the internal buffer and close the Writer
       * @see java.io.Writer#close()
       */
      public void close() throws java.io.IOException
      {
          // send to the real writer
          if (m_writer != null)   
              m_writer.close();
  
          // from here on just for tracing purposes
          flushBuffer();
      }
  
  
      /**
       * Write a single character.  The character to be written is contained in
       * the 16 low-order bits of the given integer value; the 16 high-order bits
       * are ignored.
       *
       * <p> Subclasses that intend to support efficient single-character output
       * should override this method.
       *
       * @param c  int specifying a character to be written.
       * @exception  IOException  If an I/O error occurs
       */
      public void write(final int c) throws IOException
      {
          // send to the real writer
          if (m_writer != null)
              m_writer.write(c);
  
          // ---------- from here on just collect for tracing purposes
  
          /* If we are close to the end of the buffer then flush it.
           * Remember the buffer can hold a few more characters than buf_length
           */
          if (count >= buf_length)
              flushBuffer();
  
          if (c < 0x80)
          {
              buf[count++] = (byte) (c);
          }
          else if (c < 0x800)
          {
              buf[count++] = (byte) (0xc0 + (c >> 6));
              buf[count++] = (byte) (0x80 + (c & 0x3f));
          }
          else
          {
              buf[count++] = (byte) (0xe0 + (c >> 12));
              buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
              buf[count++] = (byte) (0x80 + (c & 0x3f));
          }
      }
  
      /**
       * Write a portion of an array of characters.
       *
       * @param  chars  Array of characters
       * @param  start   Offset from which to start writing characters
       * @param  length   Number of characters to write
       *
       * @exception  IOException  If an I/O error occurs
       *
       * @throws java.io.IOException
       */
      public void write(final char chars[], final int start, final int length)
          throws java.io.IOException
      {
          // send to the real writer
          if (m_writer != null)
              m_writer.write(chars, start, length);
  
          // from here on just collect for tracing purposes
          int lengthx3 = (length << 1) + length;
  
          if (lengthx3 >= buf_length)
          {
  
              /* If the request length exceeds the size of the output buffer,
                * flush the output buffer and make the buffer bigger to handle.
                */
  
              flushBuffer();
              setBufferSize(2 * lengthx3);
  
          }
  
          if (lengthx3 > buf_length - count)
          {
              flushBuffer();
          }
  
          final int n = length + start;
          for (int i = start; i < n; i++)
          {
              final char c = chars[i];
  
              if (c < 0x80)
                  buf[count++] = (byte) (c);
              else if (c < 0x800)
              {
                  buf[count++] = (byte) (0xc0 + (c >> 6));
                  buf[count++] = (byte) (0x80 + (c & 0x3f));
              }
              else
              {
                  buf[count++] = (byte) (0xe0 + (c >> 12));
                  buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
                  buf[count++] = (byte) (0x80 + (c & 0x3f));
              }
          }
  
      }
  
      /**
       * Write a string.
       *
       * @param  s  String to be written
       *
       * @exception  IOException  If an I/O error occurs
       */
      public void write(final String s) throws IOException
      {
          // send to the real writer
          if (m_writer != null)
              m_writer.write(s);
  
          // from here on just collect for tracing purposes
          final int length = s.length();
  
          // We multiply the length by three since this is the maximum length
          // of the characters that we can put into the buffer.  It is possible
          // for each Unicode character to expand to three bytes.
  
          int lengthx3 = (length << 1) + length;
  
          if (lengthx3 >= buf_length)
          {
  
              /* If the request length exceeds the size of the output buffer,
                * flush the output buffer and make the buffer bigger to handle.
                */
  
              flushBuffer();
              setBufferSize(2 * lengthx3);
          }
  
          if (lengthx3 > buf_length - count)
          {
              flushBuffer();
          }
  
          for (int i = 0; i < length; i++)
          {
              final char c = s.charAt(i);
  
              if (c < 0x80)
                  buf[count++] = (byte) (c);
              else if (c < 0x800)
              {
                  buf[count++] = (byte) (0xc0 + (c >> 6));
                  buf[count++] = (byte) (0x80 + (c & 0x3f));
              }
              else
              {
                  buf[count++] = (byte) (0xe0 + (c >> 12));
                  buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
                  buf[count++] = (byte) (0x80 + (c & 0x3f));
              }
          }
      }
  
  }
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ToHTMLSAXHandler.java
  
  Index: ToHTMLSAXHandler.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 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.xml.serializer;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.Writer;
  import java.util.Properties;
  
  import javax.xml.transform.Result;
  
  import org.w3c.dom.Node;
  import org.xml.sax.Attributes;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  import org.xml.sax.ext.LexicalHandler;
  
  /**
   * This class accepts SAX-like calls, then sends true SAX calls to a
   * wrapped SAX handler.  There is optimization done knowing that the ultimate
   * output is HTML.
   */
  public class ToHTMLSAXHandler extends ToSAXHandler
  {
  
      /**
       * Keeps track of whether output escaping is currently enabled
       */
      protected boolean m_escapeSetting = false;
  
      /**
       * Returns null.
       * @return null
       * @see org.apache.xml.serializer.Serializer#getOutputFormat()
       */
      public Properties getOutputFormat()
      {
          return null;
      }
  
      /**
       * Reurns null
       * @return null
       * @see org.apache.xml.serializer.Serializer#getOutputStream()
       */
      public OutputStream getOutputStream()
      {
          return null;
      }
  
      /**
       * Returns null
       * @return null
       * @see org.apache.xml.serializer.Serializer#getWriter()
       */
      public Writer getWriter()
      {
          return null;
      }
  
      /**
       * Does nothing.
       * @see org.apache.xml.serializer.SerializationHandler#indent(int)
       */
      public void indent(int n) throws SAXException
      {
      }
  
      /**
       * Returns false
       * @return false
       * @see org.apache.xml.serializer.Serializer#reset()
       */
      public boolean reset()
      {
          return false;
      }
  
      /**
       * Does nothing.
       * @see org.apache.xml.serializer.DOMSerializer#serialize(Node)
       */
      public void serialize(Node node) throws IOException
      {
          return;
      }
  
      /**
       * Turns special character escaping on/off.
       *
       *
       * @param excape true if escaping is to be set on.
       *
       * @see org.apache.xml.serializer.SerializationHandler#setEscaping(boolean)
       */
      public boolean setEscaping(boolean escape) throws SAXException
      {
          boolean oldEscapeSetting = m_escapeSetting;
          m_escapeSetting = escape;
  
          if (escape) {
              processingInstruction(Result.PI_ENABLE_OUTPUT_ESCAPING, "");
          } else {
              processingInstruction(Result.PI_DISABLE_OUTPUT_ESCAPING, "");
          }
  
          return oldEscapeSetting;
      }
  
      /**
       * Does nothing
       * @param indent the number of spaces to indent per indentation level
       * (ignored)
       * @see org.apache.xml.serializer.SerializationHandler#setIndent(boolean)
       */
      public void setIndent(boolean indent)
      {
      }
  
      /**
       * Does nothing.
       * @param format this parameter is not used
       * @see org.apache.xml.serializer.Serializer#setOutputFormat(Properties)
       */
      public void setOutputFormat(Properties format)
      {
      }
  
      /**
       * Does nothing.
       * @param output this parameter is ignored
       * @see org.apache.xml.serializer.Serializer#setOutputStream(OutputStream)
       */
      public void setOutputStream(OutputStream output)
      {
      }
  
  
      /**
       * Does nothing.
       * @param writer this parameter is ignored.
       * @see org.apache.xml.serializer.Serializer#setWriter(Writer)
       */
      public void setWriter(Writer writer)
      {
      }
  
      /**
       * @see org.xml.sax.ext.DeclHandler#attributeDecl(String, String, String, String, String)
       */
      /**
       * Does nothing.
       *
       * @param eName this parameter is ignored
       * @param aName this parameter is ignored
       * @param type this parameter is ignored
       * @param valueDefault this parameter is ignored
       * @param value this parameter is ignored
       * @see org.xml.sax.ext.DeclHandler#attributeDecl(String, String, String,String,String)
       */    
      public void attributeDecl(
          String eName,
          String aName,
          String type,
          String valueDefault,
          String value)
          throws SAXException
      {
      }
  
  
      /**
       * Does nothing.
       * @see org.xml.sax.ext.DeclHandler#elementDecl(String, String)
       */    
      public void elementDecl(String name, String model) throws SAXException
      {
          return;
      }
  
      /**
       * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(String, String, String)
       */
      public void externalEntityDecl(String arg0, String arg1, String arg2)
          throws SAXException
      {
      }
  
      /**
       * Does nothing.
       *
       * @see org.xml.sax.DTDHandler#unparsedEntityDecl
       */
      public void internalEntityDecl(String name, String value)
          throws SAXException
      {
      }
  
      /**
       * Receive notification of the end of an element.
       *
       * <p>The SAX parser will invoke this method at the end of every
       * element in the XML document; there will be a corresponding
       * startElement() event for every endElement() event (even when the
       * element is empty).</p>
       *
       * <p>If the element name has a namespace prefix, the prefix will
       * still be attached to the name.</p>
       *
       *
       * @param namespaceURI The Namespace URI, or the empty string if the
       *        element has no Namespace URI or if Namespace
       *        processing is not being performed.
       * @param localName The local name (without prefix), or the
       *        empty string if Namespace processing is not being
       *        performed.
       * @param name The qualified name (with prefix), or the
       *        empty string if qualified names are not available.
       * @param name The element type name
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       * @see org.xml.sax.ContentHandler#endElement(String, String, String)
       */
      public void endElement(String uri, String localName, String qName)
          throws SAXException
      {
          flushPending();
          m_saxHandler.endElement(uri, localName, qName);
          
          // time to fire off endElement event
          super.fireEndElem(qName);
      }
  
      /**
       * Does nothing.
       */
      public void endPrefixMapping(String prefix) throws SAXException
      {
      }
  
      /**
       * Does nothing.
       * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
       */
      public void ignorableWhitespace(char[] ch, int start, int length)
          throws SAXException
      {
      }
      
      /**
       * Receive notification of a processing instruction.
       *
       * <p>The Parser will invoke this method once for each processing
       * instruction found: note that processing instructions may occur
       * before or after the main document element.</p>
       *
       * <p>A SAX parser should never report an XML declaration (XML 1.0,
       * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
       * using this method.</p>
       *
       * @param target The processing instruction target.
       * @param data The processing instruction data, or null if
       *        none was supplied.
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       *
       * @throws org.xml.sax.SAXException
       * @see org.xml.sax.ContentHandler#processingInstruction(String, String)
       */
      public void processingInstruction(String arg0, String arg1)
          throws SAXException
      {
          flushPending();
          m_saxHandler.processingInstruction(arg0,arg1);
  
  		// time to fire off processing instruction event
  		super.fireEscapingEvent(arg0,arg1);        
      }
  
      /**
       * Does nothing.  
       * @see org.xml.sax.ContentHandler#setDocumentLocator(Locator)
       */
      public void setDocumentLocator(Locator arg0)
      {
          // do nothing
      }
  
      /**
       * Does nothing.
       * @see org.xml.sax.ContentHandler#skippedEntity(String)
       */
      public void skippedEntity(String arg0) throws SAXException
      {
      }
  
      /**
       * Receive notification of the beginning of an element, although this is a
       * SAX method additional namespace or attribute information can occur before
       * or after this call, that is associated with this element.
       *
       *
       * @param namespaceURI The Namespace URI, or the empty string if the
       *        element has no Namespace URI or if Namespace
       *        processing is not being performed.
       * @param localName The local name (without prefix), or the
       *        empty string if Namespace processing is not being
       *        performed.
       * @param qName The elements name.
       * @param atts The attributes attached to the element, if any.
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       * @see org.xml.sax.ContentHandler#startElement
       * @see org.xml.sax.ContentHandler#endElement
       * @see org.xml.sax.AttributeList
       *
       * @throws org.xml.sax.SAXException
       *
       * @see org.xml.sax.ContentHandler#startElement(String, String, String, Attributes)
       */
      public void startElement(
          String namespaceURI,
          String localName,
          String qName,
          Attributes atts)
          throws SAXException
      {
          flushPending();
          super.startElement(namespaceURI, localName, qName, atts);
          m_saxHandler.startElement(namespaceURI, localName, qName, atts);
          m_startTagOpen = false;
      }
  
      /**
       * Receive notification of a comment anywhere in the document. This callback
       * will be used for comments inside or outside the document element.
       * @param ch An array holding the characters in the comment.
       * @param start The starting position in the array.
       * @param length The number of characters to use from the array.
       * @throws org.xml.sax.SAXException The application may raise an exception.
       *
       * @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int)
       */
      public void comment(char[] ch, int start, int length) throws SAXException
      {
          flushPending();
          m_lexHandler.comment(ch, start, length);
  
          // time to fire off comment event
          super.fireCommentEvent(ch, start, length);
          return;
      }
  
      /**
       * Does nothing.
       * @see org.xml.sax.ext.LexicalHandler#endCDATA()
       */
      public void endCDATA() throws SAXException
      {
          return;
      }
  
      /**
       * Does nothing.
       * @see org.xml.sax.ext.LexicalHandler#endDTD()
       */
      public void endDTD() throws SAXException
      {
      }
  
      /**
       * Does nothing.
       * @see org.xml.sax.ext.LexicalHandler#startCDATA()
       */
      public void startCDATA() throws SAXException
      {
      }
  
      /**
       * Does nothing.
       * @see org.xml.sax.ext.LexicalHandler#startEntity(String)
       */
      public void startEntity(String arg0) throws SAXException
      {
      }
  
      /**
       * Receive notification of the end of a document.
       *
       * <p>The SAX parser will invoke this method only once, and it will
       * be the last method invoked during the parse.  The parser shall
       * not invoke this method until it has either abandoned parsing
       * (because of an unrecoverable error) or reached the end of
       * input.</p>
       *
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       *
       * @throws org.xml.sax.SAXException
       *
       * @see org.xml.sax.ContentHander#endDocument()
       */
      public void endDocument() throws SAXException
      {
          flushPending();
  
          // Close output document
          m_saxHandler.endDocument();
  
          super.fireEndDoc();        
      }
  
      /**
       * 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 SAXException
      {
  
          m_startTagOpen = false;
  
          // Now is time to send the startElement event
          m_saxHandler.startElement(
              EMPTYSTRING,
              m_elementName,
              m_elementName,
              m_attributes);
          m_attributes.clear();       
  
      }
  
      /**
       * Do nothing.
       * @see org.apache.xml.serializer.SerializationHandler#close()
       */
      public void close()
      {
          return;
      }
  
      /**
       * Receive notification of character data.
       *
       * @param chars The string of characters to process.
       *
       * @throws org.xml.sax.SAXException
       *
       * @see org.apache.xml.serializer.ExtendedContentHandler#characters(String)
       */
      public void characters(String chars) throws SAXException
      {
          this.characters(chars.toCharArray(), 0, chars.length());
          return;
      }
  
  
      /**
       * A constructor
       * @param handler the wrapped SAX content handler
       * @param encoding the encoding of the output HTML document
       */
      public ToHTMLSAXHandler(ContentHandler handler, String encoding)
      {
          super(handler,encoding);
      }
      /**
       * A constructor.
       * @param handler the wrapped SAX content handler
       * @param lex the wrapped lexical handler
       * @param encoding the encoding of the output HTML document
       */
      public ToHTMLSAXHandler(
          ContentHandler handler,
          LexicalHandler lex,
          String encoding)
      {
          super(handler,lex,encoding);
      }
  
      /**
       * An element starts, but attributes are not fully known yet.
       *
       * @param elementNamespaceURI the URI of the namespace of the element
       * (optional)
       * @param elementLocalName the element name, but without prefix
       * (optional)
       * @param elementName the element name, with prefix, if any (required)
       *
       * @see org.apache.xml.serializer.ExtendedContentHandler#startElement(String)
       */
      public void startElement(
          String elementNamespaceURI,
          String elementLocalName,
          String elementName) throws SAXException
      {
  
          super.startElement(elementNamespaceURI, elementLocalName, elementName);
  
          flushPending();
  
          // Handle document type declaration (for first element only)
          if (m_lexHandler != null)
          {
              String doctypeSystem = getDoctypeSystem();
              String doctypePublic = getDoctypePublic();
              if ((doctypeSystem != null) || (doctypePublic != null))
                  m_lexHandler.startDTD(
                      elementName,
                      doctypePublic,
                      doctypeSystem);
              m_lexHandler = null;
          }
  
          m_currentElemDepth++;
          m_elementName = elementName;         // required
          m_elementLocalName = elementLocalName; // possibly null (optional)
          m_elementURI = elementNamespaceURI;  // possibly null (optional)
  //        m_attributes.clear();
          m_startTagOpen = true;
  
      }
      /**
       * An element starts, but attributes are not fully known yet.
       *
       * @param elementName the element name, with prefix, if any
       *
       * @see org.apache.xml.serializer.ExtendedContentHandler#startElement(String)
       */
      public void startElement(String elementName) throws SAXException
      {
          this.startElement(null,null, elementName);
      }
      
      /**
       * Receive notification of the end of an element.
       * @param elementName The element type name
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *     wrapping another exception.
       *
       * @see org.apache.xml.serializer.ExtendedContentHandler#endElement(String)
       */
      public void endElement(String elementName) throws SAXException
      {
          flushPending();
          m_saxHandler.endElement(EMPTYSTRING, elementName, elementName);
  
          // time to fire off endElement event
          super.fireEndElem(elementName);        
      }
  
      /**
       * Receive notification of character data.
       *
       * <p>The Parser will call this method to report each chunk of
       * character data.  SAX parsers may return all contiguous character
       * data in a single chunk, or they may split it into several
       * chunks; however, all of the characters in any single event
       * must come from the same external entity, so that the Locator
       * provides useful information.</p>
       *
       * <p>The application must not attempt to read from the array
       * outside of the specified range.</p>
       *
       * <p>Note that some parsers will report whitespace using the
       * ignorableWhitespace() method rather than this one (validating
       * parsers must do so).</p>
       *
       * @param ch The characters from the XML document.
       * @param off The start position in the array.
       * @param len The number of characters to read from the array.
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       * @see #ignorableWhitespace
       * @see org.xml.sax.Locator
       *
       * @throws org.xml.sax.SAXException
       *
       * @see org.xml.sax.ContentHandler#characters(char[], int, int)
       */
      public void characters(char[] ch, int off, int len) throws SAXException
      {
  
          flushPending();
          m_saxHandler.characters(ch, off, len);
  
          // time to fire off characters event
          super.fireCharEvent(ch, off, len);        
      }
  
      /**
       * This method flushes any pending events, which can be startDocument()
       * closing the opening tag of an element, or closing an open CDATA section.
       */
      public void flushPending()
      {
  		if (m_needToCallStartDocument)
  		{
  			try {startDocumentInternal();
  			m_needToCallStartDocument = false;
  			} catch (SAXException e) {}
  		}       	
          // Close any open element
          if (m_startTagOpen)
          {
              try
              {
                  closeStartTag();
              }
              catch(SAXException se)
              {
                  // do something ??
              }
              m_startTagOpen = false;
          }
      }
      /**
       * Handle a prefix/uri mapping, which is associated with a startElement()
       * that is soon to follow. Need to close any open start tag to make
       * sure than any name space attributes due to this event are associated wih
       * the up comming element, not the current one.
       * @see org.xml.sax.ExtendedContentHandler#startPrefixMapping
       *
       * @param prefix The Namespace prefix being declared.
       * @param uri The Namespace URI the prefix is mapped to.
       * @param shouldFlush true if any open tags need to be closed first, this
       * will impact which element the mapping applies to (open parent, or its up
       * comming child)
       * @return returns true if the call made a change to the current
       * namespace information, false if it did not change anything, e.g. if the
       * prefix/namespace mapping was already in scope from before.
       *
       * @throws org.xml.sax.SAXException The client may throw
       *            an exception during processing.
       */    
      public boolean startPrefixMapping(
          String prefix,
          String uri,
          boolean shouldFlush)
          throws SAXException
      {
          // no namespace support for HTML
          if (shouldFlush) 
              flushPending();   
          m_saxHandler.startPrefixMapping(prefix,uri);
          return false;
      }
  
      /**
       * Begin the scope of a prefix-URI Namespace mapping
       * just before another element is about to start.
       * This call will close any open tags so that the prefix mapping
       * will not apply to the current element, but the up comming child.
       *
       * @see org.xml.sax.ContentHandler#startPrefixMapping
       *
       * @param prefix The Namespace prefix being declared.
       * @param uri The Namespace URI the prefix is mapped to.
       *
       * @throws org.xml.sax.SAXException The client may throw
       *            an exception during processing.
       *
       */
      public void startPrefixMapping(String prefix, String uri)
          throws org.xml.sax.SAXException
      {
          startPrefixMapping(prefix,uri,true);        
      }
  
      /**
       * This method is used when a prefix/uri namespace mapping
       * is indicated after the element was started with a
       * startElement() and before and endElement().
       * startPrefixMapping(prefix,uri) would be used before the
       * startElement() call.
       * @param prefix the prefix associated with the given URI.
       * @param uri the URI of the namespace
       *
       * @see org.apache.xml.serializer.ExtendedContentHandler#namespaceAfterStartElement(String, String)
       */
      public void namespaceAfterStartElement(
          final String prefix,
          final String uri)
          throws SAXException
      {
          // hack for XSLTC with finding URI for default namespace
          if (m_elementURI == null)
          {
              String prefix1 = getPrefixPart(m_elementName);
              if (prefix1 == null && EMPTYSTRING.equals(prefix))
              {
                  // the elements URI is not known yet, and it
                  // doesn't have a prefix, and we are currently
                  // setting the uri for prefix "", so we have
                  // the uri for the element... lets remember it
                  m_elementURI = uri;
              }
          }       
          startPrefixMapping(prefix,uri,false);
      }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ToHTMLStream.java
  
  Index: ToHTMLStream.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 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.xml.serializer;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.UnsupportedEncodingException;
  import java.util.Properties;
  
  import javax.xml.transform.Result;
  
  import org.apache.xml.res.XMLErrorResources;
  import org.apache.xml.res.XMLMessages;
  import org.apache.xml.utils.BoolStack;
  import org.apache.xml.utils.Trie;
  import org.xml.sax.Attributes;
  import org.xml.sax.SAXException;
  
  /**
   * @author minchau
   *
   * To change this generated comment edit the template variable "typecomment":
   * Window>Preferences>Java>Templates.
   * To enable and disable the creation of type comments go to
   * Window>Preferences>Java>Code Generation.
   */
  public class ToHTMLStream extends ToStream 
  {
      /** State stack to keep track of if the current element has output 
       *  escaping disabled. 
       */
      protected BoolStack m_isRawStack = new BoolStack();
  
      /** True if the current element is a block element.  (seems like 
       *  this needs to be a stack. -sb). */
      private boolean m_inBlockElem = false;
  
      /**
       * Map that tells which XML characters should have special treatment, and it
       *  provides character to entity name lookup.
       */
      protected static CharInfo m_htmlcharInfo =
  //        new CharInfo(CharInfo.HTML_ENTITIES_RESOURCE);
          CharInfo.getCharInfo(CharInfo.HTML_ENTITIES_RESOURCE);
  
      /** A digital search trie for fast, case insensitive lookup of ElemDesc objects. */
      static Trie m_elementFlags = new Trie();
  
      static {
  
          // HTML 4.0 loose DTD
          m_elementFlags.put("BASEFONT", new ElemDesc(0 | ElemDesc.EMPTY));
          m_elementFlags.put(
              "FRAME",
              new ElemDesc(0 | ElemDesc.EMPTY | ElemDesc.BLOCK));
          m_elementFlags.put("FRAMESET", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put("NOFRAMES", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put(
              "ISINDEX",
              new ElemDesc(0 | ElemDesc.EMPTY | ElemDesc.BLOCK));
          m_elementFlags.put(
              "APPLET",
              new ElemDesc(0 | ElemDesc.WHITESPACESENSITIVE));
          m_elementFlags.put("CENTER", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put("DIR", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put("MENU", new ElemDesc(0 | ElemDesc.BLOCK));
  
          // HTML 4.0 strict DTD
          m_elementFlags.put("TT", new ElemDesc(0 | ElemDesc.FONTSTYLE));
          m_elementFlags.put("I", new ElemDesc(0 | ElemDesc.FONTSTYLE));
          m_elementFlags.put("B", new ElemDesc(0 | ElemDesc.FONTSTYLE));
          m_elementFlags.put("BIG", new ElemDesc(0 | ElemDesc.FONTSTYLE));
          m_elementFlags.put("SMALL", new ElemDesc(0 | ElemDesc.FONTSTYLE));
          m_elementFlags.put("EM", new ElemDesc(0 | ElemDesc.PHRASE));
          m_elementFlags.put("STRONG", new ElemDesc(0 | ElemDesc.PHRASE));
          m_elementFlags.put("DFN", new ElemDesc(0 | ElemDesc.PHRASE));
          m_elementFlags.put("CODE", new ElemDesc(0 | ElemDesc.PHRASE));
          m_elementFlags.put("SAMP", new ElemDesc(0 | ElemDesc.PHRASE));
          m_elementFlags.put("KBD", new ElemDesc(0 | ElemDesc.PHRASE));
          m_elementFlags.put("VAR", new ElemDesc(0 | ElemDesc.PHRASE));
          m_elementFlags.put("CITE", new ElemDesc(0 | ElemDesc.PHRASE));
          m_elementFlags.put("ABBR", new ElemDesc(0 | ElemDesc.PHRASE));
          m_elementFlags.put("ACRONYM", new ElemDesc(0 | ElemDesc.PHRASE));
          m_elementFlags.put(
              "SUP",
              new ElemDesc(0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL));
          m_elementFlags.put(
              "SUB",
              new ElemDesc(0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL));
          m_elementFlags.put(
              "SPAN",
              new ElemDesc(0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL));
          m_elementFlags.put(
              "BDO",
              new ElemDesc(0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL));
          m_elementFlags.put(
              "BR",
              new ElemDesc(
                  0
                      | ElemDesc.SPECIAL
                      | ElemDesc.ASPECIAL
                      | ElemDesc.EMPTY
                      | ElemDesc.BLOCK));
          m_elementFlags.put("BODY", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put(
              "ADDRESS",
              new ElemDesc(
                  0
                      | ElemDesc.BLOCK
                      | ElemDesc.BLOCKFORM
                      | ElemDesc.BLOCKFORMFIELDSET));
          m_elementFlags.put(
              "DIV",
              new ElemDesc(
                  0
                      | ElemDesc.BLOCK
                      | ElemDesc.BLOCKFORM
                      | ElemDesc.BLOCKFORMFIELDSET));
          m_elementFlags.put("A", new ElemDesc(0 | ElemDesc.SPECIAL));
          m_elementFlags.put(
              "MAP",
              new ElemDesc(
                  0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL | ElemDesc.BLOCK));
          m_elementFlags.put(
              "AREA",
              new ElemDesc(0 | ElemDesc.EMPTY | ElemDesc.BLOCK));
          m_elementFlags.put(
              "LINK",
              new ElemDesc(
                  0 | ElemDesc.HEADMISC | ElemDesc.EMPTY | ElemDesc.BLOCK));
          m_elementFlags.put(
              "IMG",
              new ElemDesc(
                  0
                      | ElemDesc.SPECIAL
                      | ElemDesc.ASPECIAL
                      | ElemDesc.EMPTY
                      | ElemDesc.WHITESPACESENSITIVE));
          m_elementFlags.put(
              "OBJECT",
              new ElemDesc(
                  0
                      | ElemDesc.SPECIAL
                      | ElemDesc.ASPECIAL
                      | ElemDesc.HEADMISC
                      | ElemDesc.WHITESPACESENSITIVE));
          m_elementFlags.put("PARAM", new ElemDesc(0 | ElemDesc.EMPTY));
          m_elementFlags.put(
              "HR",
              new ElemDesc(
                  0
                      | ElemDesc.BLOCK
                      | ElemDesc.BLOCKFORM
                      | ElemDesc.BLOCKFORMFIELDSET
                      | ElemDesc.EMPTY));
          m_elementFlags.put(
              "P",
              new ElemDesc(
                  0
                      | ElemDesc.BLOCK
                      | ElemDesc.BLOCKFORM
                      | ElemDesc.BLOCKFORMFIELDSET));
          m_elementFlags.put(
              "H1",
              new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK));
          m_elementFlags.put(
              "H2",
              new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK));
          m_elementFlags.put(
              "H3",
              new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK));
          m_elementFlags.put(
              "H4",
              new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK));
          m_elementFlags.put(
              "H5",
              new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK));
          m_elementFlags.put(
              "H6",
              new ElemDesc(0 | ElemDesc.HEAD | ElemDesc.BLOCK));
          m_elementFlags.put(
              "PRE",
              new ElemDesc(0 | ElemDesc.PREFORMATTED | ElemDesc.BLOCK));
          m_elementFlags.put(
              "Q",
              new ElemDesc(0 | ElemDesc.SPECIAL | ElemDesc.ASPECIAL));
          m_elementFlags.put(
              "BLOCKQUOTE",
              new ElemDesc(
                  0
                      | ElemDesc.BLOCK
                      | ElemDesc.BLOCKFORM
                      | ElemDesc.BLOCKFORMFIELDSET));
          m_elementFlags.put("INS", new ElemDesc(0));
          m_elementFlags.put("DEL", new ElemDesc(0));
          m_elementFlags.put(
              "DL",
              new ElemDesc(
                  0
                      | ElemDesc.BLOCK
                      | ElemDesc.BLOCKFORM
                      | ElemDesc.BLOCKFORMFIELDSET));
          m_elementFlags.put("DT", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put("DD", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put(
              "OL",
              new ElemDesc(0 | ElemDesc.LIST | ElemDesc.BLOCK));
          m_elementFlags.put(
              "UL",
              new ElemDesc(0 | ElemDesc.LIST | ElemDesc.BLOCK));
          m_elementFlags.put("LI", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put("FORM", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put("LABEL", new ElemDesc(0 | ElemDesc.FORMCTRL));
          m_elementFlags.put(
              "INPUT",
              new ElemDesc(
                  0 | ElemDesc.FORMCTRL | ElemDesc.INLINELABEL | ElemDesc.EMPTY));
          m_elementFlags.put(
              "SELECT",
              new ElemDesc(0 | ElemDesc.FORMCTRL | ElemDesc.INLINELABEL));
          m_elementFlags.put("OPTGROUP", new ElemDesc(0));
          m_elementFlags.put("OPTION", new ElemDesc(0));
          m_elementFlags.put(
              "TEXTAREA",
              new ElemDesc(0 | ElemDesc.FORMCTRL | ElemDesc.INLINELABEL));
          m_elementFlags.put(
              "FIELDSET",
              new ElemDesc(0 | ElemDesc.BLOCK | ElemDesc.BLOCKFORM));
          m_elementFlags.put("LEGEND", new ElemDesc(0));
          m_elementFlags.put(
              "BUTTON",
              new ElemDesc(0 | ElemDesc.FORMCTRL | ElemDesc.INLINELABEL));
          m_elementFlags.put(
              "TABLE",
              new ElemDesc(
                  0
                      | ElemDesc.BLOCK
                      | ElemDesc.BLOCKFORM
                      | ElemDesc.BLOCKFORMFIELDSET));
          m_elementFlags.put("CAPTION", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put("THEAD", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put("TFOOT", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put("TBODY", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put("COLGROUP", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put(
              "COL",
              new ElemDesc(0 | ElemDesc.EMPTY | ElemDesc.BLOCK));
          m_elementFlags.put("TR", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put("TH", new ElemDesc(0));
          m_elementFlags.put("TD", new ElemDesc(0));
          m_elementFlags.put(
              "HEAD",
              new ElemDesc(0 | ElemDesc.BLOCK | ElemDesc.HEADELEM));
          m_elementFlags.put("TITLE", new ElemDesc(0 | ElemDesc.BLOCK));
          m_elementFlags.put(
              "BASE",
              new ElemDesc(0 | ElemDesc.EMPTY | ElemDesc.BLOCK));
          m_elementFlags.put(
              "META",
              new ElemDesc(
                  0 | ElemDesc.HEADMISC | ElemDesc.EMPTY | ElemDesc.BLOCK));
          m_elementFlags.put(
              "STYLE",
              new ElemDesc(
                  0 | ElemDesc.HEADMISC | ElemDesc.RAW | ElemDesc.BLOCK));
          m_elementFlags.put(
              "SCRIPT",
              new ElemDesc(
                  0
                      | ElemDesc.SPECIAL
                      | ElemDesc.ASPECIAL
                      | ElemDesc.HEADMISC
                      | ElemDesc.RAW));
          m_elementFlags.put(
              "NOSCRIPT",
              new ElemDesc(
                  0
                      | ElemDesc.BLOCK
                      | ElemDesc.BLOCKFORM
                      | ElemDesc.BLOCKFORMFIELDSET));
          m_elementFlags.put("HTML", new ElemDesc(0 | ElemDesc.BLOCK));
  
          // From "John Ky" <hand@syd.speednet.com.au
          // Transitional Document Type Definition ()
          // file:///C:/Documents%20and%20Settings/sboag.BOAG600E/My%20Documents/html/sgml/loosedtd.html#basefont
          m_elementFlags.put("FONT", new ElemDesc(0 | ElemDesc.FONTSTYLE));
  
          // file:///C:/Documents%20and%20Settings/sboag.BOAG600E/My%20Documents/html/present/graphics.html#edef-STRIKE
          m_elementFlags.put("S", new ElemDesc(0 | ElemDesc.FONTSTYLE));
          m_elementFlags.put("STRIKE", new ElemDesc(0 | ElemDesc.FONTSTYLE));
  
          // file:///C:/Documents%20and%20Settings/sboag.BOAG600E/My%20Documents/html/present/graphics.html#edef-U
          m_elementFlags.put("U", new ElemDesc(0 | ElemDesc.FONTSTYLE));
  
          // From "John Ky" <hand@syd.speednet.com.au
          m_elementFlags.put("NOBR", new ElemDesc(0 | ElemDesc.FONTSTYLE));
  
          // HTML 4.0, section 16.5
          m_elementFlags.put(
              "IFRAME",
              new ElemDesc(
                  0
                      | ElemDesc.BLOCK
                      | ElemDesc.BLOCKFORM
                      | ElemDesc.BLOCKFORMFIELDSET));
          // NS4 extensions
          m_elementFlags.put(
              "LAYER",
              new ElemDesc(
                  0
                      | ElemDesc.BLOCK
                      | ElemDesc.BLOCKFORM
                      | ElemDesc.BLOCKFORMFIELDSET));
          m_elementFlags.put(
              "ILAYER",
              new ElemDesc(
                  0
                      | ElemDesc.BLOCK
                      | ElemDesc.BLOCKFORM
                      | ElemDesc.BLOCKFORMFIELDSET));
  
          ElemDesc elemDesc;
  
          elemDesc = (ElemDesc) m_elementFlags.get("AREA");
  
          elemDesc.setAttr("HREF", ElemDesc.ATTRURL);
          elemDesc.setAttr("NOHREF", ElemDesc.ATTREMPTY);
  
          elemDesc = (ElemDesc) m_elementFlags.get("BASE");
  
          elemDesc.setAttr("HREF", ElemDesc.ATTRURL);
  
          elemDesc = (ElemDesc) m_elementFlags.get("BLOCKQUOTE");
  
          elemDesc.setAttr("CITE", ElemDesc.ATTRURL);
  
          elemDesc = (ElemDesc) m_elementFlags.get("Q");
  
          elemDesc.setAttr("CITE", ElemDesc.ATTRURL);
  
          elemDesc = (ElemDesc) m_elementFlags.get("INS");
  
          elemDesc.setAttr("CITE", ElemDesc.ATTRURL);
  
          elemDesc = (ElemDesc) m_elementFlags.get("DEL");
  
          elemDesc.setAttr("CITE", ElemDesc.ATTRURL);
  
          elemDesc = (ElemDesc) m_elementFlags.get("A");
  
          elemDesc.setAttr("HREF", ElemDesc.ATTRURL);
          elemDesc.setAttr("NAME", ElemDesc.ATTRURL);
  
          elemDesc = (ElemDesc) m_elementFlags.get("LINK");
          elemDesc.setAttr("HREF", ElemDesc.ATTRURL);
  
          elemDesc = (ElemDesc) m_elementFlags.get("INPUT");
  
          elemDesc.setAttr("SRC", ElemDesc.ATTRURL);
          elemDesc.setAttr("USEMAP", ElemDesc.ATTRURL);
          elemDesc.setAttr("CHECKED", ElemDesc.ATTREMPTY);
          elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY);
          elemDesc.setAttr("ISMAP", ElemDesc.ATTREMPTY);
          elemDesc.setAttr("READONLY", ElemDesc.ATTREMPTY);
  
          elemDesc = (ElemDesc) m_elementFlags.get("SELECT");
  
          elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY);
          elemDesc.setAttr("MULTIPLE", ElemDesc.ATTREMPTY);
  
          elemDesc = (ElemDesc) m_elementFlags.get("OPTGROUP");
  
          elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY);
  
          elemDesc = (ElemDesc) m_elementFlags.get("OPTION");
  
          elemDesc.setAttr("SELECTED", ElemDesc.ATTREMPTY);
          elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY);
  
          elemDesc = (ElemDesc) m_elementFlags.get("TEXTAREA");
  
          elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY);
          elemDesc.setAttr("READONLY", ElemDesc.ATTREMPTY);
  
          elemDesc = (ElemDesc) m_elementFlags.get("BUTTON");
  
          elemDesc.setAttr("DISABLED", ElemDesc.ATTREMPTY);
  
          elemDesc = (ElemDesc) m_elementFlags.get("SCRIPT");
  
          elemDesc.setAttr("SRC", ElemDesc.ATTRURL);
          elemDesc.setAttr("FOR", ElemDesc.ATTRURL);
          elemDesc.setAttr("DEFER", ElemDesc.ATTREMPTY);
  
          elemDesc = (ElemDesc) m_elementFlags.get("IMG");
  
          elemDesc.setAttr("SRC", ElemDesc.ATTRURL);
          elemDesc.setAttr("LONGDESC", ElemDesc.ATTRURL);
          elemDesc.setAttr("USEMAP", ElemDesc.ATTRURL);
          elemDesc.setAttr("ISMAP", ElemDesc.ATTREMPTY);
  
          elemDesc = (ElemDesc) m_elementFlags.get("OBJECT");
  
          elemDesc.setAttr("CLASSID", ElemDesc.ATTRURL);
          elemDesc.setAttr("CODEBASE", ElemDesc.ATTRURL);
          elemDesc.setAttr("DATA", ElemDesc.ATTRURL);
          elemDesc.setAttr("ARCHIVE", ElemDesc.ATTRURL);
          elemDesc.setAttr("USEMAP", ElemDesc.ATTRURL);
          elemDesc.setAttr("DECLARE", ElemDesc.ATTREMPTY);
  
          elemDesc = (ElemDesc) m_elementFlags.get("FORM");
  
          elemDesc.setAttr("ACTION", ElemDesc.ATTRURL);
  
          elemDesc = (ElemDesc) m_elementFlags.get("HEAD");
  
          elemDesc.setAttr("PROFILE", ElemDesc.ATTRURL);
  
          // Attribution to: "Voytenko, Dimitry" <DV...@SECTORBASE.COM>
          elemDesc = (ElemDesc) m_elementFlags.get("FRAME");
  
          elemDesc.setAttr("SRC", ElemDesc.ATTRURL);
          elemDesc.setAttr("LONGDESC", ElemDesc.ATTRURL);
  
          // HTML 4.0, section 16.5
          elemDesc = (ElemDesc) m_elementFlags.get("IFRAME");
  
          elemDesc.setAttr("SRC", ElemDesc.ATTRURL);
          elemDesc.setAttr("LONGDESC", ElemDesc.ATTRURL);
  
          // NS4 extensions
          elemDesc = (ElemDesc) m_elementFlags.get("LAYER");
  
          elemDesc.setAttr("SRC", ElemDesc.ATTRURL);
  
          elemDesc = (ElemDesc) m_elementFlags.get("ILAYER");
  
          elemDesc.setAttr("SRC", ElemDesc.ATTRURL);
  
          elemDesc = (ElemDesc) m_elementFlags.get("DIV");
  
          elemDesc.setAttr("SRC", ElemDesc.ATTRURL);
      }
  
      /**
       * Dummy element for elements not found.
       */
      static private ElemDesc m_dummy = new ElemDesc(0 | ElemDesc.BLOCK);
  
      /** True if URLs should be specially escaped with the %xx form. */
      private boolean m_specialEscapeURLs = true;
  
      /** True if the META tag should be omitted. */
      private boolean m_omitMetaTag = false;
  
      /** Element description of the element currently being processed */
      private ElemDesc m_elementDesc = null;
  
      /**
       * Tells if the formatter should use special URL escaping.
       *
       * @param bool True if URLs should be specially escaped with the %xx form.
       */
      public void setSpecialEscapeURLs(boolean bool)
      {
          m_specialEscapeURLs = bool;
      }
  
      /**
       * Tells if the formatter should omit the META tag.
       *
       * @param bool True if the META tag should be omitted.
       */
      public void setOmitMetaTag(boolean bool)
      {
          m_omitMetaTag = bool;
      }
  
      /**
       * Specifies an output format for this serializer. It the
       * serializer has already been associated with an output format,
       * it will switch to the new format. This method should not be
       * called while the serializer is in the process of serializing
       * a document.
       *
       * @param format The output format to use
       */
      public void setOutputFormat(Properties format)
      {
   
          m_specialEscapeURLs =
              OutputPropertyUtils.getBooleanProperty(
                  OutputPropertiesFactory.S_USE_URL_ESCAPING,
                  format);
  
          m_omitMetaTag =
              OutputPropertyUtils.getBooleanProperty(
                  OutputPropertiesFactory.S_OMIT_META_TAG,
                  format);
  
          super.setOutputFormat(format);
      }
  
      /**
       * Tells if the formatter should use special URL escaping.
       *
       * @return True if URLs should be specially escaped with the %xx form.
       */
      private final boolean getSpecialEscapeURLs()
      {
          return m_specialEscapeURLs;
      }
  
      /**
       * Tells if the formatter should omit the META tag.
       *
       * @return True if the META tag should be omitted.
       */
      private final boolean getOmitMetaTag()
      {
          return m_omitMetaTag;
      }
  
      /**
       * Get a description of the given element.
       *
       * @param name non-null name of element, case insensitive.
       *
       * @return non-null reference to ElemDesc, which may be m_dummy if no 
       *         element description matches the given name.
       */
      private final ElemDesc getElemDesc(String name)
      {
  
          if (null != name)
          {
              Object obj = m_elementFlags.get(name);
  
              if (null != obj)
                  return (ElemDesc) obj;
          }
  
          return m_dummy;
      }
  
      /**
       * Default constructor.
       */
      public ToHTMLStream()
      {
  
          super();
          m_charInfo = m_htmlcharInfo;
          // initialize namespaces
          m_prefixMap = new NamespaceMappings();
  
      }
  
      /** The name of the current element. */
      private String m_currentElementName = null;
  
      /**
       * Receive notification of the beginning of a document.
       *
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       *
       * @throws org.xml.sax.SAXException
       */
      protected void startDocumentInternal() throws org.xml.sax.SAXException
      {
          super.startDocumentInternal();
  
          m_needToCallStartDocument = false; 
          m_needToOutputDocTypeDecl = true;
          m_startNewLine = false;
          setOmitXMLDeclaration(true);
  
          if (true == m_needToOutputDocTypeDecl)
          {
              String doctypeSystem = getDoctypeSystem();
              String doctypePublic = getDoctypePublic();
              if ((null != doctypeSystem) || (null != doctypePublic))
              {
                  try
                  {
                  m_writer.write("<!DOCTYPE HTML");
  
                  if (null != doctypePublic)
                  {
                      m_writer.write(" PUBLIC \"");
                      m_writer.write(doctypePublic);
                      m_writer.write("\"");
                  }
  
                  if (null != doctypeSystem)
                  {
                      if (null == doctypePublic)
                          m_writer.write(" SYSTEM \"");
                      else
                          m_writer.write(" \"");
  
                      m_writer.write(doctypeSystem);
                      m_writer.write("\"");
                  }
  
                  m_writer.write(">");
                  outputLineSep();
                  }
                  catch(IOException e)
                  {
                      throw new SAXException(e);
                  }
              }
          }
  
          m_needToOutputDocTypeDecl = false;
      }
  
      /**
       * Receive notification of the end of a document. 
       *
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       *
       * @throws org.xml.sax.SAXException
       */
      public final void endDocument() throws org.xml.sax.SAXException
      {
          
          flushPending();
          if (m_doIndent && !m_isprevtext)
          {
              try
              {
              outputLineSep();
              }
              catch(IOException e)
              {
                  throw new SAXException(e);
              }
          }
  
          flushWriter();
  
          super.fireEndDoc();
      }
  
      /**
       *  Receive notification of the beginning of an element.
       *
       *
       *  @param namespaceURI
       *  @param localName
       *  @param name The element type name.
       *  @param atts The attributes attached to the element, if any.
       *  @throws org.xml.sax.SAXException Any SAX exception, possibly
       *             wrapping another exception.
       *  @see #endElement
       *  @see org.xml.sax.AttributeList
       */
      public void startElement(
          String namespaceURI,
          String localName,
          String name,
          Attributes atts)
          throws org.xml.sax.SAXException
      {
          // System.out.println("SerializerToHTML#startElement("+namespaceURI+", "+localName+", "+name+", ...);");
  
          if (m_cdataTagOpen)
              closeCDATA();
          else if (m_needToCallStartDocument)
              startDocumentInternal();
              
  //        if (m_needToOutputDocTypeDecl 
  //        && ( (null != getDoctypeSystem()) || (null!= getDoctypePublic())))
  //        {
  //            outputDocTypeDecl(name, true);
  //        }
  //        m_needToOutputDocTypeDecl = false;
  
  
          if (null != namespaceURI && namespaceURI.length() > 0)
          {
              super.startElement(namespaceURI, localName, name, atts);
  
              return;
          }
  
          try
          {
          boolean savedDoIndent = m_doIndent;
          boolean noLineBreak;
          if (m_startTagOpen)
          {
              closeStartTag();
              m_startTagOpen = false;
          }
  
          ElemDesc elemDesc = getElemDesc(name);
          // remember for later
          m_elementLocalName = localName;
          m_elementURI = namespaceURI;
          m_elementName = name;
          m_elementDesc = elemDesc;
          
          // ElemDesc parentElemDesc = getElemDesc(m_currentElementName);
          boolean isBlockElement = elemDesc.is(ElemDesc.BLOCK);
          boolean isHeadElement = elemDesc.is(ElemDesc.HEADELEM);
  
          // boolean isWhiteSpaceSensitive = elemDesc.is(ElemDesc.WHITESPACESENSITIVE);
          if (m_ispreserve)
              m_ispreserve = false;
          else if (
              m_doIndent
              && (null != m_currentElementName)
              && (!m_inBlockElem || isBlockElement) /* && !isWhiteSpaceSensitive */
              )
          {
              m_startNewLine = true;
  
              indent();
          }
  
          m_inBlockElem = !isBlockElement;
  
          m_isRawStack.push(elemDesc.is(ElemDesc.RAW));
  
          m_currentElementName = name;
  
          // m_parents.push(m_currentElementName);
          m_writer.write('<');
          m_writer.write(name);
  
          if (atts != null)
              addAttributes(atts);
  
          // mark that the closing '>' of the starting tag is not yet written out
          m_startTagOpen = true;
          m_currentElemDepth++; // current element is one element deeper
          m_isprevtext = false;
          m_doIndent = savedDoIndent;
  
          if (isHeadElement)
          {
              if (m_startTagOpen)
                  closeStartTag();
  
              if (!m_omitMetaTag)
              {
                  if (m_doIndent)
                      indent();
  
                  m_writer.write("<META http-equiv=\"Content-Type\" content=\"text/html; charset=");
  
                  // String encoding = Encodings.getMimeEncoding(m_encoding).toLowerCase();
                  String encoding = getEncoding();
                  String encode = Encodings.getMimeEncoding(encoding);
  
                  m_writer.write(encode);
                  m_writer.write('"');
                  m_writer.write('>');
              }
          }
          }
          catch(IOException e)
          {
              throw new SAXException(e);
          }
      }
  
      /**
       *  Receive notification of the end of an element.
       *
       *
       *  @param namespaceURI
       *  @param localName
       *  @param name The element type name
       *  @throws org.xml.sax.SAXException Any SAX exception, possibly
       *             wrapping another exception.
       */
      public final void endElement(
          String namespaceURI,
          String localName,
          String name)
          throws org.xml.sax.SAXException
      {
          // System.out.println("SerializerToHTML#endElement("+namespaceURI+", "+localName+", "+name+");");
  
          if (m_cdataTagOpen)
              closeCDATA();
  
          if (null != namespaceURI && namespaceURI.length() > 0)
          {
              super.endElement(namespaceURI, localName, name);
  
              return;
          }
  
          m_currentElemDepth--;
  
          // System.out.println(m_currentElementName);
          // m_parents.pop();
          m_isRawStack.pop();
  
          ElemDesc elemDesc = getElemDesc(name);
          m_elementDesc = elemDesc;
  
          // ElemDesc parentElemDesc = getElemDesc(m_currentElementName);
          boolean isBlockElement = elemDesc.is(ElemDesc.BLOCK);
          boolean shouldIndent = false;
  
          if (m_ispreserve)
          {
              m_ispreserve = false;
          }
          else if (m_doIndent && (!m_inBlockElem || isBlockElement))
          {
              m_startNewLine = true;
              shouldIndent = true;
  
              // indent(m_currentIndent);
          }
  
          m_inBlockElem = !isBlockElement;
  
          try
          {
          if (!m_startTagOpen)
          {
              // this block is like a copy of closeStartTag()
              // except that 
              if (shouldIndent)
                  indent();
  
              m_writer.write("</");
              m_writer.write(name);
              m_writer.write('>');
  
              m_currentElementName = name;
  
              m_cdataSectionStates.pop();
              if (!m_preserves.isEmpty())
                  m_preserves.pop();
          }
          else
          {
              /* process any attributes gathered after the
               * startElement(String) call
               */
              processAttributes();
              if (!elemDesc.is(ElemDesc.EMPTY))
              {
                  m_writer.write('>');
  
                  // As per Dave/Paul recommendation 12/06/2000
                  // if (shouldIndent)
                  //  indent(m_currentIndent);
  
                  m_writer.write('<');
                  m_writer.write('/');
                  m_writer.write(name);
                  m_writer.write('>');
              }
              else
              {
                  m_writer.write('>');
              }
  
              /* no need to call m_cdataSectionStates.pop();
               * because pushCdataSectionState() was never called
               * ... the endElement call came before we had a chance
               * to push the state.
               */
  
          }
  
          if (elemDesc.is(ElemDesc.WHITESPACESENSITIVE))
              m_ispreserve = true;
  
          /* we don't have any open tags anymore, since we just 
           * wrote out a closing ">" 
           */
          m_startTagOpen = false;
  
          m_isprevtext = false;
          
          }
          catch(IOException e)
          {
              throw new SAXException(e);
          }
  
          // fire off the end element event
          super.fireEndElem(name);        
   
      }
  
      /**
       * Process an attribute.
       * @param   name   The name of the attribute.
       * @param   value   The value of the attribute.
       * @param   elemDesc The description of the HTML element 
       *           that has this attribute.
       *
       * @throws org.xml.sax.SAXException
       */
      protected void processAttribute(
          String name,
          String value,
          ElemDesc elemDesc)
          throws IOException
      {
  
          m_writer.write(' ');
  
          if (   ((value.length() == 0) || value.equalsIgnoreCase(name))
              && elemDesc != null 
              && elemDesc.isAttrFlagSet(name, ElemDesc.ATTREMPTY))
          {
              m_writer.write(name);
          }
          else
          {
              m_writer.write(name);
              m_writer.write('=');
  
              m_writer.write('\"');
              if (   elemDesc != null
                  && elemDesc.isAttrFlagSet(name, ElemDesc.ATTRURL))
                  writeAttrURI(value, m_specialEscapeURLs);
              else
                  writeAttrString(value, this.getEncoding());
              m_writer.write('\"');
  
          }
      }
  
      /**
       * Tell if a character is an ASCII digit.
       */
      private boolean isASCIIDigit(char c)
      {
          return (c >= '0' && c <= '9');
      }
  
      /**
       * Make an integer into an HH hex value.
       * Does no checking on the size of the input, since this 
       * is only meant to be used locally by writeAttrURI.
       * 
       * @param i must be a value less than 255.
       * 
       * @return should be a two character string.
       */
      private String makeHHString(int i)
      {
          String s = Integer.toHexString(i).toUpperCase();
          if (s.length() == 1)
          {
              s = "0" + s;
          }
          return s;
      }
  
      /**
      * Dmitri Ilyin: Makes sure if the String is HH encoded sign.
      * @param str must be 2 characters long
      *
      * @return true or false
      */
      private boolean isHHSign(String str)
      {
          boolean sign = true;
          try
          {
              char r = (char) Integer.parseInt(str, 16);
          }
          catch (NumberFormatException e)
          {
              sign = false;
          }
          return sign;
      }
  
      /**
       * Write the specified <var>string</var> after substituting non ASCII characters,
       * with <CODE>%HH</CODE>, where HH is the hex of the byte value.
       *
       * @param   string      String to convert to XML format.
       * @param doURLEscaping True if we should try to encode as 
       *                      per http://www.ietf.org/rfc/rfc2396.txt.
       *
       * @throws org.xml.sax.SAXException if a bad surrogate pair is detected.
       */
      public void writeAttrURI(String string, boolean doURLEscaping)
          throws IOException
      {
          // http://www.ietf.org/rfc/rfc2396.txt says:
          // A URI is always in an "escaped" form, since escaping or unescaping a
          // completed URI might change its semantics.  Normally, the only time
          // escape encodings can safely be made is when the URI is being created
          // from its component parts; each component may have its own set of
          // characters that are reserved, so only the mechanism responsible for
          // generating or interpreting that component can determine whether or
          // not escaping a character will change its semantics. Likewise, a URI
          // must be separated into its components before the escaped characters
          // within those components can be safely decoded.
          //
          // ...So we do our best to do limited escaping of the URL, without 
          // causing damage.  If the URL is already properly escaped, in theory, this 
          // function should not change the string value.
  
          char[] stringArray = string.toCharArray();
          int len = stringArray.length;
  
          for (int i = 0; i < len; i++)
          {
              char ch = stringArray[i];
  
              if ((ch < 32) || (ch > 126))
              {
                  if (doURLEscaping)
                  {
                      // Encode UTF16 to UTF8.
                      // Reference is Unicode, A Primer, by Tony Graham.
                      // Page 92.
  
                      // Note that Kay doesn't escape 0x20...
                      //  if(ch == 0x20) // Not sure about this... -sb
                      //  {
                      //    m_writer.write(ch);
                      //  }
                      //  else 
                      if (ch <= 0x7F)
                      {
                          m_writer.write('%');
                          m_writer.write(makeHHString(ch));
                      }
                      else if (ch <= 0x7FF)
                      {
                          // Clear low 6 bits before rotate, put high 4 bits in low byte, 
                          // and set two high bits.
                          int high = (ch >> 6) | 0xC0;
                          int low = (ch & 0x3F) | 0x80;
                          // First 6 bits, + high bit
                          m_writer.write('%');
                          m_writer.write(makeHHString(high));
                          m_writer.write('%');
                          m_writer.write(makeHHString(low));
                      }
                      else if (isUTF16Surrogate(ch)) // high surrogate
                      {
                          // I'm sure this can be done in 3 instructions, but I choose 
                          // to try and do it exactly like it is done in the book, at least 
                          // until we are sure this is totally clean.  I don't think performance 
                          // is a big issue with this particular function, though I could be 
                          // wrong.  Also, the stuff below clearly does more masking than 
                          // it needs to do.
  
                          // Clear high 6 bits.
                          int highSurrogate = ((int) ch) & 0x03FF;
  
                          // Middle 4 bits (wwww) + 1
                          // "Note that the value of wwww from the high surrogate bit pattern
                          // is incremented to make the uuuuu bit pattern in the scalar value 
                          // so the surrogate pair don't address the BMP."
                          int wwww = ((highSurrogate & 0x03C0) >> 6);
                          int uuuuu = wwww + 1;
  
                          // next 4 bits
                          int zzzz = (highSurrogate & 0x003C) >> 2;
  
                          // low 2 bits
                          int yyyyyy = ((highSurrogate & 0x0003) << 4) & 0x30;
  
                          // Get low surrogate character.
                          ch = stringArray[++i];
  
                          // Clear high 6 bits.
                          int lowSurrogate = ((int) ch) & 0x03FF;
  
                          // put the middle 4 bits into the bottom of yyyyyy (byte 3)
                          yyyyyy = yyyyyy | ((lowSurrogate & 0x03C0) >> 6);
  
                          // bottom 6 bits.
                          int xxxxxx = (lowSurrogate & 0x003F);
  
                          int byte1 = 0xF0 | (uuuuu >> 2); // top 3 bits of uuuuu
                          int byte2 =
                              0x80 | (((uuuuu & 0x03) << 4) & 0x30) | zzzz;
                          int byte3 = 0x80 | yyyyyy;
                          int byte4 = 0x80 | xxxxxx;
  
                          m_writer.write('%');
                          m_writer.write(makeHHString(byte1));
                          m_writer.write('%');
                          m_writer.write(makeHHString(byte2));
                          m_writer.write('%');
                          m_writer.write(makeHHString(byte3));
                          m_writer.write('%');
                          m_writer.write(makeHHString(byte4));
                      }
                      else
                      {
                          int high = (ch >> 12) | 0xE0; // top 4 bits
                          int middle = ((ch & 0x0FC0) >> 6) | 0x80;
                          // middle 6 bits
                          int low = (ch & 0x3F) | 0x80;
                          // First 6 bits, + high bit
                          m_writer.write('%');
                          m_writer.write(makeHHString(high));
                          m_writer.write('%');
                          m_writer.write(makeHHString(middle));
                          m_writer.write('%');
                          m_writer.write(makeHHString(low));
                      }
  
                  }
                  else if (escapingNotNeeded(ch))
                  {
                      m_writer.write(ch);
                  }
                  else
                  {
                      m_writer.write("&#");
                      m_writer.write(Integer.toString(ch));
                      m_writer.write(';');
                  }
              }
              else if ('%' == ch)
              {
                  // If the character is a '%' number number, try to avoid double-escaping.
                  // There is a question if this is legal behavior.
  
                  // Dmitri Ilyin: to check if '%' number number is invalid. It must be checked if %xx is a sign, that would be encoded
                  // The encoded signes are in Hex form. So %xx my be in form %3C that is "<" sign. I will try to change here a little.
  
                  //        if( ((i+2) < len) && isASCIIDigit(stringArray[i+1]) && isASCIIDigit(stringArray[i+2]) )
  
                  // We are no longer escaping '%'
                  /* if ( ((i+2) < len) && isHHSign(new String(stringArray,i+1,2)) )
                   {
                     m_writer.write(ch);
                   }
                   else
                   {
                     if (doURLEscaping)
                     {
                      m_writer.write('%');
                      m_writer.write(makeHHString(ch));
                     }
                     else*/
                  m_writer.write(ch);
                  // }   
  
              }
              // Since http://www.ietf.org/rfc/rfc2396.txt refers to the URI grammar as
              // not allowing quotes in the URI proper syntax, nor in the fragment 
              // identifier, we believe that it's OK to double escape quotes.
              else if (ch == '"')
              {
                  // Mike Kay encodes this as &#34;, so he may know something I don't?
                  if (doURLEscaping)
                      m_writer.write("%22");
                  else
                      m_writer.write("&quot;"); // we have to escape this, I guess.
              }
              else
              {
                  m_writer.write(ch);
              }
          }
  
      }
  
      /**
       * Writes the specified <var>string</var> after substituting <VAR>specials</VAR>,
       * and UTF-16 surrogates for character references <CODE>&amp;#xnn</CODE>.
       *
       * @param   string      String to convert to XML format.
       * @param   encoding    CURRENTLY NOT IMPLEMENTED.
       *
       * @throws org.xml.sax.SAXException
       */
      public void writeAttrString(String string, String encoding)
          throws IOException
      {
  
          final char chars[] = string.toCharArray();
          final int strLen = chars.length;
  
          for (int i = 0; i < strLen; i++)
          {
              char ch = chars[i];
  
              // System.out.println("SPECIALSSIZE: "+SPECIALSSIZE);
              // System.out.println("ch: "+(int)ch);
              // System.out.println("m_maxCharacter: "+(int)m_maxCharacter);
              // System.out.println("m_attrCharsMap[ch]: "+(int)m_attrCharsMap[ch]);
              if (escapingNotNeeded(ch) && (!m_charInfo.isSpecial(ch)))
              {
                  m_writer.write(ch);
              }
              else if ('<' == ch || '>' == ch)
              {
                  m_writer.write(ch); // no escaping in this case, as specified in 15.2
              }
              else if (
                  ('&' == ch) && ((i + 1) < strLen) && ('{' == chars[i + 1]))
              {
                  m_writer.write(ch); // no escaping in this case, as specified in 15.2
              }
              else
              {
                  int pos = accumDefaultEntity(m_writer, ch, i, chars, strLen, false);
  
                  if (i != pos)
                  {
                      i = pos - 1;
                  }
                  else
                  {
                      if (isUTF16Surrogate(ch))
                      {
   
                              i = writeUTF16Surrogate(ch, chars, i, strLen);
  
                      }
  
                      // The next is kind of a hack to keep from escaping in the case 
                      // of Shift_JIS and the like.
  
                      /*
                      else if ((ch < m_maxCharacter) && (m_maxCharacter == 0xFFFF)
                      && (ch != 160))
                      {
                      m_writer.write(ch);  // no escaping in this case
                      }
                      else
                      */
                      String entityName = m_charInfo.getEntityNameForChar(ch);
  
                      if (null != entityName)
                      {
                          m_writer.write('&');
                          m_writer.write(entityName);
                          m_writer.write(';');
                      }
                      else if (escapingNotNeeded(ch))
                      {
                          m_writer.write(ch); // no escaping in this case
                      }
                      else
                      {
                          m_writer.write("&#");
                          m_writer.write(Integer.toString(ch));
                          m_writer.write(';');
                      }
                  }
              }
          }
      }
  
  
  
      /**
       * Receive notification of character data.
       *
       * <p>The Parser will call this method to report each chunk of
       * character data.  SAX parsers may return all contiguous character
       * data in a single chunk, or they may split it into several
       * chunks; however, all of the characters in any single event
       * must come from the same external entity, so that the Locator
       * provides useful information.</p>
       *
       * <p>The application must not attempt to read from the array
       * outside of the specified range.</p>
       *
       * <p>Note that some parsers will report whitespace using the
       * ignorableWhitespace() method rather than this one (validating
       * parsers must do so).</p>
       *
       * @param chars The characters from the XML document.
       * @param start The start position in the array.
       * @param length The number of characters to read from the array.
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       * @see #ignorableWhitespace
       * @see org.xml.sax.Locator
       *
       * @throws org.xml.sax.SAXException
       */
      public final void characters(char chars[], int start, int length)
          throws org.xml.sax.SAXException
      {
  
          if (m_isRawStack.peekOrFalse())
          {
              try
              {
                  if (m_startTagOpen)
                  {
                      closeStartTag();
                      m_startTagOpen = false;
                  }
                  m_ispreserve = true;
                  
  //              With m_ispreserve just set true it looks like shouldIndent()
  //              will always return false, so drop any possible indentation.
  //              if (shouldIndent())
  //                  indent();
  
                  // m_writer.write("<![CDATA[");
                  // m_writer.write(chars, start, length);
                  writeNormalizedChars(chars, start, length, false);
  
                  // m_writer.write("]]>");
                  
                  // time to generate characters event
                  super.fireCharEvent(chars, start, length);
                  
                  return;
              }
              catch (IOException ioe)
              {
                  throw new org.xml.sax.SAXException(
                      XMLMessages.createXMLMessage(
                          XMLErrorResources.ER_OIERROR,
                          null),
                      ioe);
                  //"IO error", ioe);
              }
          }
          else
          {
              super.characters(chars, start, length);
          }
      }
  
      /**
       *  Receive notification of cdata.
       *
       *  <p>The Parser will call this method to report each chunk of
       *  character data.  SAX parsers may return all contiguous character
       *  data in a single chunk, or they may split it into several
       *  chunks; however, all of the characters in any single event
       *  must come from the same external entity, so that the Locator
       *  provides useful information.</p>
       *
       *  <p>The application must not attempt to read from the array
       *  outside of the specified range.</p>
       *
       *  <p>Note that some parsers will report whitespace using the
       *  ignorableWhitespace() method rather than this one (validating
       *  parsers must do so).</p>
       *
       *  @param ch The characters from the XML document.
       *  @param start The start position in the array.
       *  @param length The number of characters to read from the array.
       *  @throws org.xml.sax.SAXException Any SAX exception, possibly
       *             wrapping another exception.
       *  @see #ignorableWhitespace
       *  @see org.xml.sax.Locator
       *
       * @throws org.xml.sax.SAXException
       */
      public final void cdata(char ch[], int start, int length)
          throws org.xml.sax.SAXException
      {
  
          if ((null != m_currentElementName)
              && (m_currentElementName.equalsIgnoreCase("SCRIPT")
                  || m_currentElementName.equalsIgnoreCase("STYLE")))
          {
              try
              {
                  if (m_startTagOpen)
                  {
                      closeStartTag();
                      m_startTagOpen = false;
                  }
  
                  m_ispreserve = true;
  
                  if (shouldIndent())
                      indent();
  
                  // m_writer.write(ch, start, length);
                  writeNormalizedChars(ch, start, length, true);
              }
              catch (IOException ioe)
              {
                  throw new org.xml.sax.SAXException(
                      XMLMessages.createXMLMessage(
                          XMLErrorResources.ER_OIERROR,
                          null),
                      ioe);
                  //"IO error", ioe);
              }
          }
          else
          {
              super.cdata(ch, start, length);
          }
      }
  
      /**
       *  Receive notification of a processing instruction.
       *
       *  @param target The processing instruction target.
       *  @param data The processing instruction data, or null if
       *         none was supplied.
       *  @throws org.xml.sax.SAXException Any SAX exception, possibly
       *             wrapping another exception.
       *
       * @throws org.xml.sax.SAXException
       */
      public void processingInstruction(String target, String data)
          throws org.xml.sax.SAXException
      {
  
  		// Process any pending starDocument and startElement first.
  		flushPending(); 
  		
          // Use a fairly nasty hack to tell if the next node is supposed to be 
          // unescaped text.
          if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING))
          {
              startNonEscaping();
          }
          else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING))
          {
              endNonEscaping();
          }
          else
          {
              try
              {
              if (m_startTagOpen)
              {
                  closeStartTag();
                  m_startTagOpen = false;
              }
              else if (m_needToCallStartDocument)
                  startDocumentInternal();
  
              if (shouldIndent())
                  indent();
  
              m_writer.write("<?" + target);
  
              if (data.length() > 0 && !Character.isSpaceChar(data.charAt(0)))
                  m_writer.write(" ");
  
              m_writer.write(data + ">"); // different from XML
  
              // Always output a newline char if not inside of an 
              // element. The whitespace is not significant in that
              // case.
              if (m_currentElemDepth <= 0)
                  outputLineSep();
  
              m_startNewLine = true;
              }
              catch(IOException e)
              {
                  throw new SAXException(e);
              }
          }
                 
          // now generate the PI event
          super.fireEscapingEvent(target, data);
       }
  
      /**
       * Receive notivication of a entityReference.
       *
       * @param name non-null reference to entity name string.
       *
       * @throws org.xml.sax.SAXException
       */
      public final void entityReference(String name)
          throws org.xml.sax.SAXException
      {
          try
          {
  
          m_writer.write("&");
          m_writer.write(name);
          m_writer.write(";");
          
          } catch(IOException e)
          {
              throw new SAXException(e);
          }
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#endElement(String)
       */
      public final void endElement(String elemName) throws SAXException
      {
          endElement(null, null, elemName);
      }
  
      /**
       * If passed in via attribSAX, process the official SAX attributes
       * otherwise process the collected attributes from SAX-like
       * calls for an element from calls to 
       * attribute(String name, String value)
       * 
       * @param attribSAX official attributes from a SAX call to startElement
       *
       * @throws org.xml.sax.SAXException
       */
      public void processAttributes()
          throws IOException,SAXException
      {
  
          // finish processing attributes, time to fire off the start element event
          super.fireStartElem(m_elementName);
                  
          int nAttrs = 0;
          if ((nAttrs = m_attributes.getLength()) > 0)
          {
              /* 
               * process the collected attributes
               */
              for (int i = 0; i < nAttrs; i++)
              {
                  processAttribute(
                      m_attributes.getQName(i),
                      m_attributes.getValue(i),
                      m_elementDesc);
              }
              
  
                       
              
  
                       
              m_attributes.clear();
  
          }
      }
      /**
       * @see org.apache.xml.serializer.Serializer#asDOMSerializer()
       */
      public DOMSerializer asDOMSerializer() throws IOException
      {
          return null;
      }
  
      /**
       * For the enclosing elements starting tag write out out any attributes
       * followed by ">"
       *
       *@throws org.xml.sax.SAXException
       */
      protected void closeStartTag() throws SAXException
      {
          if (m_startTagOpen)
          {
              try
              {
                  
              processAttributes();
  
              m_writer.write('>');
  
              /* whether Xalan or XSLTC, we have the prefix mappings now, so
               * lets determine if the current element is specified in the cdata-
               * section-elements list.
               */
              pushCdataSectionState();
  
              m_isprevtext = false;
              m_preserves.push(m_ispreserve);
              m_startTagOpen = false;
              
              }
              catch(IOException e)
              {
                  throw new SAXException(e);
              }
          }
      }
      /**
       * Initialize the serializer with the specified output stream and output
       * format. Must be called before calling any of the serialize methods.
       *
       * @param output The output stream to use
       * @param format The output format
       * @throws UnsupportedEncodingException The encoding specified   in the
       * output format is not supported
       */
      protected synchronized void init(OutputStream output, Properties format)
          throws UnsupportedEncodingException
      {
          if (null == format)
          {
              format = OutputPropertiesFactory.getDefaultMethodProperties(Method.HTML);
           }
          super.init(output,format, false);
      }
      
          /**
           * Specifies an output stream to which the document should be
           * serialized. This method should not be called while the
           * serializer is in the process of serializing a document.
           * <p>
           * The encoding specified in the output properties is used, or
           * if no encoding was specified, the default for the selected
           * output method.
           *
           * @param output The output stream
           */
          public void setOutputStream(OutputStream output)
          {
  
              try
              {
                  Properties format;
                  if (null == m_format)
                      format = OutputPropertiesFactory.getDefaultMethodProperties(Method.HTML);
                  else
                      format = m_format;
                  init(output, format, true);
              }
              catch (UnsupportedEncodingException uee)
              {
  
                  // Should have been warned in init, I guess...
              }
          }    
          /**
           * This method is used when a prefix/uri namespace mapping
           * is indicated after the element was started with a
           * startElement() and before and endElement().
           * startPrefixMapping(prefix,uri) would be used before the
           * startElement() call.
           * @param uri the URI of the namespace
           * @param prefix the prefix associated with the given URI.
           *
           * @see org.apache.xml.serializer.ExtendedContentHandler#namespaceAfterStartElement(String, String)
           */
          public void namespaceAfterStartElement(String prefix, String uri)
              throws SAXException
          {
              // hack for XSLTC with finding URI for default namespace
              if (m_elementURI == null)
              {
                  String prefix1 = getPrefixPart(m_elementName);
                  if (prefix1 == null && EMPTYSTRING.equals(prefix))
                  {
                      // the elements URI is not known yet, and it
                      // doesn't have a prefix, and we are currently
                      // setting the uri for prefix "", so we have
                      // the uri for the element... lets remember it
                      m_elementURI = uri;
                  }
              }            
              startPrefixMapping(prefix,uri,false);
          }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ToSAXHandler.java
  
  Index: ToSAXHandler.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 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.xml.serializer;
  
  import java.util.Vector;
  
  import org.xml.sax.Attributes;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.ErrorHandler;
  import org.xml.sax.SAXException;
  import org.xml.sax.SAXParseException;
  import org.xml.sax.ext.LexicalHandler;
  
  /**
   * @author minchau
   *
   * To change this generated comment edit the template variable "typecomment":
   * Window>Preferences>Java>Templates.
   * To enable and disable the creation of type comments go to
   * Window>Preferences>Java>Code Generation.
   */
  abstract public class ToSAXHandler extends SerializerBase 
  {
      public ToSAXHandler()
      {
      }
  
      public ToSAXHandler(
          ContentHandler hdlr,
          LexicalHandler lex,
          String encoding)
      {
          setContentHandler(hdlr);
          setLexHandler(lex);
          setEncoding(encoding);
      }
      public ToSAXHandler(ContentHandler handler, String encoding)
      {
          setContentHandler(handler);
          setEncoding(encoding);
      }
  
      /**
       * Underlying SAX handler. Taken from XSLTC
       */
      protected ContentHandler m_saxHandler;
  
      /**
       * Underlying LexicalHandler. Taken from XSLTC
       */
      protected LexicalHandler m_lexHandler;
  
      
      /** If this is true, then the content handler wrapped by this
       * serializer implements the TransformState interface which
       * will give the content handler access to the state of
       * the transform. */
      protected TransformStateSetter m_state = null;
  
      /**
       * Pass callback to the SAX Handler
       */
      protected void startDocumentInternal() throws SAXException
      {
          if (m_needToCallStartDocument)  
          {
              super.startDocumentInternal();
  
              m_saxHandler.startDocument();
              m_needToCallStartDocument = false;
          }
      }
      /**
       * Do nothing.
       * @see org.xml.sax.ext.LexicalHandler#startDTD(String, String, String)
       */
      public void startDTD(String arg0, String arg1, String arg2)
          throws SAXException
      {
          // do nothing for now
      }
  
      /**
       * Receive notification of character data.
       *
       * @param chars The string of characters to process.
       *
       * @throws org.xml.sax.SAXException
       *
       * @see org.apache.xml.serializer.ExtendedContentHandler#characters(String)
       */
      public void characters(String characters) throws SAXException
      {
          characters(characters.toCharArray(), 0, characters.length());
      }
  
      /**
       * Receive notification of a comment.
       *
       * @see org.apache.xml.serializer.ExtendedLexicalHandler#comment(String)
       */
      public void comment(String comment) throws SAXException
      {
  
          // Close any open element before emitting comment
          if (m_startTagOpen)
          {
              closeStartTag();
          }
          else if (m_cdataTagOpen)
          {
              closeCDATA();
          }
  
          // Ignore if a lexical handler has not been set
          if (m_lexHandler != null)
          {
              m_lexHandler.comment(comment.toCharArray(), 0, comment.length());
  
              // time to fire off comment event
              super.fireCommentEvent(comment.toCharArray(), 0, comment.length());
          }
  
      }
  
      /**
       * Do nothing as this is an abstract class. All subclasses will need to
       * define their behavior if it is different.
       * @see org.xml.sax.ContentHandler#processingInstruction(String, String)
       */
      public void processingInstruction(String target, String data)
          throws SAXException
      {
          // Redefined in SAXXMLOutput
      }
  
      protected void closeStartTag() throws SAXException
      {
      }
  
      protected void closeCDATA() throws SAXException
      {
          // Redefined in SAXXMLOutput
      }
      
      /**
       * Receive notification of the beginning of an element, although this is a
       * SAX method additional namespace or attribute information can occur before
       * or after this call, that is associated with this element.
       *
       *
       * @param namespaceURI The Namespace URI, or the empty string if the
       *        element has no Namespace URI or if Namespace
       *        processing is not being performed.
       * @param localName The local name (without prefix), or the
       *        empty string if Namespace processing is not being
       *        performed.
       * @param name The element type name.
       * @param atts The attributes attached to the element, if any.
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       * @see org.xml.sax.ContentHandler#startElement
       * @see org.xml.sax.ContentHandler#endElement
       * @see org.xml.sax.AttributeList
       *
       * @throws org.xml.sax.SAXException
       *
       * @see org.xml.sax.ContentHandler#startElement(String,String,String,Attributes)
       */
      public void startElement(
          String arg0,
          String arg1,
          String arg2,
          Attributes arg3)
          throws SAXException
      {
          if (m_state != null) {
              m_state.resetState(getTransformer());
          }
  
      	// fire off the start element event
      	super.fireStartElem(arg2);    	
      }
  
      /**
       * Sets the LexicalHandler.
       * @param _lexHandler The LexicalHandler to set
       */
      public void setLexHandler(LexicalHandler _lexHandler)
      {
          this.m_lexHandler = _lexHandler;
      }
  
      /**
       * Sets the SAX ContentHandler.
       * @param m_saxHandler The ContentHandler to set
       */
      public void setContentHandler(ContentHandler _saxHandler)
      {
          this.m_saxHandler = _saxHandler;
          if (m_lexHandler == null && _saxHandler instanceof LexicalHandler)
          {
              // we are not overwriting an existing LexicalHandler, and _saxHandler
              // is also implements LexicalHandler, so lets use it
              m_lexHandler = (LexicalHandler) _saxHandler;
          }
      }
  
      /**
       * Does nothing. The setting of CDATA section elements has an impact on
       * stream serializers.
       * @see org.apache.xml.serializer.SerializationHandler#setCdataSectionElements(java.util.Vector)
       */
      public void setCdataSectionElements(Vector URI_and_localNames)
      {
          // do nothing
      }
  
      /**
       * This method flushes any pending events, which can be startDocument()
       * closing the opening tag of an element, or closing an open CDATA section.
       */
      public void flushPending()
      {
          try
          {
              if (m_needToCallStartDocument)
              {
                  startDocumentInternal();
                  m_needToCallStartDocument = false;
              }
  
              if (m_startTagOpen)
              {
                  closeStartTag();
                  m_startTagOpen = false;
              }
              
              if (m_cdataTagOpen)
              {
                  closeCDATA();
                  m_cdataTagOpen = false;
              }
          }
          catch (SAXException e)
          {
              // can we do anything useful here,
              // or should this method throw a SAXException?
          }
  
      }
  
      /**
       * Pass in a reference to a TransformState object, which
       * can be used during SAX ContentHandler events to obtain
       * information about he state of the transformation. This
       * method will be called  before each startDocument event.
       *
       * @param ts A reference to a TransformState object
       */
      public void setTransformState(TransformStateSetter ts) {
          this.m_state = ts;
      }
  
      /**
       * Receives notification that an element starts, but attributes are not
       * fully known yet.
       *
       * @param uri the URI of the namespace of the element (optional)
       * @param localName the element name, but without prefix (optional)
       * @param qName the element name, with prefix, if any (required)
       *
       * @see org.apache.xml.serializer.ExtendedContentHandler#startElement(String, String, String)
       */
      public void startElement(String uri, String localName, String qName)
          throws SAXException {
              
          if (m_state != null) {
              m_state.resetState(getTransformer());
          }
  
      	// fire off the start element event
      	super.fireStartElem(qName);    	        
      }
  
      /**
       * An element starts, but attributes are not fully known yet.
       *
       * @param elementName the element name, with prefix (if any).
  
       * @see org.apache.xml.serializer.ExtendedContentHandler#startElement(String)
       */
      public void startElement(String qName) throws SAXException {
          if (m_state != null) {
              m_state.resetState(getTransformer());
          }        
      	// fire off the start element event
      	super.fireStartElem(qName);    	                
      }
      
      /**
       * This method gets the nodes value as a String and uses that String as if
       * it were an input character notification.
       * @param node the Node to serialize
       * @throws org.xml.sax.SAXException
       */    
      public void characters(org.w3c.dom.Node node)
          throws org.xml.sax.SAXException
      {
          // remember the current node
          if (m_state != null)
          {
              m_state.setCurrentNode(node);
          }
          
          // do what the stream serializers do
          super.characters(node);
         }    
  
      /**
       * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException)
       */
      public void fatalError(SAXParseException exc) throws SAXException {
          super.fatalError(exc);
          
          m_needToCallStartDocument = false;
          
          if (m_saxHandler instanceof ErrorHandler) {
              ((ErrorHandler)m_saxHandler).fatalError(exc);            
          }
      }
  
      /**
       * @see org.xml.sax.ErrorHandler#error(SAXParseException)
       */
      public void error(SAXParseException exc) throws SAXException {
          super.error(exc);
          
          if (m_saxHandler instanceof ErrorHandler)
              ((ErrorHandler)m_saxHandler).error(exc);        
          
      }
  
      /**
       * @see org.xml.sax.ErrorHandler#warning(SAXParseException)
       */
      public void warning(SAXParseException exc) throws SAXException {
          super.warning(exc);
          
          if (m_saxHandler instanceof ErrorHandler)
              ((ErrorHandler)m_saxHandler).warning(exc);        
      }
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ToStream.java
  
  Index: ToStream.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 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.xml.serializer;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.UnsupportedEncodingException;
  import java.io.Writer;
  import java.util.BitSet;
  import java.util.Hashtable;
  import java.util.Properties;
  import java.util.StringTokenizer;
  import java.util.Vector;
  
  import javax.xml.transform.OutputKeys;
  import javax.xml.transform.Transformer;
  
  import org.apache.xml.res.XMLErrorResources;
  import org.apache.xml.res.XMLMessages;
  import org.apache.xml.utils.BoolStack;
  import org.apache.xml.utils.FastStringBuffer;
  import org.apache.xml.utils.QName;
  import org.apache.xml.utils.SystemIDResolver;
  import org.apache.xml.utils.TreeWalker;
  import org.apache.xml.utils.WrappedRuntimeException;
  import org.w3c.dom.Node;
  import org.xml.sax.Attributes;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.SAXException;
  
  //import com.sun.media.sound.IESecurity;
  
  /**
   * This abstract class is a base class for other serializers (xml, html, text
   * ...) that write output to a stream.
   * @author minchau
   *
   */
  
  abstract public class ToStream extends SerializerBase
  {
  
      private static final String COMMENT_BEGIN = "<!--";
      private static final String COMMENT_END = "-->";
  
      /** Stack to keep track of disabling output escaping. */
      protected BoolStack m_disableOutputEscapingStates = new BoolStack();
  
      /**
       * Boolean that tells if we already tried to get the converter.
       */
      boolean m_triedToGetConverter = false;
      /**
       * Method reference to the sun.io.CharToByteConverter#canConvert method 
       * for this encoding.  Invalid if m_charToByteConverter is null.
       */
      java.lang.reflect.Method m_canConvertMeth;
  
      /**
       * Opaque reference to the sun.io.CharToByteConverter for this 
       * encoding.
       */
      Object m_charToByteConverter = null;
  
      /**
       * Stack to keep track of whether or not we need to
       * preserve whitespace.
       */
      protected BoolStack m_preserves = new BoolStack();
  
      /**
       * State flag to tell if preservation of whitespace
       * is important.
       */
      protected boolean m_ispreserve = false;
  
      /**
       * State flag that tells if the previous node processed
       * was text, so we can tell if we should preserve whitespace.
       */
      protected boolean m_isprevtext = false;
  
      /**
       * A stack of Boolean objects that tell if the given element
       * has children.
       */
      // protected BoolStack m_elemStack = new BoolStack();
  
      /**
       * Map that tells which XML characters should have special treatment, and it
       *  provides character to entity name lookup.
       */
      private static CharInfo m_xmlcharInfo =
          //      new CharInfo(CharInfo.XML_ENTITIES_RESOURCE);
      CharInfo.getCharInfo(CharInfo.XML_ENTITIES_RESOURCE);
  
      /**
       * The maximum character size before we have to resort
       * to escaping.
       */
      protected int m_maxCharacter = Encodings.getLastPrintable();
  
      /**
       * Use the system line seperator to write line breaks.
       */
      protected final char[] m_lineSep =
          System.getProperty("line.separator").toCharArray();
  
      /**
       * The length of the line seperator, since the write is done
       * one character at a time.
       */
      protected final int m_lineSepLen = m_lineSep.length;
  
      /**
       * Map that tells which characters should have special treatment, and it
       *  provides character to entity name lookup.
       */
      protected CharInfo m_charInfo;
  
      /** Table of user-specified char infos. */
      private static Hashtable m_charInfos = null;
  
      /** True if we control the buffer, and we should flush the output on endDocument. */
      boolean m_shouldFlush = true;
  
      //    protected OutputBuffer _buffer = null;
  
      /**
       * Add space before '/>' for XHTML.
       */
      protected boolean m_spaceBeforeClose = false;
  
      /**
       * Flag to signal that a newline should be added.
       */
      boolean m_startNewLine;
  
      /**
       * Tells if we're in an internal document type subset.
       */
      protected boolean m_inDoctype = false;
  
      /**
         * Flag to quickly tell if the encoding is UTF8.
         */
      boolean m_isUTF8 = false;
  
      /** The xsl:output properties. */
      protected Properties m_format;
  
      /**
       * remembers if we are in between the startCDATA() and endCDATA() callbacks
       */
      protected boolean m_cdataStartCalled = false;
  
      /**
       * Default constructor
       */
      public ToStream()
      {
      }
  
      /**
       * This helper method to writes out "]]>" when closing a CDATA section.
       *
       * @throws org.xml.sax.SAXException
       */
      protected void closeCDATA() throws org.xml.sax.SAXException
      {
          try
          {
              m_writer.write(CDATA_DELIMITER_CLOSE);
              // write out a CDATA section closing "]]>"
              m_cdataTagOpen = false; // Remember that we have done so.
          }
          catch (IOException e)
          {
              throw new SAXException(e);
          }
      }
  
      /**
       * Serializes the DOM node. Throws an exception only if an I/O
       * exception occured while serializing.
       *
       * @param elem The element to serialize
       *
       * @param node Node to serialize.
       * @throws IOException An I/O exception occured while serializing
       */
      public void serialize(Node node) throws IOException
      {
  
          try
          {
              TreeWalker walker =
                  new TreeWalker(this, new org.apache.xml.utils.DOM2Helper());
  
              walker.traverse(node);
          }
          catch (org.xml.sax.SAXException se)
          {
              throw new WrappedRuntimeException(se);
          }
      }
  
      /**
       * Return true if the character is the high member of a surrogate pair.
       *
       * NEEDSDOC @param c
       *
       * NEEDSDOC ($objectName$) @return
       */
      static final boolean isUTF16Surrogate(char c)
      {
          return (c & 0xFC00) == 0xD800;
      }
  
      /**
       * Taken from XSLTC 
       */
      private boolean m_escaping = true;
  
      /**
       * Flush the formatter's result stream.
       *
       * @throws org.xml.sax.SAXException
       */
      protected final void flushWriter() throws org.xml.sax.SAXException
      {
  
          if (null != m_writer)
          {
              try
              {
                  if (m_writer instanceof WriterToUTF8Buffered)
                  {
                      if (m_shouldFlush)
                           ((WriterToUTF8Buffered) m_writer).flush();
                      else
                           ((WriterToUTF8Buffered) m_writer).flushBuffer();
                  }
                  if (m_writer instanceof WriterToUTF8)
                  {
                      if (m_shouldFlush)
                          m_writer.flush();
                  }
                  else if (m_writer instanceof WriterToASCI)
                  {
                      if (m_shouldFlush)
                          m_writer.flush();
                  }
                  else
                  {
                      // Flush always. 
                      // Not a great thing if the writer was created 
                      // by this class, but don't have a choice.
                      m_writer.flush();
                  }
              }
              catch (IOException ioe)
              {
                  throw new org.xml.sax.SAXException(ioe);
              }
          }
      }
  
      /**
       * Get the output stream where the events will be serialized to.
       *
       * @return reference to the result stream, or null of only a writer was
       * set.
       */
      public OutputStream getOutputStream()
      {
  
          if (m_writer instanceof WriterToUTF8Buffered)
              return ((WriterToUTF8Buffered) m_writer).getOutputStream();
          if (m_writer instanceof WriterToUTF8)
              return ((WriterToUTF8) m_writer).getOutputStream();
          else if (m_writer instanceof WriterToASCI)
              return ((WriterToASCI) m_writer).getOutputStream();
          else
              return null;
      }
  
      // Implement DeclHandler
  
      /**
       *   Report an element type declaration.
       *  
       *   <p>The content model will consist of the string "EMPTY", the
       *   string "ANY", or a parenthesised group, optionally followed
       *   by an occurrence indicator.  The model will be normalized so
       *   that all whitespace is removed,and will include the enclosing
       *   parentheses.</p>
       *  
       *   @param name The element type name.
       *   @param model The content model as a normalized string.
       *   @exception SAXException The application may raise an exception.
       */
      public void elementDecl(String name, String model) throws SAXException
      {
          // Do not inline external DTD
          if (m_inExternalDTD)
              return;
          try
          {
  
              if (m_inDoctype)
              {
                  m_writer.write(" [");
                  m_writer.write(m_lineSep, 0, m_lineSepLen);
  
                  m_inDoctype = false;
              }
  
              m_writer.write("<!ELEMENT ");
              m_writer.write(name);
              m_writer.write(' ');
              m_writer.write(model);
              m_writer.write('>');
              m_writer.write(m_lineSep, 0, m_lineSepLen);
          }
          catch (IOException e)
          {
              throw new SAXException(e);
          }
  
      }
  
      /**
       * Report an internal entity declaration.
       *
       * <p>Only the effective (first) declaration for each entity
       * will be reported.</p>
       *
       * @param name The name of the entity.  If it is a parameter
       *        entity, the name will begin with '%'.
       * @param value The replacement text of the entity.
       * @exception SAXException The application may raise an exception.
       * @see #externalEntityDecl
       * @see org.xml.sax.DTDHandler#unparsedEntityDecl
       */
      public void internalEntityDecl(String name, String value)
          throws SAXException
      {
          // Do not inline external DTD
          if (m_inExternalDTD)
              return;
          try
          {
              if (m_inDoctype)
              {
                  m_writer.write(" [");
                  m_writer.write(m_lineSep, 0, m_lineSepLen);
  
                  m_inDoctype = false;
              }
  
              outputEntityDecl(name, value);
          }
          catch (IOException e)
          {
              throw new SAXException(e);
          }
  
      }
  
      /**
       * Output the doc type declaration.
       *
       * @param name non-null reference to document type name.
       * NEEDSDOC @param value
       *
       * @throws org.xml.sax.SAXException
       */
      void outputEntityDecl(String name, String value) throws IOException
      {
  
          m_writer.write("<!ENTITY ");
          m_writer.write(name);
          m_writer.write(" \"");
          m_writer.write(value);
          m_writer.write("\">");
          m_writer.write(m_lineSep, 0, m_lineSepLen);
      }
  
      /**
       * Output a system-dependent line break.
       *
       * @throws org.xml.sax.SAXException
       */
      protected final void outputLineSep() throws IOException
      {
  
          m_writer.write(m_lineSep, 0, m_lineSepLen);
      }
  
      /**
       * Specifies an output format for this serializer. It the
       * serializer has already been associated with an output format,
       * it will switch to the new format. This method should not be
       * called while the serializer is in the process of serializing
       * a document.
       *
       * @param format The output format to use
       */
      public void setOutputFormat(Properties format)
      {
  
          boolean shouldFlush = m_shouldFlush;
  
          init(m_writer, format, false, false);
  
          m_shouldFlush = shouldFlush;
      }
  
      /**
       * Initialize the serializer with the specified writer and output format.
       * Must be called before calling any of the serialize methods.
       *
       * @param writer The writer to use
       * @param format The output format
       * @param shouldFlush True if the writer should be flushed at EndDocument.
       */
      private synchronized void init(
          Writer writer,
          Properties format,
          boolean defaultProperties,
          boolean shouldFlush)
      {
  
          m_shouldFlush = shouldFlush;
  
          
          // if we are tracing events we need to trace what
          // characters are written to the output writer.
          if (m_tracer != null
           && !(writer instanceof SerializerTraceWriter)  )
              m_writer = new SerializerTraceWriter(writer, m_tracer);
          else
              m_writer = writer;        
          
  
          m_format = format;
          //        m_cdataSectionNames =
          //            OutputProperties.getQNameProperties(
          //                OutputKeys.CDATA_SECTION_ELEMENTS,
          //                format);
          setCdataSectionElements(OutputKeys.CDATA_SECTION_ELEMENTS, format);
  
          setIndentAmount(
              OutputPropertyUtils.getIntProperty(
                  OutputPropertiesFactory.S_KEY_INDENT_AMOUNT,
                  format));
          setIndent(
              OutputPropertyUtils.getBooleanProperty(OutputKeys.INDENT, format));
  
          boolean shouldNotWriteXMLHeader =
              OutputPropertyUtils.getBooleanProperty(
                  OutputKeys.OMIT_XML_DECLARATION,
                  format);
          setOmitXMLDeclaration(shouldNotWriteXMLHeader);
          setDoctypeSystem(format.getProperty(OutputKeys.DOCTYPE_SYSTEM));
          String doctypePublic = format.getProperty(OutputKeys.DOCTYPE_PUBLIC);
          setDoctypePublic(doctypePublic);
  
          // if standalone was explicitly specified
          if (format.get(OutputKeys.STANDALONE) != null)
          {
              String val = format.getProperty(OutputKeys.STANDALONE);
              if (defaultProperties)
                  setStandaloneInternal(val);
              else
                  setStandalone(val);
          }
  
          setMediaType(format.getProperty(OutputKeys.MEDIA_TYPE));
  
          if (null != doctypePublic)
          {
              if (doctypePublic.startsWith("-//W3C//DTD XHTML"))
                  m_spaceBeforeClose = true;
          }
  
          // initCharsMap();
          String encoding = getEncoding();
          if (null == encoding)
          {
              encoding =
                  Encodings.getMimeEncoding(
                      format.getProperty(OutputKeys.ENCODING));
              setEncoding(encoding);
          }
  
          m_isUTF8 = encoding.equals(Encodings.DEFAULT_MIME_ENCODING);
          m_maxCharacter = Encodings.getLastPrintable(encoding);
  
          // Access this only from the Hashtable level... we don't want to 
          // get default properties.
          String entitiesFileName =
              (String) format.get(OutputPropertiesFactory.S_KEY_ENTITIES);
  
          if (null != entitiesFileName)
          {
              m_charInfo = CharInfo.getCharInfo(entitiesFileName);
          }
  
      }
  
      /**
       * Initialize the serializer with the specified writer and output format.
       * Must be called before calling any of the serialize methods.
       *
       * @param writer The writer to use
       * @param format The output format
       */
      private synchronized void init(Writer writer, Properties format)
      {
          init(writer, format, false, false);
      }
      /**
       * Initialize the serializer with the specified output stream and output
       * format. Must be called before calling any of the serialize methods.
       *
       * @param output The output stream to use
       * @param format The output format
       * @param defaultProperties true if the properties are the default
       * properties
       * 
       * @throws UnsupportedEncodingException The encoding specified   in the
       * output format is not supported
       */
      protected synchronized void init(
          OutputStream output,
          Properties format,
          boolean defaultProperties)
          throws UnsupportedEncodingException
      {
  
          String encoding = getEncoding();
          if (encoding == null)
          {
              // if not already set then get it from the properties
              encoding =
                  Encodings.getMimeEncoding(
                      format.getProperty(OutputKeys.ENCODING));
              setEncoding(encoding);
          }
  
          if (encoding.equalsIgnoreCase("UTF-8"))
          {
              m_isUTF8 = true;
              //            if (output instanceof java.io.BufferedOutputStream)
              //            {
              //                init(new WriterToUTF8(output), format, defaultProperties, true);
              //            }
              //            else if (output instanceof java.io.FileOutputStream)
              //            {
              //                init(new WriterToUTF8Buffered(output), format, defaultProperties, true);
              //            }
              //            else
              //            {
              //                // Not sure what to do in this case.  I'm going to be conservative 
              //                // and not buffer.
              //                init(new WriterToUTF8(output), format, defaultProperties, true);
              //            }
              if (output instanceof java.io.BufferedOutputStream)
              {
                  init(new WriterToUTF8(output), format, defaultProperties, true);
              }
              else
              {
                  init(
                      new WriterToUTF8Buffered(output),
                      format,
                      defaultProperties,
                      true);
              }
  
          }
          else if (
              encoding.equals("WINDOWS-1250")
                  || encoding.equals("US-ASCII")
                  || encoding.equals("ASCII"))
          {
              init(new WriterToASCI(output), format, defaultProperties, true);
          }
          else
          {
              Writer osw;
  
              try
              {
                  osw = Encodings.getWriter(output, encoding);
              }
              catch (UnsupportedEncodingException uee)
              {
                  System.out.println(
                      "Warning: encoding \""
                          + encoding
                          + "\" not supported"
                          + ", using "
                          + Encodings.DEFAULT_MIME_ENCODING);
  
                  encoding = Encodings.DEFAULT_MIME_ENCODING;
                  setEncoding(encoding);
                  osw = Encodings.getWriter(output, encoding);
              }
  
              m_maxCharacter = Encodings.getLastPrintable(encoding);
  
              init(osw, format, defaultProperties, true);
          }
  
      }
  
      /**
       * Returns the output format for this serializer.
       *
       * @return The output format in use
       */
      public Properties getOutputFormat()
      {
          return m_format;
      }
  
      /**
       * Specifies a writer to which the document should be serialized.
       * This method should not be called while the serializer is in
       * the process of serializing a document.
       *
       * @param writer The output writer stream
       */
      public void setWriter(Writer writer)
      {        
          // if we are tracing events we need to trace what 
          // characters are written to the output writer.
          if (m_tracer != null
           && !(writer instanceof SerializerTraceWriter)  )
              m_writer = new SerializerTraceWriter(writer, m_tracer);
          else
              m_writer = writer;
      }
  
      /**
       * Specifies an output stream to which the document should be
       * serialized. This method should not be called while the
       * serializer is in the process of serializing a document.
       * <p>
       * The encoding specified in the output properties is used, or
       * if no encoding was specified, the default for the selected
       * output method.
       *
       * @param output The output stream
       */
      public void setOutputStream(OutputStream output)
      {
  
          try
          {
              Properties format;
              if (null == m_format)
                  format =
                      OutputPropertiesFactory.getDefaultMethodProperties(
                          Method.XML);
              else
                  format = m_format;
              init(output, format, true);
          }
          catch (UnsupportedEncodingException uee)
          {
  
              // Should have been warned in init, I guess...
          }
      }
  
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setEscaping(boolean)
       */
      public boolean setEscaping(boolean escape)
      {
          final boolean temp = m_escaping;
          m_escaping = escape;
          return temp;
  
      }
  
      /**
       * Resets the serializer. If this method returns true, the
       * serializer may be used for subsequent serialization of new
       * documents. It is possible to change the output format and
       * output stream prior to serializing, or to use the existing
       * output format and output stream.
       *
       * @return True if serializer has been reset and can be reused
       */
      public boolean reset()
      {
          m_needToCallStartDocument = true;
          
          return false;
      }
  
      /**
       * Might print a newline character and the indentation amount
       * of the current element.
       *
       * @throws org.xml.sax.SAXException if an error occurs during writing.
       */
      protected void indent() throws IOException
      {
  
          if (m_startNewLine)
              outputLineSep();
          /* For m_indentAmount > 0 this extra test might be slower
           * but Xalan's default value is 0, so this extra test
           * will run faster in that situation.
           */
          if (m_indentAmount > 0)
              printSpace(m_currentElemDepth * m_indentAmount);
  
      }
      /**
       * Prints <var>n</var> spaces.
       * @param pw        The character output stream to use.
       * @param n         Number of spaces to print.
       *
       * @throws org.xml.sax.SAXException if an error occurs when writing.
       */
      private void printSpace(int n) throws IOException
      {
  
          for (int i = 0; i < n; i++)
          {
              m_writer.write(' ');
          }
  
      }
  
      /**
       * Report an attribute type declaration.
       *
       * <p>Only the effective (first) declaration for an attribute will
       * be reported.  The type will be one of the strings "CDATA",
       * "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY",
       * "ENTITIES", or "NOTATION", or a parenthesized token group with
       * the separator "|" and all whitespace removed.</p>
       *
       * @param eName The name of the associated element.
       * @param aName The name of the attribute.
       * @param type A string representing the attribute type.
       * @param valueDefault A string representing the attribute default
       *        ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if
       *        none of these applies.
       * @param value A string representing the attribute's default value,
       *        or null if there is none.
       * @exception SAXException The application may raise an exception.
       */
      public void attributeDecl(
          String eName,
          String aName,
          String type,
          String valueDefault,
          String value)
          throws SAXException
      {
          // Do not inline external DTD
          if (m_inExternalDTD)
              return;
          try
          {
              if (m_inDoctype)
              {
                  m_writer.write(" [");
                  m_writer.write(m_lineSep, 0, m_lineSepLen);
  
                  m_inDoctype = false;
              }
  
              m_writer.write("<!ATTLIST ");
              m_writer.write(eName);
              m_writer.write(" ");
  
              m_writer.write(aName);
              m_writer.write(" ");
              m_writer.write(type);
              if (valueDefault != null)
              {
                  m_writer.write(" ");
                  m_writer.write(valueDefault);
              }
  
              //m_writer.write(" ");
              //m_writer.write(value);
              m_writer.write(">");
              m_writer.write(m_lineSep, 0, m_lineSepLen);
          }
          catch (IOException e)
          {
              throw new SAXException(e);
          }
      }
  
      /**
       * Get the character stream where the events will be serialized to.
       *
       * @return Reference to the result Writer, or null.
       */
      public Writer getWriter()
      {
          return m_writer;
      }
  
      /**
       * Report a parsed external entity declaration.
       *
       * <p>Only the effective (first) declaration for each entity
       * will be reported.</p>
       *
       * @param name The name of the entity.  If it is a parameter
       *        entity, the name will begin with '%'.
       * @param publicId The declared public identifier of the entity, or
       *        null if none was declared.
       * @param systemId The declared system identifier of the entity.
       * @exception SAXException The application may raise an exception.
       * @see #internalEntityDecl
       * @see org.xml.sax.DTDHandler#unparsedEntityDecl
       */
      public void externalEntityDecl(
          String name,
          String publicId,
          String systemId)
          throws SAXException
      {
      }
  
      /**
       * Tell if this character can be written without escaping.
       */
      protected boolean escapingNotNeeded(char ch)
      {
          if (ch < 127)
          {
              if (ch >= 0x20 || (0x0A == ch || 0x0D == ch || 0x09 == ch))
                  return true;
              else
                  return false;
          }
  
          if (null == m_charToByteConverter && false == m_triedToGetConverter)
          {
              m_triedToGetConverter = true;
              try
              {
                  m_charToByteConverter =
                      Encodings.getCharToByteConverter(getEncoding());
                  if (null != m_charToByteConverter)
                  {
                      Class argsTypes[] = new Class[1];
                      argsTypes[0] = Character.TYPE;
                      Class convClass = m_charToByteConverter.getClass();
                      m_canConvertMeth =
                          convClass.getMethod("canConvert", argsTypes);
                  }
              }
              catch (Exception e)
              {
                  // This is just an assert: no action at the moment.
                  System.err.println("Warning: " + e.getMessage());
              }
          }
          if (null != m_charToByteConverter)
          {
              try
              {
                  Object args[] = new Object[1];
                  args[0] = new Character(ch);
                  Boolean bool =
                      (Boolean) m_canConvertMeth.invoke(
                          m_charToByteConverter,
                          args);
                  return bool.booleanValue()
                      ? !Character.isISOControl(ch)
                      : false;
              }
              catch (java.lang.reflect.InvocationTargetException ite)
              {
                  // This is just an assert: no action at the moment.
                  System.err.println(
                      "Warning: InvocationTargetException in canConvert!");
              }
              catch (java.lang.IllegalAccessException iae)
              {
                  // This is just an assert: no action at the moment.
                  System.err.println(
                      "Warning: IllegalAccessException in canConvert!");
              }
          }
          // fallback!
          return (ch <= m_maxCharacter);
      }
  
      /**
       * Once a surrogate has been detected, write the pair as a single
       * character reference.
       *
       * @param c the first part of the surrogate.
       * @param ch Character array.
       * @param i position Where the surrogate was detected.
       * @param end The end index of the significant characters.
       * @return i+1.
       * @throws IOException
       * @throws org.xml.sax.SAXException if invalid UTF-16 surrogate detected.
       */
      protected int writeUTF16Surrogate(char c, char ch[], int i, int end)
          throws IOException
      {
  
          // UTF-16 surrogate
          int surrogateValue = getURF16SurrogateValue(c, ch, i, end);
  
          i++;
  
          m_writer.write('&');
          m_writer.write('#');
  
          // m_writer.write('x');
          m_writer.write(Integer.toString(surrogateValue));
          m_writer.write(';');
  
          return i;
      }
  
      /**
       * Once a surrogate has been detected, get the pair as a single integer
       * value.
       *
       * @param c the first part of the surrogate.
       * @param ch Character array.
       * @param i position Where the surrogate was detected.
       * @param end The end index of the significant characters.
       * @return i+1.
       * @throws org.xml.sax.SAXException if invalid UTF-16 surrogate detected.
       */
      int getURF16SurrogateValue(char c, char ch[], int i, int end)
          throws IOException
      {
  
          int next;
  
          if (i + 1 >= end)
          {
              throw new IOException(
                  XMLMessages.createXMLMessage(
                      XMLErrorResources.ER_INVALID_UTF16_SURROGATE,
                      new Object[] { Integer.toHexString((int) c)}));
              //"Invalid UTF-16 surrogate detected: "
  
              //+Integer.toHexString((int)c)+ " ?");
          }
          else
          {
              next = ch[++i];
  
              if (!(0xdc00 <= next && next < 0xe000))
                  throw new IOException(
                      XMLMessages.createXMLMessage(
                          XMLErrorResources.ER_INVALID_UTF16_SURROGATE,
                          new Object[] {
                              Integer.toHexString((int) c)
                                  + " "
                                  + Integer.toHexString(next)}));
              //"Invalid UTF-16 surrogate detected: "
  
              //+Integer.toHexString((int)c)+" "+Integer.toHexString(next));
              next = ((c - 0xd800) << 10) + next - 0xdc00 + 0x00010000;
          }
  
          return next;
      }
  
      /**
       * Handle one of the default entities, return false if it
       * is not a default entity.
       *
       * @param ch character to be escaped.
       * @param i index into character array.
       * @param chars non-null reference to character array.
       * @param len length of chars.
       * @param escLF true if the linefeed should be escaped.
       *
       * @return i+1 if the character was written, else i.
       *
       * @throws java.io.IOException
       */
      protected int accumDefaultEntity(
          java.io.Writer writer,
          char ch,
          int i,
          char[] chars,
          int len,
          boolean escLF)
          throws IOException
      {
  
          if (!escLF && CharInfo.S_LINEFEED == ch)
          {
              writer.write(m_lineSep, 0, m_lineSepLen);
          }
          else
          {
              if (m_charInfo.isSpecial(ch))
              {
                  String entityRef = m_charInfo.getEntityNameForChar(ch);
  
                  if (null != entityRef)
                  {
                      writer.write('&');
                      writer.write(entityRef);
                      writer.write(';');
                  }
                  else
                      return i;
              }
              else
                  return i;
          }
  
          return i + 1;
  
      }
      /**
       * Normalize the characters, but don't escape.
       *
       * @param ch The characters from the XML document.
       * @param start The start position in the array.
       * @param length The number of characters to read from the array.
       * @param isCData true if a CDATA block should be built around the characters.
       *
       * @throws IOException
       * @throws org.xml.sax.SAXException
       */
      void writeNormalizedChars(
          char ch[],
          int start,
          int length,
          boolean isCData)
          throws IOException, org.xml.sax.SAXException
      {
  
          int end = start + length;
  
          for (int i = start; i < end; i++)
          {
              char c = ch[i];
  
              if (CharInfo.S_LINEFEED == c)
              {
                  m_writer.write(m_lineSep, 0, m_lineSepLen);
              }
              else if (isCData && (!escapingNotNeeded(c)))
              {
                  //                if (i != 0)
                  if (m_cdataTagOpen)
                      closeCDATA();
  
                  // This needs to go into a function... 
                  if (isUTF16Surrogate(c))
                  {
                      i = writeUTF16Surrogate(c, ch, i, end);
                  }
                  else
                  {
                      m_writer.write("&#");
  
                      String intStr = Integer.toString((int) c);
  
                      m_writer.write(intStr);
                      m_writer.write(';');
                  }
  
                  //                if ((i != 0) && (i < (end - 1)))
                  //                if (!m_cdataTagOpen && (i < (end - 1)))
                  //                {
                  //                    m_writer.write(CDATA_DELIMITER_OPEN);
                  //                    m_cdataTagOpen = true;
                  //                }
              }
              else if (
                  isCData
                      && ((i < (end - 2))
                          && (']' == c)
                          && (']' == ch[i + 1])
                          && ('>' == ch[i + 2])))
              {
                  m_writer.write(CDATA_CONTINUE);
  
                  i += 2;
              }
              else
              {
                  if (escapingNotNeeded(c))
                  {
                      if (isCData && !m_cdataTagOpen)
                      {
                          m_writer.write(CDATA_DELIMITER_OPEN);
                          m_cdataTagOpen = true;
                      }
                      m_writer.write(c);
                  }
  
                  // This needs to go into a function... 
                  else if (isUTF16Surrogate(c))
                  {
                      if (m_cdataTagOpen)
                          closeCDATA();
                      i = writeUTF16Surrogate(c, ch, i, end);
                  }
                  else
                  {
                      if (m_cdataTagOpen)
                          closeCDATA();
                      m_writer.write("&#");
  
                      String intStr = Integer.toString((int) c);
  
                      m_writer.write(intStr);
                      m_writer.write(';');
                  }
              }
          }
  
      }
  
      /**
       * Ends an un-escaping section.
       *
       * @see #startNonEscaping
       *
       * @throws org.xml.sax.SAXException
       */
      public void endNonEscaping() throws org.xml.sax.SAXException
      {
          m_disableOutputEscapingStates.pop();
      }
  
      /**
       * Starts an un-escaping section. All characters printed within an un-
       * escaping section are printed as is, without escaping special characters
       * into entity references. Only XML and HTML serializers need to support
       * this method.
       * <p> The contents of the un-escaping section will be delivered through the
       * regular <tt>characters</tt> event.
       *
       * @throws org.xml.sax.SAXException
       */
      public void startNonEscaping() throws org.xml.sax.SAXException
      {
          m_disableOutputEscapingStates.push(true);
      }
  
      /**
       * Receive notification of cdata.
       *
       * <p>The Parser will call this method to report each chunk of
       * character data.  SAX parsers may return all contiguous character
       * data in a single chunk, or they may split it into several
       * chunks; however, all of the characters in any single event
       * must come from the same external entity, so that the Locator
       * provides useful information.</p>
       *
       * <p>The application must not attempt to read from the array
       * outside of the specified range.</p>
       *
       * <p>Note that some parsers will report whitespace using the
       * ignorableWhitespace() method rather than this one (validating
       * parsers must do so).</p>
       *
       * @param ch The characters from the XML document.
       * @param start The start position in the array.
       * @param length The number of characters to read from the array.
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       * @see #ignorableWhitespace
       * @see org.xml.sax.Locator
       *
       * @throws org.xml.sax.SAXException
       */
      protected void cdata(char ch[], int start, final int length)
          throws org.xml.sax.SAXException
      {
  
          try
          {
              final int old_start = start;
              if (m_startTagOpen)
              {
                  closeStartTag();
                  m_startTagOpen = false;
              }
              m_ispreserve = true;
  
              if (shouldIndent())
                  indent();
  
              boolean writeCDataBrackets =
                  (((length >= 1) && escapingNotNeeded(ch[start])));
  
              /* Write out the CDATA opening delimiter only if
               * we are supposed to, and if we are not already in
               * the middle of a CDATA section  
               */
              if (writeCDataBrackets && !m_cdataTagOpen)
              {
                  m_writer.write(CDATA_DELIMITER_OPEN);
                  m_cdataTagOpen = true;
              }
  
              // m_writer.write(ch, start, length);
              if (isEscapingDisabled())
              {
                  charactersRaw(ch, start, length);
              }
              else
                  writeNormalizedChars(ch, start, length, true);
  
              /* used to always write out CDATA closing delimiter here,
               * but now we delay, so that we can merge CDATA sections on output.    
               * need to write closing delimiter later
               */
              if (writeCDataBrackets)
              {
                  /* if the CDATA section ends with ] don't leave it open
                   * as there is a chance that an adjacent CDATA sections
                   * starts with ]>.  
                   * We don't want to merge ]] with > , or ] with ]> 
                   */
                  if (ch[start + length - 1] == ']')
                      closeCDATA();
              }
  
              // time to fire off CDATA event
              super.fireCDATAEvent(ch, old_start, length);
          }
          catch (IOException ioe)
          {
              throw new org.xml.sax.SAXException(
                  XMLMessages.createXMLMessage(
                      XMLErrorResources.ER_OIERROR,
                      null),
                  ioe);
              //"IO error", ioe);
          }
      }
  
      /**
       * Tell if the character escaping should be disabled for the current state.
       *
       * @return true if the character escaping should be disabled.
       */
      private boolean isEscapingDisabled()
      {
          return m_disableOutputEscapingStates.peekOrFalse();
      }
  
      /**
       * If available, when the disable-output-escaping attribute is used,
       * output raw text without escaping.
       *
       * @param ch The characters from the XML document.
       * @param start The start position in the array.
       * @param length The number of characters to read from the array.
       *
       * @throws org.xml.sax.SAXException
       */
      protected void charactersRaw(char ch[], int start, int length)
          throws org.xml.sax.SAXException
      {
  
          if (m_inEntityRef)
              return;
          try
          {
              if (m_startTagOpen)
              {
                  closeStartTag();
                  m_startTagOpen = false;
              }
  
              m_ispreserve = true;
  
              m_writer.write(ch, start, length);
          }
          catch (IOException e)
          {
              throw new SAXException(e);
          }
  
      }
  
      /**
       * Receive notification of character data.
       *
       * <p>The Parser will call this method to report each chunk of
       * character data.  SAX parsers may return all contiguous character
       * data in a single chunk, or they may split it into several
       * chunks; however, all of the characters in any single event
       * must come from the same external entity, so that the Locator
       * provides useful information.</p>
       *
       * <p>The application must not attempt to read from the array
       * outside of the specified range.</p>
       *
       * <p>Note that some parsers will report whitespace using the
       * ignorableWhitespace() method rather than this one (validating
       * parsers must do so).</p>
       *
       * @param chars The characters from the XML document.
       * @param start The start position in the array.
       * @param length The number of characters to read from the array.
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       * @see #ignorableWhitespace
       * @see org.xml.sax.Locator
       *
       * @throws org.xml.sax.SAXException
       */
      public void characters(char chars[], int start, int length)
          throws org.xml.sax.SAXException
      {
          if (0 == length)
          {
              // Even though the character string is empty, but it is still a character event
              // time to fire off characters generation event
              super.fireCharEvent(chars, start, length);
              return;
          }
  
          if (m_startTagOpen)
          {
              closeStartTag();
              m_startTagOpen = false;
          }
          else if (m_needToCallStartDocument)
          {
              startDocumentInternal();
          }
  
          if (m_cdataStartCalled || m_cdataSectionStates.peekOrFalse())
          {
              /* either due to startCDATA() being called or due to 
               * cdata-section-elements atribute, we need this as cdata
               */
              cdata(chars, start, length);
  
              return;
          }
  
          if (m_cdataTagOpen)
              closeCDATA();
          // the check with _escaping is a bit of a hack for XLSTC
  
          if (m_disableOutputEscapingStates.peekOrFalse() || (!m_escaping))
          {
              charactersRaw(chars, start, length);
  
              // time to fire off characters generation event
              super.fireCharEvent(chars, start, length);
  
              return;
          }
  
          if (m_startTagOpen)
              closeStartTag();
  
          int startClean = start;
          int lengthClean = 0;
  
          // int pos = 0;
          int end = start + length;
          boolean checkWhite = true;
          final int maxCharacter = m_maxCharacter;
          final BitSet specialsMap = m_charInfo.m_specialsMap;
          try
          {
              for (int i = start; i < end; i++)
              {
                  char ch = chars[i];
  
                  if (checkWhite
                      && ((ch > 0x20)
                          || !((ch == 0x20)
                              || (ch == 0x09)
                              || (ch == 0xD)
                              || (ch == 0xA))))
                  {
                      m_ispreserve = true;
                      checkWhite = false;
                  }
  
                  // The first if(...) has the most common part of escapingNotNeeded()
                  // inlined to save the call.  If the expression is false it will
                  // fall back to the next else if(...) which does the real thing
                  // with esacapingNotNeeded()
                  if ((((ch < 127)
                      && (0x20 <= ch || (0x0A == ch || 0x0D == ch || 0x09 == ch)))
                      && (!specialsMap.get(ch)))
                      || ('"' == ch))
                  {
                      lengthClean++;
                  }
                  else if (
                      (escapingNotNeeded(ch) && (!specialsMap.get(ch)))
                          || ('"' == ch))
                  {
                      lengthClean++;
                  }
                  else
                  {
                      if (lengthClean > 0)
                      {
                          m_writer.write(chars, startClean, lengthClean);
  
                          lengthClean = 0;
                      }
  
                      if (CharInfo.S_LINEFEED == ch)
                      {
                          m_writer.write(m_lineSep, 0, m_lineSepLen);
  
                          startClean = i + 1;
                      }
                      else
                      {
                          startClean =
                              accumDefaultEscape(
                                  m_writer,
                                  ch,
                                  i,
                                  chars,
                                  end,
                                  false);
                          i = startClean - 1;
                      }
                  }
              }
  
              if (lengthClean > 0)
              {
                  m_writer.write(chars, startClean, lengthClean);
              }
  
              m_isprevtext = true;
          }
          catch (IOException e)
          {
              throw new SAXException(e);
          }
  
          // time to fire off characters generation event
          super.fireCharEvent(chars, start, length);
      }
  
      /**
       * Receive notification of character data.
       *
       * @param s The string of characters to process.
       *
       * @throws org.xml.sax.SAXException
       */
      public void characters(String s) throws org.xml.sax.SAXException
      {
          characters(s.toCharArray(), 0, s.length());
      }
  
      /**
       * Escape and m_writer.write a character.
       *
       * @param ch character to be escaped.
       * @param i index into character array.
       * @param chars non-null reference to character array.
       * @param len length of chars.
       * @param escLF true if the linefeed should be escaped.
       *
       * @return i+1 if the character was written, else i.
       *
       * @throws org.xml.sax.SAXException
       */
      protected int accumDefaultEscape(
          Writer writer,
          char ch,
          int i,
          char[] chars,
          int len,
          boolean escLF)
          throws IOException
      {
  
          int pos = accumDefaultEntity(writer, ch, i, chars, len, escLF);
  
          if (i == pos)
          {
              pos++;
  
              if (0xd800 <= ch && ch < 0xdc00)
              {
  
                  // UTF-16 surrogate
                  int next;
  
                  if (i + 1 >= len)
                  {
                      throw new IOException(
                          XMLMessages.createXMLMessage(
                              XMLErrorResources.ER_INVALID_UTF16_SURROGATE,
                              new Object[] { Integer.toHexString(ch)}));
                      //"Invalid UTF-16 surrogate detected: "
  
                      //+Integer.toHexString(ch)+ " ?");
                  }
                  else
                  {
                      next = chars[++i];
  
                      if (!(0xdc00 <= next && next < 0xe000))
                          throw new IOException(
                              XMLMessages.createXMLMessage(
                                  XMLErrorResources
                                      .ER_INVALID_UTF16_SURROGATE,
                                  new Object[] {
                                      Integer.toHexString(ch)
                                          + " "
                                          + Integer.toHexString(next)}));
                      //"Invalid UTF-16 surrogate detected: "
  
                      //+Integer.toHexString(ch)+" "+Integer.toHexString(next));
                      next = ((ch - 0xd800) << 10) + next - 0xdc00 + 0x00010000;
                  }
  
                  writer.write("&#");
                  writer.write(Integer.toString(next));
                  writer.write(";");
  
                  /*} else if (null != ctbc && !ctbc.canConvert(ch)) {
                  sb.append("&#x");
                  sb.append(Integer.toString((int)ch, 16));
                  sb.append(";");*/
              }
              else
              {
                  if (!escapingNotNeeded(ch) || (m_charInfo.isSpecial(ch)))
                  {
                      writer.write("&#");
                      writer.write(Integer.toString(ch));
                      writer.write(";");
                  }
                  else
                  {
                      writer.write(ch);
                  }
              }
  
          }
          return pos;
      }
  
      /**
       * Receive notification of the beginning of an element, although this is a
       * SAX method additional namespace or attribute information can occur before
       * or after this call, that is associated with this element.
       *
       *
       * @param namespaceURI The Namespace URI, or the empty string if the
       *        element has no Namespace URI or if Namespace
       *        processing is not being performed.
       * @param localName The local name (without prefix), or the
       *        empty string if Namespace processing is not being
       *        performed.
       * @param name The element type name.
       * @param atts The attributes attached to the element, if any.
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       * @see org.xml.sax.ContentHandler#startElement
       * @see org.xml.sax.ContentHandler#endElement
       * @see org.xml.sax.AttributeList
       *
       * @throws org.xml.sax.SAXException
       */
      public void startElement(
          String namespaceURI,
          String localName,
          String name,
          Attributes atts)
          throws org.xml.sax.SAXException
      {
          if (m_inEntityRef)
              return;
  
          if (m_needToCallStartDocument)
          {
              startDocumentInternal();
              m_needToCallStartDocument = false;
          }
          else if (m_cdataTagOpen)
              closeCDATA();
          try
          {
              if ((true == m_needToOutputDocTypeDecl)
                  && (null != getDoctypeSystem()))
              {
                  outputDocTypeDecl(name, true);
              }
  
              m_needToOutputDocTypeDecl = false;
  
              /* before we over-write the current elementLocalName etc.
               * lets close out the old one (if we still need to)
               */
              if (m_startTagOpen)
              {
                  closeStartTag();
                  m_startTagOpen = false;
              }
  
              if (namespaceURI != null)
                  ensurePrefixIsDeclared(namespaceURI, name);
  
              // remember for later
              m_elementLocalName = localName;
              m_elementURI = namespaceURI;
              m_elementName = name;
  
              m_ispreserve = false;
  
              if (shouldIndent() && m_startNewLine)
              {
                  indent();
              }
  
              m_startNewLine = true;
  
              m_writer.write('<');
              m_writer.write(name);
          }
          catch (IOException e)
          {
              throw new SAXException(e);
          }
  
          // process the attributes now, because after this SAX call they might be gone
          if (atts != null)
              addAttributes(atts);
  
          // mark that the closing '>' of the starting tag is not yet written out
          m_startTagOpen = true;
          m_currentElemDepth++; // current element is one element deeper
          m_isprevtext = false;
      }
  
      /**
        * Receive notification of the beginning of an element, additional
        * namespace or attribute information can occur before or after this call,
        * that is associated with this element.
        *
        *
        * @param namespaceURI The Namespace URI, or the empty string if the
        *        element has no Namespace URI or if Namespace
        *        processing is not being performed.
        * @param localName The local name (without prefix), or the
        *        empty string if Namespace processing is not being
        *        performed.
        * @param name The element type name.
        * @throws org.xml.sax.SAXException Any SAX exception, possibly
        *            wrapping another exception.
        * @see org.xml.sax.ContentHandler#startElement
        * @see org.xml.sax.ContentHandler#endElement
        * @see org.xml.sax.AttributeList
        *
        * @throws org.xml.sax.SAXException
        */
      public void startElement(
          String elementNamespaceURI,
          String elementLocalName,
          String elementName)
          throws SAXException
      {
          startElement(elementNamespaceURI, elementLocalName, elementName, null);
      }
  
      public void startElement(String elementName) throws SAXException
      {
          startElement(null, null, elementName, null);
      }
  
      /**
       * Output the doc type declaration.
       *
       * @param name non-null reference to document type name.
       * NEEDSDOC @param closeDecl
       *
       * @throws java.io.IOException
       */
      void outputDocTypeDecl(String name, boolean closeDecl) throws SAXException
      {
          if (m_cdataTagOpen)
              closeCDATA();
          try
          {
              m_writer.write("<!DOCTYPE ");
              m_writer.write(name);
  
              String doctypePublic = getDoctypePublic();
              if (null != doctypePublic)
              {
                  m_writer.write(" PUBLIC \"");
                  m_writer.write(doctypePublic);
                  m_writer.write('\"');
              }
  
              String doctypeSystem = getDoctypeSystem();
              if (null != doctypeSystem)
              {
                  if (null == doctypePublic)
                      m_writer.write(" SYSTEM \"");
                  else
                      m_writer.write(" \"");
  
                  m_writer.write(doctypeSystem);
  
                  if (closeDecl)
                  {
                      m_writer.write("\">");
                      m_writer.write(m_lineSep, 0, m_lineSepLen);
                      closeDecl = false; // done closing
                  }
                  else
                      m_writer.write('\"');
              }
              boolean dothis = false;
              if (dothis)
              {
                  // at one point this code seemed right,
                  // but not anymore - bjm
                  if (closeDecl)
                  {
                      m_writer.write(">");
                      m_writer.write(m_lineSep, 0, m_lineSepLen);
                  }
              }
          }
          catch (IOException e)
          {
              throw new SAXException(e);
          }
      }
  
      /**
       * Process the colleced attributes from SAX- like calls for an element from
       * calls to addattibute(String name, String value)
       * 
       *
       * @throws org.xml.sax.SAXException
       */
      public void processAttributes() throws IOException, SAXException
      {
  
          // finish processing attributes, time to fire off the start element event
          super.fireStartElem(m_elementName);
  
          int nAttrs = 0;
          // if passed real SAX attributes, then process only them
  
          if ((nAttrs = m_attributes.getLength()) > 0)
          {
              /* real SAX attributes are not passed in, so process the 
               * attributes that were collected after the startElement call.
               * _attribVector is a "cheap" list for Stream serializer output
               * accumulated over a series of calls to attribute(name,value)
               */
  
              String encoding = getEncoding();
              for (int i = 0; i < nAttrs; i++)
              {
                  // elementAt is JDK 1.1.8
                  final String name = m_attributes.getQName(i);
                  final String value = m_attributes.getValue(i);
                  m_writer.write(' ');
                  m_writer.write(name);
                  m_writer.write("=\"");
                  writeAttrString(m_writer, value, encoding);
                  m_writer.write('\"');
              }
  
              /* The attributes are now processed so clear them out
               * so that they don't accumulate from element to element.
               * .removeAllElements() is used as it is from JDK 1.1.8
               */
              m_attributes.clear();
  
          }
      }
  
      /**
       * Returns the specified <var>string</var> after substituting <VAR>specials</VAR>,
       * and UTF-16 surrogates for chracter references <CODE>&amp;#xnn</CODE>.
       *
       * @param   string      String to convert to XML format.
       * @param   encoding    CURRENTLY NOT IMPLEMENTED.
       *
       * @throws java.io.IOException
       */
      public void writeAttrString(
          Writer writer,
          String string,
          String encoding)
          throws IOException
      {
  
          final char[] stringChars = string.toCharArray();
          final int len = stringChars.length;
          for (int i = 0; i < len; i++)
          {
              char ch = stringChars[i];
              if (escapingNotNeeded(ch) && (!m_charInfo.isSpecial(ch)))
              {
                  writer.write(ch);
              }
              else
              { // I guess the parser doesn't normalize cr/lf in attributes. -sb
                  if ((CharInfo.S_CARRIAGERETURN == ch)
                      && ((i + 1) < len)
                      && (CharInfo.S_LINEFEED == stringChars[i + 1]))
                  {
                      i++;
                      ch = CharInfo.S_LINEFEED;
                  }
  
                  accumDefaultEscape(writer, ch, i, stringChars, len, true);
              }
          }
  
      }
  
      /**
       * Receive notification of the end of an element.
       *
       *
       * @param namespaceURI The Namespace URI, or the empty string if the
       *        element has no Namespace URI or if Namespace
       *        processing is not being performed.
       * @param localName The local name (without prefix), or the
       *        empty string if Namespace processing is not being
       *        performed.
       * @param name The element type name
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       *
       * @throws org.xml.sax.SAXException
       */
      public void endElement(String namespaceURI, String localName, String name)
          throws org.xml.sax.SAXException
      {
          if (m_inEntityRef)
              return;
  
          // namespaces declared at the current depth are no longer valid
          // so get rid of them    
          m_prefixMap.popNamespaces(m_currentElemDepth);
  
          // this element is done, so the new current element is one element less deep    
          m_currentElemDepth--;
  
          try
          {
              if (m_startTagOpen)
              {
                  /* The start tag is still open and we have hit
                   * endElement, so close it down
                   */
                  processAttributes();
                  if (m_spaceBeforeClose)
                      m_writer.write(" />");
                  else
                      m_writer.write("/>");
                  /* don't need to pop cdataSectionState because
                   * this element ended so quickly that we didn't get
                   * to push the state.
                   */
  
              }
              else
              {
                  if (m_cdataTagOpen)
                      closeCDATA();
  
                  if (shouldIndent())
                      indent();
                  m_writer.write('<');
                  m_writer.write('/');
                  m_writer.write(name);
                  m_writer.write('>');
                  m_cdataSectionStates.pop();
              }
          }
          catch (IOException e)
          {
              throw new SAXException(e);
          }
  
          if (!m_startTagOpen)
          {
              m_ispreserve = m_preserves.isEmpty() ? false : m_preserves.pop();
          }
  
          m_isprevtext = false;
          m_startTagOpen = false;
  
          // m_disableOutputEscapingStates.pop();
  
          // fire off the end element event
          super.fireEndElem(name);
      }
  
      /**
       * Receive notification of the end of an element.
       * @param name The element type name
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *     wrapping another exception.
       */
      public void endElement(String name) throws org.xml.sax.SAXException
      {
          endElement(null, null, name);
      }
  
      /**
       * Begin the scope of a prefix-URI Namespace mapping
       * just before another element is about to start.
       * This call will close any open tags so that the prefix mapping
       * will not apply to the current element, but the up comming child.
       * 
       * @see org.xml.sax.ContentHandler#startPrefixMapping
       * 
       * @param prefix The Namespace prefix being declared.
       * @param uri The Namespace URI the prefix is mapped to.
       * 
       * @throws org.xml.sax.SAXException The client may throw
       *            an exception during processing.
       * 
       */
      public void startPrefixMapping(String prefix, String uri)
          throws org.xml.sax.SAXException
      {
          // the "true" causes the flush of any open tags
          startPrefixMapping(prefix, uri, true);
      }
  
      /**
       * Handle a prefix/uri mapping, which is associated with a startElement()
       * that is soon to follow. Need to close any open start tag to make
       * sure than any name space attributes due to this event are associated wih
       * the up comming element, not the current one.
       * @see org.xml.sax.ExtendedContentHandler#startPrefixMapping
       *
       * @param prefix The Namespace prefix being declared.
       * @param uri The Namespace URI the prefix is mapped to.
       * @param shouldFlush true if any open tags need to be closed first, this
       * will impact which element the mapping applies to (open parent, or its up
       * comming child)
       * @return returns true if the call made a change to the current 
       * namespace information, false if it did not change anything, e.g. if the
       * prefix/namespace mapping was already in scope from before.
       * 
       * @throws org.xml.sax.SAXException The client may throw
       *            an exception during processing.
       *
       *
       */
      public boolean startPrefixMapping(
          String prefix,
          String uri,
          boolean shouldFlush)
          throws org.xml.sax.SAXException
      {
  
          /* Remember the mapping, and at what depth it was declared
           * This is one greater than the current depth because these
           * mappings will apply to the next depth. This is in
           * consideration that startElement() will soon be called
           */
  
          boolean pushed;
          int pushDepth;
          if (shouldFlush)
          {
              flushPending();
              // the prefix mapping applies to the child element (one deeper)
              pushDepth = m_currentElemDepth + 1;
          }
          else
          {
              // the prefix mapping applies to the current element
              pushDepth = m_currentElemDepth;
          }
          pushed = m_prefixMap.pushNamespace(prefix, uri, pushDepth);
  
          if (pushed)
          {
              /* bjm: don't know if we really needto do this. The
               * callers of this object should have injected both
               * startPrefixMapping and the attributes.  We are 
               * just covering our butt here.
               */
              String name;
              if (EMPTYSTRING.equals(prefix))
              {
                  name = "xmlns";
                  addAttributeAlways(XMLNS_URI, prefix, name, "CDATA", uri);
              }
              else
              {
                  if (!EMPTYSTRING.equals(uri))
                      // hack for XSLTC attribset16 test
                  { // that maps ns1 prefix to "" URI
                      name = "xmlns:" + prefix;
  
                      /* for something like xmlns:abc="w3.pretend.org"
                       *  the      uri is the value, that is why we pass it in the
                       * value, or 5th slot of addAttributeAlways()
                       */
                      addAttributeAlways(XMLNS_URI, prefix, name, "CDATA", uri);
                  }
              }
          }
          return pushed;
      }
  
      /**
       * Receive notification of an XML comment anywhere in the document. This
       * callback will be used for comments inside or outside the document
       * element, including comments in the external DTD subset (if read).
       * @param ch An array holding the characters in the comment.
       * @param start The starting position in the array.
       * @param length The number of characters to use from the array.
       * @throws org.xml.sax.SAXException The application may raise an exception.
       */
      public void comment(char ch[], int start, int length)
          throws org.xml.sax.SAXException
      {
  
          int start_old = start;
          if (m_inEntityRef)
              return;
          if (m_startTagOpen)
          {
              closeStartTag();
              m_startTagOpen = false;
          }
          else if (m_needToCallStartDocument)
          {
              startDocumentInternal();
              m_needToCallStartDocument = false;
          }
  
          try
          {
              if (shouldIndent())
                  indent();
  
              final int limit = start + length;
              boolean wasDash = false;
              if (m_cdataTagOpen)
                  closeCDATA();
              m_writer.write(COMMENT_BEGIN);
              // Detect occurrences of two consecutive dashes, handle as necessary.
              for (int i = start; i < limit; i++)
              {
                  if (wasDash && ch[i] == '-')
                  {
                      m_writer.write(ch, start, i - start);
                      m_writer.write(" -");
                      start = i + 1;
                  }
                  wasDash = (ch[i] == '-');
              }
  
              // if we have some chars in the comment
              if (length > 0)
              {
                  // Output the remaining characters (if any)
                  final int remainingChars = (limit - start);
                  if (remainingChars > 0)
                      m_writer.write(ch, start, remainingChars);
                  // Protect comment end from a single trailing dash
                  if (ch[limit - 1] == '-')
                      m_writer.write(' ');
              }
              m_writer.write(COMMENT_END);
          }
          catch (IOException e)
          {
              throw new SAXException(e);
          }
  
          m_startNewLine = true;
          // time to generate comment event
          super.fireCommentEvent(ch, start_old,length);
      }
  
      /**
       * Report the end of a CDATA section.
       * @throws org.xml.sax.SAXException The application may raise an exception.
       *
       *  @see  #startCDATA
       */
      public void endCDATA() throws org.xml.sax.SAXException
      {
          if (m_cdataTagOpen)
              closeCDATA();
          m_cdataStartCalled = false;
      }
  
      /**
       * Report the end of DTD declarations.
       * @throws org.xml.sax.SAXException The application may raise an exception.
       * @see #startDTD
       */
      public void endDTD() throws org.xml.sax.SAXException
      {
          try
          {
              if (m_needToOutputDocTypeDecl)
              {
                  outputDocTypeDecl(m_elementName, false);
                  m_needToOutputDocTypeDecl = false;
              }
              if (!m_inDoctype)
                  m_writer.write("]>");
              else
              {
                  m_writer.write('>');
              }
  
              m_writer.write(m_lineSep, 0, m_lineSepLen);
          }
          catch (IOException e)
          {
              throw new SAXException(e);
          }
  
      }
  
      /**
       * End the scope of a prefix-URI Namespace mapping.
       * @see org.xml.sax.ContentHandler#endPrefixMapping
       * 
       * @param prefix The prefix that was being mapping.
       * @throws org.xml.sax.SAXException The client may throw
       *            an exception during processing.
       */
      public void endPrefixMapping(String prefix) throws org.xml.sax.SAXException
      { // do nothing
      }
  
      /**
       * Receive notification of ignorable whitespace in element content.
       * 
       * Not sure how to get this invoked quite yet.
       * 
       * @param ch The characters from the XML document.
       * @param start The start position in the array.
       * @param length The number of characters to read from the array.
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       * @see #characters
       * 
       * @throws org.xml.sax.SAXException
       */
      public void ignorableWhitespace(char ch[], int start, int length)
          throws org.xml.sax.SAXException
      {
  
          if (0 == length)
              return;
          characters(ch, start, length);
      }
  
      /**
       * Receive notification of a skipped entity.
       * @see org.xml.sax.ContentHandler#skippedEntity
       * 
       * @param name The name of the skipped entity.  If it is a
       *       parameter                   entity, the name will begin with '%',
       * and if it is the external DTD subset, it will be the string
       * "[dtd]".
       * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping
       * another exception.
       */
      public void skippedEntity(String name) throws org.xml.sax.SAXException
      { // TODO: Should handle
      }
  
      /**
       * Report the start of a CDATA section.
       * 
       * @throws org.xml.sax.SAXException The application may raise an exception.
       * @see #endCDATA
       */
      public void startCDATA() throws org.xml.sax.SAXException
      {
          m_cdataStartCalled = true;
      }
  
      /**
       * Report the beginning of an entity.
       * 
       * The start and end of the document entity are not reported.
       * The start and end of the external DTD subset are reported
       * using the pseudo-name "[dtd]".  All other events must be
       * properly nested within start/end entity events.
       * 
       * @param name The name of the entity.  If it is a parameter
       *        entity, the name will begin with '%'.
       * @throws org.xml.sax.SAXException The application may raise an exception.
       * @see #endEntity
       * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
       * @see org.xml.sax.ext.DeclHandler#externalEntityDecl
       */
      public void startEntity(String name) throws org.xml.sax.SAXException
      {
          if (name.equals("[dtd]"))
              m_inExternalDTD = true;
          m_inEntityRef = true;
      }
  
      /**
       * For the enclosing elements starting tag write out
       * out any attributes followed by ">"
       *
       * @throws org.xml.sax.SAXException
       */
      protected void closeStartTag() throws SAXException
      {
  
          if (m_startTagOpen)
          {
  
              try
              {
                  processAttributes();
                  m_writer.write('>');
              }
              catch (IOException e)
              {
                  throw new SAXException(e);
              }
  
              /* whether Xalan or XSLTC, we have the prefix mappings now, so
               * lets determine if the current element is specified in the cdata-
               * section-elements list.
               */
              pushCdataSectionState();
  
              m_isprevtext = false;
              m_preserves.push(m_ispreserve);
              m_startTagOpen = false;
  
          }
  
      }
  
      /**
       * Report the start of DTD declarations, if any.
       *
       * Any declarations are assumed to be in the internal subset unless
       * otherwise indicated.
       * 
       * @param name The document type name.
       * @param publicId The declared public identifier for the
       *        external DTD subset, or null if none was declared.
       * @param systemId The declared system identifier for the
       *        external DTD subset, or null if none was declared.
       * @throws org.xml.sax.SAXException The application may raise an
       *            exception.
       * @see #endDTD
       * @see #startEntity
       */
      public void startDTD(String name, String publicId, String systemId)
          throws org.xml.sax.SAXException
      {
          setDoctypeSystem(systemId);
          setDoctypePublic(publicId);
  
          m_elementName = name;
          m_inDoctype = true;
      }
  
      /**
       * Returns the m_indentAmount.
       * @return int
       */
      public int getIndentAmount()
      {
          return m_indentAmount;
      }
  
      /**
       * Sets the m_indentAmount.
       * 
       * @param m_indentAmount The m_indentAmount to set
       */
      public void setIndentAmount(int m_indentAmount)
      {
          this.m_indentAmount = m_indentAmount;
      }
  
      /**
       * Tell if, based on space preservation constraints and the doIndent property,
       * if an indent should occur.
       *
       * @return True if an indent should occur.
       */
      protected boolean shouldIndent()
      {
          return m_doIndent && (!m_ispreserve && !m_isprevtext);
      }
  
      /**
       * Searches for the list of qname properties with the specified key in the
       * property list. If the key is not found in this property list, the default
       * property list, and its defaults, recursively, are then checked. The
       * method returns <code>null</code> if the property is not found.
       *
       * @param   key   the property key.
       * @param props the list of properties to search in.
       * 
       * Sets the vector of local-name/URI pairs of the cdata section elements
       * specified in the cdata-section-elements property.
       * 
       * This method is essentially a copy of getQNameProperties() from
       * OutputProperties. Eventually this method should go away and a call
       * to setCdataSectionElements(Vector v) should be made directly.
       */
      private void setCdataSectionElements(String key, Properties props)
      {
  
          String s = props.getProperty(key);
  
          if (null != s)
          {
              // Vector of URI/LocalName pairs
              Vector v = new Vector();
              int l = s.length();
              boolean inCurly = false;
              FastStringBuffer buf = new FastStringBuffer();
  
              // parse through string, breaking on whitespaces.  I do this instead
              // of a tokenizer so I can track whitespace inside of curly brackets,
              // which theoretically shouldn't happen if they contain legal URLs.
              for (int i = 0; i < l; i++)
              {
                  char c = s.charAt(i);
  
                  if (Character.isWhitespace(c))
                  {
                      if (!inCurly)
                      {
                          if (buf.length() > 0)
                          {
                              addCdataSectionElement(buf.toString(), v);
                              buf.reset();
                          }
                          continue;
                      }
                  }
                  else if ('{' == c)
                      inCurly = true;
                  else if ('}' == c)
                      inCurly = false;
  
                  buf.append(c);
              }
  
              if (buf.length() > 0)
              {
                  addCdataSectionElement(buf.toString(), v);
                  buf.reset();
              }
              // call the official, public method to set the collected names
              setCdataSectionElements(v);
          }
  
      }
  
      /**
       * Adds a URI/LocalName pair of strings to the list.
       *
       * @param name String of the form "{uri}local" or "local" 
       * 
       * @return a QName object
       */
      private void addCdataSectionElement(String URI_and_localName, Vector v)
      {
  
          StringTokenizer tokenizer =
              new StringTokenizer(URI_and_localName, "{}", false);
          QName qname;
          String s1 = tokenizer.nextToken();
          String s2 = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null;
  
          if (null == s2)
          {
              // add null URI and the local name
              v.add(null);
              v.add(s1);
          }
          else
          {
              // add URI, then local name
              v.add(s1);
              v.add(s2);
          }
      }
  
      /**
       * Remembers the cdata sections specified in the cdata-section-elements.
       * The "official way to set URI and localName pairs. 
       * This method should be used by both Xalan and XSLTC.
       * 
       * @param Vector URI_and_localNames a vector of pairs of Strings (URI/local)
       */
      public void setCdataSectionElements(Vector URI_and_localNames)
      {
          m_cdataSectionElements = URI_and_localNames;
      }
  
      /**
       * Makes sure that the namespace URI for the given qualified attribute name
       * is declared.
       * @param ns the namespace URI
       * @param rawName the qualified name 
       * @return returns null if no action is taken, otherwise it returns the
       * prefix used in declaring the namespace. 
       * @throws SAXException
       */
      protected String ensureAttributesNamespaceIsDeclared(
          String ns,
          String localName,
          String rawName)
          throws org.xml.sax.SAXException
      {
  
          if (ns != null && ns.length() > 0)
          {
  
              // extract the prefix in front of the raw name
              int index = 0;
              String prefixFromRawName =
                  (index = rawName.indexOf(":")) < 0
                      ? ""
                      : rawName.substring(0, index);
  
              if (index > 0)
              {
                  // we have a prefix, lets see if it maps to a namespace 
                  String uri = m_prefixMap.lookupNamespace(prefixFromRawName);
                  if (uri != null && uri.equals(ns))
                  {
                      // the prefix in the raw name is already maps to the given namespace uri
                      // so we don't need to do anything
                      return null;
                  }
                  else
                  {
                      // The uri does not map to the prefix in the raw name,
                      // so lets make the mapping.
                      this.startPrefixMapping(prefixFromRawName, ns, false);
                      this.addAttribute(
                          "http://www.w3.org/2000/xmlns/",
                          prefixFromRawName,
                          "xmlns:" + prefixFromRawName,
                          "CDATA",
                          ns);
                      return prefixFromRawName;
                  }
              }
              else
              {
                  // we don't have a prefix in the raw name.
                  // Does the URI map to a prefix already?
                  String prefix = m_prefixMap.lookupPrefix(ns);
                  if (prefix == null)
                  {
                      // uri is not associated with a prefix,
                      // so lets generate a new prefix to use
                      prefix = m_prefixMap.generateNextPrefix();
                      this.startPrefixMapping(prefix, ns, false);
                      this.addAttribute(
                          "http://www.w3.org/2000/xmlns/",
                          prefix,
                          "xmlns:" + prefix,
                          "CDATA",
                          ns);
                  }
  
                  return prefix;
  
              }
          }
          return null;
      }
  
      private void ensurePrefixIsDeclared(String ns, String rawName)
          throws org.xml.sax.SAXException
      {
  
          if (ns != null && ns.length() > 0)
          {
              int index;
              String prefix =
                  (index = rawName.indexOf(":")) < 0
                      ? ""
                      : rawName.substring(0, index);
  
              if (null != prefix)
              {
                  String foundURI = m_prefixMap.lookupNamespace(prefix);
  
                  if ((null == foundURI) || !foundURI.equals(ns))
                  {
                      this.startPrefixMapping(prefix, ns);
  
                      // Bugzilla1133: Generate attribute as well as namespace event.
                      // SAX does expect both.
  
                      this.addAttributeAlways(
                          "http://www.w3.org/2000/xmlns/",
                          prefix,
                          "xmlns" + (prefix.length() == 0 ? "" : ":") + prefix,
                          "CDATA",
                          ns);
                  }
  
              }
          }
      }
  
      /**
       * This method flushes any pending events, which can be startDocument()
       * closing the opening tag of an element, or closing an open CDATA section.
       */
      public void flushPending()
      {
          try
          {
  
              if (m_needToCallStartDocument)
              {
                  startDocumentInternal();
                  m_needToCallStartDocument = false;
              }
              if (m_startTagOpen)
              {
                  closeStartTag();
                  m_startTagOpen = false;
              }
  
              if (m_cdataTagOpen)
              {
                  closeCDATA();
                  m_cdataTagOpen = false;
              }
          }
          catch (SAXException e)
          { // can we do anything useful here,
              // or should this method throw a SAXException?
          }
  
      }
  
      public void setContentHandler(ContentHandler ch)
      {
          // this method is really only useful in the ToSAXHandler classes but it is
          // in the interface.  If the method defined here is ever called
          // we are probably in trouble.
      }
  
      /**
       * Adds the given attribute to the set of attributes, even if there is
       * nocurrently open element. This is useful if a SAX startPrefixMapping()
       * should need to add an attribute before the element name is seen.
       * 
       * This method is a copy of its super classes method, except that some
       * tracing of events is done.  This is so the tracing is only done for
       * stream serializers, not for SAX ones.
       *
       * @param uri the URI of the attribute
       * @param localName the local name of the attribute
       * @param rawName   the qualified name of the attribute
       * @param type the type of the attribute (probably CDATA)
       * @param value the value of the attribute
       */
      public void addAttributeAlways(
          String uri,
          String localName,
          String rawName,
          String type,
          String value)
      {
  
          int index;
          index = m_attributes.getIndex(rawName);
          if (index >= 0)
          {
              String old_value = null;
              if (m_tracer != null)
              {
                  old_value = m_attributes.getValue(index);
                  if (value.equals(old_value))
                      old_value = null;
              }
  
              /* We've seen the attribute before.
               * We may have a null uri or localName, but all we really
               * want to re-set is the value anyway.
               */
              m_attributes.setValue(index, value);
              if (old_value != null)
                  firePseudoAttributes();
  
          }
          else
          {
              // the attribute doesn't exist yet, create it
              m_attributes.addAttribute(uri, localName, rawName, type, value);
              if (m_tracer != null)
                  firePseudoAttributes();
          }
  
      }
  
      /**
       * To fire off the pseudo characters of attributes, as they currently
       * exist. This method should be called everytime an attribute is added,
       * or when an attribute value is changed.
       */
  
      protected void firePseudoAttributes()
      {
  
          int nAttrs;
  
          if (m_tracer != null && (nAttrs = m_attributes.getLength()) > 0)
          {
              String encoding = getEncoding();
              // make a StringBuffer to write the name="value" pairs to.
              StringBuffer sb = new StringBuffer();
  
              // make a writer that internally appends to the same
              // StringBuffer
              java.io.Writer writer = new ToStream.WritertoStringBuffer(sb);
  
              try
              {
                  for (int i = 0; i < nAttrs; i++)
                  {
  
                      // for each attribute append the name="value"
                      // to the StringBuffer
                      final String name = m_attributes.getQName(i);
                      final String value = m_attributes.getValue(i);
                      sb.append(' ');
                      sb.append(name);
                      sb.append("=\"");
                      writeAttrString(writer, value, encoding);
                      sb.append('\"');
                  }
              }
              catch (IOException ioe)
              {
              }
  
              // convert the StringBuffer to a char array and
              // emit the trace event that these characters "might"
              // be written
              char ch[] = sb.toString().toCharArray();
              m_tracer.fireGenerateEvent(
                  SerializerTrace.EVENTTYPE_OUTPUT_PSEUDO_CHARACTERS,
                  ch,
                  0,
                  ch.length);
          }
      }
  
      /**
       * This inner class is used only to collect attribute values
       * written by the method writeAttrString() into a string buffer.
       * In this manner trace events, and the real writing of attributes will use
       * the same code.
       * 
       * @author minchau
       *
       */
      private class WritertoStringBuffer extends java.io.Writer
      {
          final private StringBuffer m_stringbuf;
          /**
           * @see java.io.Writer#write(char[], int, int)
           */
          WritertoStringBuffer(StringBuffer sb)
          {
              m_stringbuf = sb;
          }
  
          public void write(char[] arg0, int arg1, int arg2) throws IOException
          {
              m_stringbuf.append(arg0, arg1, arg2);
          }
          /**
           * @see java.io.Writer#flush()
           */
          public void flush() throws IOException
          {
          }
          /**
           * @see java.io.Writer#close()
           */
          public void close() throws IOException
          {
          }
  
          public void write(int i)
          {
              m_stringbuf.append((char) i);
          }
          
          public void write(String s)
          {
              m_stringbuf.append(s);
          }
      }
  
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setTransformer(Transformer)
       */
      public void setTransformer(Transformer transformer) {
          super.setTransformer(transformer);
          if (m_tracer != null
           && !(m_writer instanceof SerializerTraceWriter)  )
              m_writer = new SerializerTraceWriter(m_writer, m_tracer);        
          
          
      }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ToTextSAXHandler.java
  
  Index: ToTextSAXHandler.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 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.xml.serializer;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.Writer;
  import java.util.Properties;
  
  import org.w3c.dom.Node;
  import org.xml.sax.Attributes;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  import org.xml.sax.ext.LexicalHandler;
  
  /**
   * @author minchau
   *
   * To change this generated comment edit the template variable "typecomment":
   * Window>Preferences>Java>Templates.
   * To enable and disable the creation of type comments go to
   * Window>Preferences>Java>Code Generation.
   */
  public class ToTextSAXHandler extends ToSAXHandler 
  {
      /**
       * From XSLTC
       * @see org.apache.xml.serializer.ExtendedContentHandler#endElement(String)
       */
      public void endElement(String elemName) throws SAXException
      {
          super.fireEndElem(elemName);
      }
  
      /**
       * @see org.xml.sax.ContentHandler#endElement(String, String, String)
       */
      public void endElement(String arg0, String arg1, String arg2)
          throws SAXException
      {
          super.fireEndElem(arg2);    	
      }
  
      public ToTextSAXHandler(ContentHandler hdlr, LexicalHandler lex, String encoding)
      {
          super(hdlr, lex, encoding);
      }
      
          /**
       * From XSLTC
       */
      public ToTextSAXHandler(ContentHandler handler, String encoding)
      {
          super(handler,encoding);
      }
  
      public void comment(char ch[], int start, int length)
          throws org.xml.sax.SAXException
      {
          super.fireCommentEvent(ch, start, length);
      }
  
      public void comment(String data) throws org.xml.sax.SAXException
      {
          comment(data.toCharArray(), 0, data.length());
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#getOutputFormat()
       */
      public Properties getOutputFormat()
      {
          return null;
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#getOutputStream()
       */
      public OutputStream getOutputStream()
      {
          return null;
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#getWriter()
       */
      public Writer getWriter()
      {
          return null;
      }
  
      /**
       * Does nothing because 
       * the indent attribute is ignored for text output
       * @see org.apache.xml.serializer.SerializationHandler#indent(int)
       */
      public void indent(int n) throws SAXException
      {
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#reset()
       */
      public boolean reset()
      {
          return false;
      }
  
      /**
       * @see org.apache.xml.serializer.DOMSerializer#serialize(Node)
       */
      public void serialize(Node node) throws IOException
      {
      }
  
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setEscaping(boolean)
       */
      public boolean setEscaping(boolean escape)
      {
          return false;
      }
  
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setIndent(boolean)
       */
      public void setIndent(boolean indent)
      {
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#setOutputFormat(Properties)
       */
      public void setOutputFormat(Properties format)
      {
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#setOutputStream(OutputStream)
       */
      public void setOutputStream(OutputStream output)
      {
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#setWriter(Writer)
       */
      public void setWriter(Writer writer)
      {
      }
  
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
       */
      public void addAttribute(
          String uri,
          String localName,
          String rawName,
          String type,
          String value)
      {
      }
  
      /**
       * @see org.xml.sax.ext.DeclHandler#attributeDecl(String, String, String, String, String)
       */
      public void attributeDecl(
          String arg0,
          String arg1,
          String arg2,
          String arg3,
          String arg4)
          throws SAXException
      {
      }
  
      /**
       * @see org.xml.sax.ext.DeclHandler#elementDecl(String, String)
       */
      public void elementDecl(String arg0, String arg1) throws SAXException
      {
      }
  
      /**
       * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(String, String, String)
       */
      public void externalEntityDecl(String arg0, String arg1, String arg2)
          throws SAXException
      {
      }
  
      /**
       * @see org.xml.sax.ext.DeclHandler#internalEntityDecl(String, String)
       */
      public void internalEntityDecl(String arg0, String arg1)
          throws SAXException
      {
      }
  
      /**
       * @see org.xml.sax.ContentHandler#endPrefixMapping(String)
       */
      public void endPrefixMapping(String arg0) throws SAXException
      {
      }
  
      /**
       * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
       */
      public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
          throws SAXException
      {
      }
  
      /**
       * From XSLTC
       * @see org.xml.sax.ContentHandler#processingInstruction(String, String)
       */
      public void processingInstruction(String arg0, String arg1)
          throws SAXException
      {
  		super.fireEscapingEvent(arg0,arg1);            	
      }
  
      /**
       * @see org.xml.sax.ContentHandler#setDocumentLocator(Locator)
       */
      public void setDocumentLocator(Locator arg0)
      {
      }
  
      /**
       * @see org.xml.sax.ContentHandler#skippedEntity(String)
       */
      public void skippedEntity(String arg0) throws SAXException
      {
      }
  
      /**
       * @see org.xml.sax.ContentHandler#startElement(String, String, String, Attributes)
       */
      public void startElement(
          String arg0,
          String arg1,
          String arg2,
          Attributes arg3)
          throws SAXException
      {
          flushPending();
          super.startElement(arg0, arg1, arg2, arg3);
      }
  
      /**
       * @see org.xml.sax.ext.LexicalHandler#endCDATA()
       */
      public void endCDATA() throws SAXException
      {
      }
  
      /**
       * @see org.xml.sax.ext.LexicalHandler#endDTD()
       */
      public void endDTD() throws SAXException
      {
      }
  
      /**
       * @see org.xml.sax.ext.LexicalHandler#startCDATA()
       */
      public void startCDATA() throws SAXException
      {
      }
  
  
      /**
       * @see org.xml.sax.ext.LexicalHandler#startEntity(String)
       */
      public void startEntity(String arg0) throws SAXException
      {
      }
  
  
      /**
       * From XSLTC
       * @see org.apache.xml.serializer.ExtendedContentHandler#startElement(String)
       */
      public void startElement(
      String elementNamespaceURI,
      String elementLocalName,
      String elementName) throws SAXException
      {
          super.startElement(elementNamespaceURI, elementLocalName, elementName);
      }
      
      public void startElement(
      String elementName) throws SAXException
      {
          super.startElement(elementName);
      }
      
  
      /**
       * From XSLTC
       * @see org.xml.sax.ContentHandler#endDocument()
       */
      public void endDocument() throws SAXException { 
          
          flushPending();
          m_saxHandler.endDocument();
  
          super.fireEndDoc();
      }
   
      /**
  	 *	
       * @see org.apache.xml.serializer.ExtendedContentHandler#characters(String)
       */
      public void characters(String characters) 
      throws SAXException 
      { 
     
          m_saxHandler.characters(characters.toCharArray(), 0, 
          characters.length());
      
      }
      /**
  	 * @see org.xml.sax.ContentHandler#characters(char[], int, int)
       */
      public void characters(char[] characters, int offset, int length)
      throws SAXException 
      { 
      
          m_saxHandler.characters(characters, offset, length);
  
          // time to fire off characters event
          super.fireCharEvent(characters, offset, length);                
      }
  
      /**
       * From XSLTC
       */
      public void addAttribute(String name, String value) 
      {
          // do nothing
      }
  
  
      public boolean startPrefixMapping(
          String prefix,
          String uri,
          boolean shouldFlush)
          throws SAXException
      {
          // no namespace support for HTML
          return false;
      }
  
  
      public void startPrefixMapping(String prefix, String uri)
          throws org.xml.sax.SAXException
      {
          // no namespace support for HTML
      }
  
  
      public void namespaceAfterStartElement(
          final String prefix,
          final String uri)
          throws SAXException
      {
          // no namespace support for HTML
      }
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ToTextStream.java
  
  Index: ToTextStream.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 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.xml.serializer;
  
  import java.io.IOException;
  
  import org.apache.xml.serializer.CharInfo;
  import org.xml.sax.Attributes;
  import org.xml.sax.SAXException;
  
  /**
   * @author minchau
   *
   * To change this generated comment edit the template variable "typecomment":
   * Window>Preferences>Java>Templates.
   * To enable and disable the creation of type comments go to
   * Window>Preferences>Java>Code Generation.
   */
  public class ToTextStream extends ToStream 
  { 
  
         
    /**
     * Default constructor.
     */
    public ToTextStream()
    {
      super();
    }
  
   
   
    /**
     * Receive notification of the beginning of a document.
     *
     * <p>The SAX parser will invoke this method only once, before any
     * other methods in this interface or in DTDHandler (except for
     * setDocumentLocator).</p>
     *
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     *
     * @throws org.xml.sax.SAXException
     */
    protected void startDocumentInternal() throws org.xml.sax.SAXException
    {
      super.startDocumentInternal();
  
      m_needToCallStartDocument = false;
  
      // No action for the moment.
    }
  
    /**
     * Receive notification of the end of a document.
     *
     * <p>The SAX parser will invoke this method only once, and it will
     * be the last method invoked during the parse.  The parser shall
     * not invoke this method until it has either abandoned parsing
     * (because of an unrecoverable error) or reached the end of
     * input.</p>
     *
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     *
     * @throws org.xml.sax.SAXException
     */
    public void endDocument() throws org.xml.sax.SAXException
    {
      flushPending();
      flushWriter();
      super.fireEndDoc();
    }
  
    /**
     * Receive notification of the beginning of an element.
     *
     * <p>The Parser will invoke this method at the beginning of every
     * element in the XML document; there will be a corresponding
     * endElement() event for every startElement() event (even when the
     * element is empty). All of the element's content will be
     * reported, in order, before the corresponding endElement()
     * event.</p>
     *
     * <p>If the element name has a namespace prefix, the prefix will
     * still be attached.  Note that the attribute list provided will
     * contain only attributes with explicit values (specified or
     * defaulted): #IMPLIED attributes will be omitted.</p>
     *
     *
     * @param namespaceURI The Namespace URI, or the empty string if the
     *        element has no Namespace URI or if Namespace
     *        processing is not being performed.
     * @param localName The local name (without prefix), or the
     *        empty string if Namespace processing is not being
     *        performed.
     * @param name The qualified name (with prefix), or the
     *        empty string if qualified names are not available.
     * @param atts The attributes attached to the element, if any.
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see #endElement
     * @see org.xml.sax.AttributeList
     *
     * @throws org.xml.sax.SAXException
     */
    public void startElement(
            String namespaceURI, String localName, String name, Attributes atts)
              throws org.xml.sax.SAXException
    {
  
      m_currentElemDepth++;
  
      // time to fire off startElement event
      super.fireStartElem(name);
      return;
    }
  
    /**
     * Receive notification of the end of an element.
     *
     * <p>The SAX parser will invoke this method at the end of every
     * element in the XML document; there will be a corresponding
     * startElement() event for every endElement() event (even when the
     * element is empty).</p>
     *
     * <p>If the element name has a namespace prefix, the prefix will
     * still be attached to the name.</p>
     *
     *
     * @param namespaceURI The Namespace URI, or the empty string if the
     *        element has no Namespace URI or if Namespace
     *        processing is not being performed.
     * @param localName The local name (without prefix), or the
     *        empty string if Namespace processing is not being
     *        performed.
     * @param name The qualified name (with prefix), or the
     *        empty string if qualified names are not available.
     * @param name The element type name
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     *
     * @throws org.xml.sax.SAXException
     */
    public void endElement(String namespaceURI, String localName, String name)
            throws org.xml.sax.SAXException
    {
          m_currentElemDepth--;
  		super.fireEndElem(name);           
    }
  
    /**
     * Receive notification of character data.
     *
     * <p>The Parser will call this method to report each chunk of
     * character data.  SAX parsers may return all contiguous character
     * data in a single chunk, or they may split it into several
     * chunks; however, all of the characters in any single event
     * must come from the same external entity, so that the Locator
     * provides useful information.</p>
     *
     * <p>The application must not attempt to read from the array
     * outside of the specified range.</p>
     *
     * <p>Note that some parsers will report whitespace using the
     * ignorableWhitespace() method rather than this one (validating
     * parsers must do so).</p>
     *
     * @param ch The characters from the XML document.
     * @param start The start position in the array.
     * @param length The number of characters to read from the array.
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see #ignorableWhitespace
     * @see org.xml.sax.Locator
     */
    public void characters(char ch[], int start, int length)
            throws org.xml.sax.SAXException
    {
  
      // this.accum(ch, start, length);
      flushPending();    
      
      try
      {
          writeNormalizedChars(ch, start, length, false);
  		super.fireCharEvent(ch, start, length);      
      }
      catch(IOException ioe)
      {
        throw new SAXException(ioe);
      }
    }
  
    /**
     * If available, when the disable-output-escaping attribute is used,
     * output raw text without escaping.
     *
     * @param ch The characters from the XML document.
     * @param start The start position in the array.
     * @param length The number of characters to read from the array.
     *
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     */
    public void charactersRaw(char ch[], int start, int length)
            throws org.xml.sax.SAXException
    {
  
      try
      {
        writeNormalizedChars(ch, start, length, false);
      }
      catch(IOException ioe)
      {
        throw new SAXException(ioe);
      }
    }
    
  /**
   * Normalize the characters, but don't escape.  Different from 
   * SerializerToXML#writeNormalizedChars because it does not attempt to do 
   * XML escaping at all.
   *
   * @param ch The characters from the XML document.
   * @param start The start position in the array.
   * @param length The number of characters to read from the array.
   * @param isCData true if a CDATA block should be built around the characters.
   *
   * @throws IOException
   * @throws org.xml.sax.SAXException
   */
  void writeNormalizedChars(
      final char ch[],
      final int start,
      final int length,
      final boolean isCData)
      throws IOException, org.xml.sax.SAXException
  {
      final int end = start + length;
  
      /* copy a few "constants" before the loop for performance */
      final char S_LINEFEED = CharInfo.S_LINEFEED;
      final int M_MAXCHARACTER = this.m_maxCharacter;
  
      if (isCData)
      {
          for (int i = start; i < end; i++)
          {
              final char c = ch[i];
  
              if (S_LINEFEED == c)
              {
                  m_writer.write(m_lineSep, 0, m_lineSepLen);
              }
              else if (c > M_MAXCHARACTER)
              {
                  if (i != 0)
                      closeCDATA();
  
                  // This needs to go into a function...
                  if (isUTF16Surrogate(c))
                  {
                      i = writeUTF16Surrogate(c, ch, i, end);
                  }
                  else
                  {
                      m_writer.write(c);
                  }
  
                  if ((i != 0) && (i < (end - 1)))
                  {
                      m_writer.write(CDATA_DELIMITER_OPEN);
                      m_cdataTagOpen = true;
                  }
              }
              else if (
                  ((i < (end - 2))
                      && (']' == c)
                      && (']' == ch[i + 1])
                      && ('>' == ch[i + 2])))
              {
                  m_writer.write(CDATA_CONTINUE);
                  i += 2;
              }
              else
              {
                  if (c <= M_MAXCHARACTER)
                  {
                      m_writer.write(c);
                  }
  
                  else if (isUTF16Surrogate(c))
                  {
                      i = writeUTF16Surrogate(c, ch, i, end);
                  }
                  else
                  {
                      m_writer.write(c);
                  }
              }
          }
      }
      else
      {
          // not in CDATA section
          for (int i = start; i < end; i++)
          {
              final char c = ch[i];
  
              if (S_LINEFEED == c)
              {
                  m_writer.write(m_lineSep, 0, m_lineSepLen);
              }
              else if (c <= M_MAXCHARACTER)
              {
                  m_writer.write(c);
              }
              else if (isUTF16Surrogate(c))
              {
                  i = writeUTF16Surrogate(c, ch, i, end);
              }
              else
              {
                  m_writer.write(c);
              }
          }
      }
  }
  
    /**
     * Receive notification of cdata.
     *
     * <p>The Parser will call this method to report each chunk of
     * character data.  SAX parsers may return all contiguous character
     * data in a single chunk, or they may split it into several
     * chunks; however, all of the characters in any single event
     * must come from the same external entity, so that the Locator
     * provides useful information.</p>
     *
     * <p>The application must not attempt to read from the array
     * outside of the specified range.</p>
     *
     * <p>Note that some parsers will report whitespace using the
     * ignorableWhitespace() method rather than this one (validating
     * parsers must do so).</p>
     *
     * @param ch The characters from the XML document.
     * @param start The start position in the array.
     * @param length The number of characters to read from the array.
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see #ignorableWhitespace
     * @see org.xml.sax.Locator
     */
    public void cdata(char ch[], int start, int length)
            throws org.xml.sax.SAXException
    {
      try
      {
          writeNormalizedChars(ch, start, length, false);
          super.fireCDATAEvent(ch, start, length);              
      }
      catch(IOException ioe)
      {
        throw new SAXException(ioe);
      }
    }
  
    /**
     * Receive notification of ignorable whitespace in element content.
     *
     * <p>Validating Parsers must use this method to report each chunk
     * of ignorable whitespace (see the W3C XML 1.0 recommendation,
     * section 2.10): non-validating parsers may also use this method
     * if they are capable of parsing and using content models.</p>
     *
     * <p>SAX parsers may return all contiguous whitespace in a single
     * chunk, or they may split it into several chunks; however, all of
     * the characters in any single event must come from the same
     * external entity, so that the Locator provides useful
     * information.</p>
     *
     * <p>The application must not attempt to read from the array
     * outside of the specified range.</p>
     *
     * @param ch The characters from the XML document.
     * @param start The start position in the array.
     * @param length The number of characters to read from the array.
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see #characters
     *
     * @throws org.xml.sax.SAXException
     */
    public void ignorableWhitespace(char ch[], int start, int length)
            throws org.xml.sax.SAXException
    {
  
      try
      {
        writeNormalizedChars(ch, start, length, false);
      }
      catch(IOException ioe)
      {
        throw new SAXException(ioe);
      }
    }
  
    /**
     * Receive notification of a processing instruction.
     *
     * <p>The Parser will invoke this method once for each processing
     * instruction found: note that processing instructions may occur
     * before or after the main document element.</p>
     *
     * <p>A SAX parser should never report an XML declaration (XML 1.0,
     * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
     * using this method.</p>
     *
     * @param target The processing instruction target.
     * @param data The processing instruction data, or null if
     *        none was supplied.
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     *
     * @throws org.xml.sax.SAXException
     */
    public void processingInstruction(String target, String data)
            throws org.xml.sax.SAXException
    {
      // flush anything pending first
      flushPending();     
      super.fireEscapingEvent(target, data);    
    }
  
    /**
     * Called when a Comment is to be constructed.
     * Note that Xalan will normally invoke the other version of this method.
     * %REVIEW% In fact, is this one ever needed, or was it a mistake?
     *
     * @param   data  The comment data.
     * @throws org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     */
    public void comment(String data) throws org.xml.sax.SAXException
    {
      comment(data.toCharArray(), 0, data.length());
    }
  
    /**
     * Report an XML comment anywhere in the document.
     *
     * This callback will be used for comments inside or outside the
     * document element, including comments in the external DTD
     * subset (if read).
     *
     * @param ch An array holding the characters in the comment.
     * @param start The starting position in the array.
     * @param length The number of characters to use from the array.
     * @throws org.xml.sax.SAXException The application may raise an exception.
     */
    public void comment(char ch[], int start, int length)
            throws org.xml.sax.SAXException
    {
  
      flushPending();
  
      super.fireCommentEvent(ch, start, length);
    }
  
    /**
     * Receive notivication of a entityReference.
     *
     * @param name non-null reference to the name of the entity.
     *
     * @throws org.xml.sax.SAXException
     */
    public void entityReference(String name) throws org.xml.sax.SAXException
    {
          super.fireEntityReference(name);    
    }
    
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
       */
      public void addAttribute(
          String uri,
          String localName,
          String rawName,
          String type,
          String value)
      {
          // do nothing, just forget all about the attribute
      }
   
      /**
       * @see org.xml.sax.ext.LexicalHandler#endCDATA()
       */
      public void endCDATA() throws SAXException
      {
          // do nothing
      }
  
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#endElement(String)
       */
      public void endElement(String elemName) throws SAXException
      {
          m_currentElemDepth--;
          super.fireEndElem(elemName);                       
      }
   
      /**
       * From XSLTC
       */
      public void startElement(
      String elementNamespaceURI,
      String elementLocalName,
      String elementName) 
      throws SAXException 
      {
          m_currentElemDepth++;
  
          if (m_needToCallStartDocument)
              startDocumentInternal();		
  		// time to fire off startlement event.
          super.fireStartElem(elementName);
          
          return;
      }
  
  
      /**
       * From XSLTC
       */
      public void characters(String characters) 
      throws SAXException 
      { 
          characters(characters.toCharArray(), 0, characters.length());
      }
  
  
      /**
       * From XSLTC
       */
      public void addAttribute(String name, String value)
      {
          // do nothing, forget about the attribute
      }
  
      public boolean startPrefixMapping(
          String prefix,
          String uri,
          boolean shouldFlush)
          throws SAXException
      {
          // no namespace support for HTML
          return false;
      }
  
  
      public void startPrefixMapping(String prefix, String uri)
          throws org.xml.sax.SAXException
      {
          // no namespace support for HTML
      }
  
  
      public void namespaceAfterStartElement(
          final String prefix,
          final String uri)
          throws SAXException
      {
          // no namespace support for HTML
      }    
  
      public void flushPending()
      {
          try
          {
              if (m_needToCallStartDocument)
              {
                  startDocumentInternal();
                  m_needToCallStartDocument = false;
              }
          }
          catch (SAXException e)
          { // can we do anything useful here,
              // or should this method throw a SAXException?
          }
      }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ToUnknownStream.java
  
  Index: ToUnknownStream.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 2003, International Business
   * Machines, Inc., http://www.ibm.com.  For more information on the Apache
   * Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.Writer;
  import java.util.Properties;
  import java.util.Vector;
  
  import javax.xml.transform.SourceLocator;
  import javax.xml.transform.Transformer;
  
  import org.w3c.dom.Node;
  import org.xml.sax.Attributes;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  
  
  /**
   *This class wraps another SerializationHandler. The wrapped object will either
   * handler XML or HTML, which is not known until a little later when the first XML
   * tag is seen.  If the first tag is <html> then the wrapped object is an HTML
   * handler, otherwise it is an XML handler.
   *
   * This class effectively caches the first few calls to it then passes them
   * on to the wrapped handler (once it exists).  After that subsequent calls a
   * simply passed directly to the wrapped handler.
   *
   * The user of this class doesn't know if the output is ultimatley XML or HTML.
   */
  public class ToUnknownStream extends SerializerBase
  {
  
      /**
       * The wrapped handler, initially XML but possibly switched to HTML
       */
      private SerializationHandler m_handler;
  
      /**
       * A String with no characters
       */
      private static final String EMPTYSTRING = "";
  
      /**
       * true if the underlying handler (XML or HTML) is fully initialized
       */
      private boolean m_wrapped_handler_not_initialized = false;
  
  
      /**
       * the prefix of the very first tag in the document
       */
      private String m_firstElementPrefix;
      /**
       * the element name (including any prefix) of the very first tag in the document
       */
      private String m_firstElementName;
  
      /**
       * the namespace URI associated with the first element
       */
      private String m_firstElementURI;
      
      /**
       * the local name (no prefix) associated with the first element
       */
      private String m_firstElementLocalName = null;
  
      /**
       * true if the first tag has been emitted to the wrapped handler
       */
      private boolean m_firstTagNotEmitted = true;
  
      /**
       * A collection of namespace URI's (only for first element).
       * _namespacePrefix has the matching prefix for these URI's
       */
      private Vector m_namespaceURI = null;
      /**
       * A collection of namespace Prefix (only for first element)
       * _namespaceURI has the matching URIs for these prefix'
       */
      private Vector m_namespacePrefix = null;
  
      /**
       * true if startDocument() was called before the underlying handler
       * was initialized
       */
      private boolean m_needToCallStartDocument = false;
      /**
       * true if setVersion() was called before the underlying handler
       * was initialized
       */
      private boolean m_setVersion_called = false;
      /**
       * true if setDoctypeSystem() was called before the underlying handler
       * was initialized
       */
      private boolean m_setDoctypeSystem_called = false;
      /**
       * true if setDoctypePublic() was called before the underlying handler
       * was initialized
       */
      private boolean m_setDoctypePublic_called = false;
      /**
       * true if setMediaType() was called before the underlying handler
       * was initialized
       */
      private boolean m_setMediaType_called = false;
  
      /**
       * Default constructor.
       * Initially this object wraps an XML Stream object, so _handler is never null.
       * That may change later to an HTML Stream object.
       */
      public ToUnknownStream()
      {
          m_handler = new ToXMLStream();
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#asContentHandler()
       * @return the wrapped XML or HTML handler
       */
      public ContentHandler asContentHandler() throws IOException
      {
          /* don't return the real handler ( m_handler ) because
           * that would expose the real handler to the outside.
           * Keep m_handler private so it can be internally swapped
           * to an HTML handler.
           */
          return this;
      }
  
      /**
       * @see org.apache.xml.serializer.SerializationHandler#close()
       */
      public void close()
      {
          m_handler.close();
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#getOutputFormat()
       * @return the properties of the underlying handler
       */
      public Properties getOutputFormat()
      {
          return m_handler.getOutputFormat();
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#getOutputStream()
       * @return the OutputStream of the underlying XML or HTML handler
       */
      public OutputStream getOutputStream()
      {
          return m_handler.getOutputStream();
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#getWriter()
       * @return the Writer of the underlying XML or HTML handler
       */
      public Writer getWriter()
      {
          return m_handler.getWriter();
      }
  
      /**
       * passes the call on to the underlying HTML or XML handler
       * @see org.apache.xml.serializer.Serializer#reset()
       * @return ???
       */
      public boolean reset()
      {
          return m_handler.reset();
      }
  
      /**
       * Converts the DOM node to output
       * @param node the DOM node to transform to output
       * @see org.apache.xml.serializer.DOMSerializer#serialize(Node)
       *
       */
      public void serialize(Node node) throws IOException
      {
          if (m_firstTagNotEmitted)
          {
              flush();
          }
          m_handler.serialize(node);
      }
  
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setEscaping(boolean)
       */
      public boolean setEscaping(boolean escape) throws SAXException
      {
          return m_handler.setEscaping(escape);
      }
  
      /**
       * Set the properties of the handler
       * @param format the output properties to set
       * @see org.apache.xml.serializer.Serializer#setOutputFormat(Properties)
       */
      public void setOutputFormat(Properties format)
      {
          m_handler.setOutputFormat(format);
      }
  
      /**
       * Sets the output stream to write to
       * @param output the OutputStream to write to
       * @see org.apache.xml.serializer.Serializer#setOutputStream(OutputStream)
       */
      public void setOutputStream(OutputStream output)
      {
          m_handler.setOutputStream(output);
      }
  
      /**
       * Sets the writer to write to
       * @param writer the writer to write to
       * @see org.apache.xml.serializer.Serializer#setWriter(Writer)
       */
      public void setWriter(Writer writer)
      {
          m_handler.setWriter(writer);
      }
  
      /**
       * Adds an attribute to the currenly open tag
       * @param uri the URI of a namespace
       * @param localName the attribute name, without prefix
       * @param rawName the attribute name, with prefix (if any)
       * @param type the type of the attribute, typically "CDATA"
       * @param value the value of the parameter
       * @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
       */
      public void addAttribute(
          String uri,
          String localName,
          String rawName,
          String type,
          String value)
          throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              flush();
          }
          m_handler.addAttribute(uri, localName, rawName, type, value);
      }
      /**
       * Adds an attribute to the currenly open tag
       * @param name the attribute name, with prefix (if any)
       * @param value the value of the parameter
       * @see org.apache.xml.serializer.ExtendedContentHandler#attribute(String, String)
       */
      public void addAttribute(String rawName, String value)
      {
          if (m_firstTagNotEmitted)
          {
              flush();
          }
          m_handler.addAttribute(rawName, value);
   
      }
  
      /**
       * Converts the String to a character array and calls the SAX method 
       * characters(char[],int,int);
       * 
       * @see org.apache.xml.serializer.ExtendedContentHandler#characters(String)
       */
      public void characters(String chars) throws SAXException
      {
          final char[] arr = chars.toCharArray();
          this.characters(arr, 0, arr.length);
      }    
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.ExtendedContentHandler#endElement(String)
       */
      public void endElement(String elementName) throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              flush();
          }
          m_handler.endElement(elementName);
      }
  
  
      /**
       * @see org.xml.sax.ContentHandler#startPrefixMapping(String, String)
       * @ param prefix The prefix that maps to the URI
       * @ param uri The URI for the namespace
       */
      public void startPrefixMapping(String prefix, String uri) throws SAXException
      {
          this.startPrefixMapping(prefix,uri, true);
      }
  
      /**
       * This method is used when a prefix/uri namespace mapping
       * is indicated after the element was started with a
       * startElement() and before and endElement().
       * startPrefixMapping(prefix,uri) would be used before the
       * startElement() call.
       * @param uri the URI of the namespace
       * @param prefix the prefix associated with the given URI.
       *
       * @see org.apache.xml.serializer.ExtendedContentHandler#namespaceAfterStartElement(String, String)
       */    
      public void namespaceAfterStartElement(String prefix, String uri)
          throws SAXException 
      {  
          // hack for XSLTC with finding URI for default namespace
          if (m_firstTagNotEmitted && m_firstElementURI == null && m_firstElementName != null)
          {
              String prefix1 = getPrefixPart(m_firstElementName);
              if (prefix1 == null && EMPTYSTRING.equals(prefix))
              {
                  // the elements URI is not known yet, and it
                  // doesn't have a prefix, and we are currently
                  // setting the uri for prefix "", so we have
                  // the uri for the element... lets remember it
                  m_firstElementURI = uri;
              }
          }         
          startPrefixMapping(prefix,uri, false);          
      }
      
      public boolean startPrefixMapping(String prefix, String uri, boolean shouldFlush)
          throws SAXException
      {
          boolean pushed = false;
          if (m_firstTagNotEmitted)
          {
              if (m_firstElementName != null && shouldFlush)
              {
                  /* we've already seen a startElement, and this is a prefix mapping
                   * for the up coming element, so flush the old element
                   * then send this event on its way.
                   */
                  flush();
                  pushed = m_handler.startPrefixMapping(prefix, uri, shouldFlush);
              } 
              else 
              {           
                  if (m_namespacePrefix == null)
                  {
                      m_namespacePrefix = new Vector();
                      m_namespaceURI = new Vector();
                  }
                  m_namespacePrefix.addElement(prefix);
                  m_namespaceURI.addElement(uri);
              
                  if (m_firstElementURI == null)
                  {
                      if (prefix.equals(m_firstElementPrefix))
                          m_firstElementURI = uri;
                  }
              }
  
          }
          else
          {
             pushed = m_handler.startPrefixMapping(prefix, uri, shouldFlush);
          }
          return pushed;
      }
  
      /**
        * This method cannot be cached because default is different in
        * HTML and XML (we need more than a boolean).
        */
  
      public void setVersion(String version)
      {
          m_handler.setVersion(version);
  
          // Cache call to setVersion()
          //       super.setVersion(version);
          m_setVersion_called = true;
      }
  
      /**
       * @see org.xml.sax.ContentHandler#startDocument()
       */
      public void startDocument() throws SAXException
      {
          m_needToCallStartDocument = true;
      }
  
   
      
      public void startElement(String qName) throws SAXException
      {
          this.startElement(null, null, qName, null);
      }
      
      public void startElement(String namespaceURI, String localName, String qName) throws SAXException
      {
          this.startElement(namespaceURI, localName, qName, null);
      }
  
      public void startElement(
          String namespaceURI,
          String localName,
          String elementName,
          Attributes atts) throws SAXException
      {
          /* we are notified of the start of an element */
          if (m_firstTagNotEmitted)
          {
              /* we have not yet sent the first element on its way */
              if (m_firstElementName != null) 
              {
                  /* this is not the first element, but a later one.
                   * But we have the old element pending, so flush it out,
                   * then send this one on its way. 
                   */
                  flush();
                  m_handler.startElement(namespaceURI, localName, elementName,  atts);                
              }
              else
              {
                  /* this is the very first element that we have seen, 
                   * so save it for flushing later.  We may yet get to know its
                   * URI due to added attributes.
                   */
                   
                  m_wrapped_handler_not_initialized = true;
                  m_firstElementName = elementName;
                  
                  // null if not known
                  m_firstElementPrefix = getPrefixPartUnknown(elementName);
                  
                  // null if not known
                  m_firstElementURI = namespaceURI;
                  
                  // null if not known
                  m_firstElementLocalName = localName;
                  
                  /* we don't want to call our own addAttributes, which
                   * merely delegates to the wrapped handler, but we want to
                   * add these attributes to m_attributes. So me must call super.
                   * addAttributes() In this case m_attributes is only used for the
                   * first element, after that this class totally delegates to the
                   * wrapped handler which is either XML or HTML.
                   */                
                  if (atts != null)   
                      super.addAttributes(atts);
                  
                  // if there are attributes, then lets make the flush()
                  // call the startElement on the handler and send the
                  // attributes on their way.
                  if (atts != null)   
                      flush();
                  
              }
          }
          else
          {
              // this is not the first element, but a later one, so just
              // send it on its way.
              m_handler.startElement(namespaceURI, localName, elementName,  atts);
          }
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.ExtendedLexicalHandler#comment(String)
       */
      public void comment(String comment) throws SAXException
      {
          if (m_firstTagNotEmitted && m_firstElementName != null)
          {
              emitFirstTag();
          }
          else if (m_needToCallStartDocument)
          {
              m_handler.startDocument();
              m_needToCallStartDocument = false;
          }
  
          m_handler.comment(comment);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#getDoctypePublic()
       */
      public String getDoctypePublic()
      {
  
          return m_handler.getDoctypePublic();
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#getDoctypeSystem()
       */
      public String getDoctypeSystem()
      {
          return m_handler.getDoctypeSystem();
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#getEncoding()
       */
      public String getEncoding()
      {
          return m_handler.getEncoding();
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#getIndent()
       */
      public boolean getIndent()
      {
          return m_handler.getIndent();
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#getIndentAmount()
       */
      public int getIndentAmount()
      {
          return m_handler.getIndentAmount();
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#getMediaType()
       */
      public String getMediaType()
      {
          return m_handler.getMediaType();
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#getOmitXMLDeclaration()
       */
      public boolean getOmitXMLDeclaration()
      {
          return m_handler.getOmitXMLDeclaration();
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#getStandalone()
       */
      public String getStandalone()
      {
          return m_handler.getStandalone();
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#getVersion()
       */
      public String getVersion()
      {
          return m_handler.getVersion();
      }
  
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#setDoctype(String, String)
       */
      public void setDoctype(String system, String pub)
      {
          m_handler.setDoctypePublic(pub);
          m_handler.setDoctypeSystem(system);
      }
  
      /**
       * Set the doctype in the underlying XML handler. Remember that this method
       * was called, just in case we need to transfer this doctype to an HTML handler
       * @param doctype the public doctype to set
       * @see org.apache.xml.serializer.XSLOutputAttributes#setDoctypePublic(String)
       */
      public void setDoctypePublic(String doctype)
      {
          m_handler.setDoctypePublic(doctype);
          m_setDoctypePublic_called = true;
      }
  
      /**
       * Set the doctype in the underlying XML handler. Remember that this method
       * was called, just in case we need to transfer this doctype to an HTML handler
       * @param doctype the system doctype to set
       * @see org.apache.xml.serializer.XSLOutputAttributes#setDoctypeSystem(String)
       */
      public void setDoctypeSystem(String doctype)
      {
          m_handler.setDoctypeSystem(doctype);
          m_setDoctypeSystem_called = true;
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#setEncoding(String)
       */
      public void setEncoding(String encoding)
      {
          m_handler.setEncoding(encoding);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#setIndent(boolean)
       */
      public void setIndent(boolean indent)
      {
          m_handler.setIndent(indent);
      }
  
      /**
       * Pass the call on to the underlying handler
       */
      public void setIndentAmount(int value)
      {
          m_handler.setIndentAmount(value);
      }
  
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#setMediaType(String)
       */
      public void setMediaType(String mediaType)
      {
          m_handler.setMediaType(mediaType);
          m_setMediaType_called = true;
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#setOmitXMLDeclaration(boolean)
       */
      public void setOmitXMLDeclaration(boolean b)
      {
          m_handler.setOmitXMLDeclaration(b);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.apache.xml.serializer.XSLOutputAttributes#setStandalone(String)
       */
      public void setStandalone(String standalone)
      {
          m_handler.setStandalone(standalone);
      }
  
      /**
       * @see org.apache.xml.serializer.XSLOutputAttributes#setVersion(String)
       */
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ext.DeclHandler#attributeDecl(String, String, String, String, String)
       */
      public void attributeDecl(
          String arg0,
          String arg1,
          String arg2,
          String arg3,
          String arg4)
          throws SAXException
      {
          m_handler.attributeDecl(arg0, arg1, arg2, arg3, arg4);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ext.DeclHandler#elementDecl(String, String)
       */
      public void elementDecl(String arg0, String arg1) throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              emitFirstTag();
          }
          m_handler.elementDecl(arg0, arg1);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(String, String, String)
       */
      public void externalEntityDecl(
          String name,
          String publicId,
          String systemId)
          throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              flush();
          }
          m_handler.externalEntityDecl(name, publicId, systemId);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ext.DeclHandler#internalEntityDecl(String, String)
       */
      public void internalEntityDecl(String arg0, String arg1)
          throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              flush();
          }
          m_handler.internalEntityDecl(arg0, arg1);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ContentHandler#characters(char[], int, int)
       */
      public void characters(char[] characters, int offset, int length)
          throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              flush();
          }
  
          m_handler.characters(characters, offset, length);
  
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ContentHandler#endDocument()
       */
      public void endDocument() throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              flush();
          }
  
          m_handler.endDocument();
          
      
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ContentHandler#endElement(String, String, String)
       */
      public void endElement(String namespaceURI, String localName, String qName)
          throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              flush();
              if (namespaceURI == null && m_firstElementURI != null)
                  namespaceURI = m_firstElementURI;
  
  
              if (localName == null && m_firstElementLocalName != null)
                  localName = m_firstElementLocalName;
          }
          
          m_handler.endElement(namespaceURI, localName, qName);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ContentHandler#endPrefixMapping(String)
       */
      public void endPrefixMapping(String prefix) throws SAXException
      {
          m_handler.endPrefixMapping(prefix);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
       */
      public void ignorableWhitespace(char[] ch, int start, int length)
          throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              flush();
          }
          m_handler.ignorableWhitespace(ch, start, length);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ContentHandler#processingInstruction(String, String)
       */
      public void processingInstruction(String target, String data)
          throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              flush();
          }
  
          m_handler.processingInstruction(target, data);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ContentHandler#setDocumentLocator(Locator)
       */
      public void setDocumentLocator(Locator locator)
      {
          m_handler.setDocumentLocator(locator);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ContentHandler#skippedEntity(String)
       */
      public void skippedEntity(String name) throws SAXException
      {
          m_handler.skippedEntity(name);
      }
  
  
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int)
       */
      public void comment(char[] ch, int start, int length) throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              flush();
          }
  
          m_handler.comment(ch, start, length);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ext.LexicalHandler#endCDATA()
       */
      public void endCDATA() throws SAXException
      {
  
          m_handler.endCDATA();
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ext.LexicalHandler#endDTD()
       */
      public void endDTD() throws SAXException
      {
  
          m_handler.endDTD();
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ext.LexicalHandler#endEntity(String)
       */
      public void endEntity(String name) throws SAXException
      {
          if (m_firstTagNotEmitted)
          {
              emitFirstTag();
          }
          m_handler.endEntity(name);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ext.LexicalHandler#startCDATA()
       */
      public void startCDATA() throws SAXException
      {
          m_handler.startCDATA();
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ext.LexicalHandler#startDTD(String, String, String)
       */
      public void startDTD(String name, String publicId, String systemId)
          throws SAXException
      {
          m_handler.startDTD(name, publicId, systemId);
      }
  
      /**
       * Pass the call on to the underlying handler
       * @see org.xml.sax.ext.LexicalHandler#startEntity(String)
       */
      public void startEntity(String name) throws SAXException
      {
          m_handler.startEntity(name);
      }
  
      /**
       * Initialize the wrapped output stream (XML or HTML).
       * If the stream handler should be HTML, then replace the XML handler with
       * an HTML handler. After than send the starting method calls that were cached
       * to the wrapped handler.
       *
       */
      private void initStreamOutput() throws SAXException
      {
  
          // Try to rule out if this is an not to be an HTML document based on prefix
          boolean firstElementIsHTML = isFirstElemHTML();
  
          if (firstElementIsHTML)
          {
              // create an HTML output handler, and initialize it
  
              // keep a reference to the old handler, ... it will soon be gone
              SerializationHandler oldHandler = m_handler;
  
              /* We have to make sure we get an output properties with the proper
               * defaults for the HTML method.  The easiest way to do this is to
               * have the OutputProperties class do it.
               */
  
              Properties htmlProperties =
                  OutputPropertiesFactory.getDefaultMethodProperties(Method.HTML);
              Serializer serializer =
                  SerializerFactory.getSerializer(htmlProperties);
  
              // The factory should be returning a ToStream
              // Don't know what to do if it doesn't
              // i.e. the user has over-ridden the content-handler property
              // for html
              m_handler = (SerializationHandler) serializer;
              //m_handler = new ToHTMLStream();
  
              Writer writer = oldHandler.getWriter();
  
              if (null != writer)
                  m_handler.setWriter(writer);
              else
              {
                  OutputStream os = oldHandler.getOutputStream();
  
                  if (null != os)
                      m_handler.setOutputStream(os);
              }
  
              // need to copy things from the old handler to the new one here
  
              //            if (_setVersion_called)
              //            {
              m_handler.setVersion(oldHandler.getVersion());
              //            }
              //            if (_setDoctypeSystem_called)
              //            {
              m_handler.setDoctypeSystem(oldHandler.getDoctypeSystem());
              //            }
              //            if (_setDoctypePublic_called)
              //            {
              m_handler.setDoctypePublic(oldHandler.getDoctypePublic());
              //            }
              //            if (_setMediaType_called)
              //            {
              m_handler.setMediaType(oldHandler.getMediaType());
              //            }
              
              m_handler.setTransformer(oldHandler.getTransformer());
          }
  
          /* Now that we have a real wrapped handler (XML or HTML) lets
           * pass any cached calls to it
           */
          // Call startDocument() if necessary
          if (m_needToCallStartDocument)
          {
              m_handler.startDocument();
              m_needToCallStartDocument = false;
          }
  
          // the wrapped handler is now fully initialized
          m_wrapped_handler_not_initialized = false;
      }
  
      private void emitFirstTag() throws SAXException
      {   
          if (m_firstElementName != null)
          {
              if (m_wrapped_handler_not_initialized)
              {
                  initStreamOutput();
                  m_wrapped_handler_not_initialized = false;
              }
              // Output first tag
              m_handler.startElement(m_firstElementURI, null, m_firstElementName, m_attributes);
              // don't need the collected attributes of the first element anymore.
              m_attributes = null;
  
              // Output namespaces of first tag
              if (m_namespacePrefix != null)
              {
                  final int n = m_namespacePrefix.size();
                  for (int i = 0; i < n; i++)
                  {
                      final String prefix =
                          (String) m_namespacePrefix.elementAt(i);
                      final String uri = (String) m_namespaceURI.elementAt(i);
                      m_handler.startPrefixMapping(prefix, uri, false);
                  }
                  m_namespacePrefix = null;
                  m_namespaceURI = null;
              }
              m_firstTagNotEmitted = false;
          }
      }
  
      /**
       * Utility function for calls to local-name().
       *
       * Don't want to override static function on SerializerBase
       * So added Unknown suffix to method name.
       */
      private String getLocalNameUnknown(String value)
      {
          int idx = value.lastIndexOf(':');
          if (idx >= 0)
              value = value.substring(idx + 1);
          idx = value.lastIndexOf('@');
          if (idx >= 0)
              value = value.substring(idx + 1);
          return (value);
      }
  
      /**
           * Utility function to return prefix
           *
           * Don't want to override static function on SerializerBase
           * So added Unknown suffix to method name.
           */
      private String getPrefixPartUnknown(String qname)
      {
          final int index = qname.indexOf(':');
          return (index > 0) ? qname.substring(0, index) : EMPTYSTRING;
      }
  
      /**
       * Determine if the firts element in the document is <html> or <HTML>
       * This uses the cached first element name, first element prefix and the
       * cached namespaces from previous method calls
       *
       * @return true if the first element is an opening <html> tag
       */
      private boolean isFirstElemHTML()
      {
          boolean isHTML;
  
          // is the first tag html, not considering the prefix ?
          isHTML =
              getLocalNameUnknown(m_firstElementName).equalsIgnoreCase("html");
  
          // Try to rule out if this is not to be an HTML document based on URI
          if (isHTML
              && m_firstElementURI != null
              && !EMPTYSTRING.equals(m_firstElementURI))
          {
              // the <html> element has a non-trivial namespace
              isHTML = false;
          }
          // Try to rule out if this is an not to be an HTML document based on prefix
          if (isHTML && m_namespacePrefix != null)
          {
              /* the first element has a name of "html", but lets check the prefix.
               * If the prefix points to a namespace with a URL that is not ""
               * then the doecument doesn't start with an <html> tag, and isn't html
               */
              final int max = m_namespacePrefix.size();
              for (int i = 0; i < max; i++)
              {
                  final String prefix = (String) m_namespacePrefix.elementAt(i);
                  final String uri = (String) m_namespaceURI.elementAt(i);
  
                  if (m_firstElementPrefix != null
                      && m_firstElementPrefix.equals(prefix)
                      && !EMPTYSTRING.equals(uri))
                  {
                      // The first element has a prefix, so it can't be <html>
                      isHTML = false;
                      break;
                  }
              }
  
          }
          return isHTML;
      }
      /**
       * @see org.apache.xml.serializer.Serializer#asDOMSerializer()
       */
      public DOMSerializer asDOMSerializer() throws IOException
      {
          return null;
      }
  
      /**
       * @param URI_and_localNames Vector a list of pairs of URI/localName
       * specified in the cdata-section-elements attribute
       * @see org.apache.xml.serializer.SerializationHandler#setCdataSectionElements(java.util.Vector)
       */
      public void setCdataSectionElements(Vector URI_and_localNames)
      {
          m_handler.setCdataSectionElements(URI_and_localNames);
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#addAttributes(org.xml.sax.Attributes)
       */
      public void addAttributes(Attributes atts) throws SAXException
      {
          m_handler.addAttributes(atts);
      }
  
      /**
       * Get the current namespace mappings.
       * Simply returns the mappings of the wrapped handler.
       * @see org.apache.xml.serializer.ExtendedContentHandler#getNamespaceMappings()
       */
      public NamespaceMappings getNamespaceMappings()
      {
          NamespaceMappings mappings = null;
          if (m_handler != null)
          {
              mappings = m_handler.getNamespaceMappings();
          }
          return mappings;
      }
      /**
       * @see org.apache.xml.serializer.SerializationHandler#flushPending()
       */
      public void flushPending()
      {
   
          flush();
        
          m_handler.flushPending();
      }
      
      private void flush()
      {
          try
          {
          if (m_firstTagNotEmitted)
          {
              emitFirstTag();
          }
          if (m_needToCallStartDocument)
          {
              m_handler.startDocument();
              m_needToCallStartDocument = false;
          }
          }
          catch(SAXException e)
          {
              throw new RuntimeException(e.toString());
          }
            
      
      }
  
      /**
       * @see org.apache.xml.serializer.SerializationHandler#getPrefix()
       */
      public String getPrefix(String namespaceURI)
      {
          return m_handler.getPrefix(namespaceURI);
      }
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#entityReference(java.lang.String)
       */
      public void entityReference(String entityName) throws SAXException
      {
          m_handler.entityReference(entityName);
      }
  
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#getNamespaceURI(java.lang.String, boolean)
       */
      public String getNamespaceURI(String qname, boolean isElement)
      {
          return m_handler.getNamespaceURI(qname, isElement);
      }
  
      public String getNamespaceURIFromPrefix(String prefix)
      {
          return m_handler.getNamespaceURIFromPrefix(prefix);
      }
  
      public void setTransformer(Transformer t)
      {
          m_handler.setTransformer(t);
      }
      public Transformer getTransformer()
      {
          return m_handler.getTransformer();
      }
  
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setContentHandler(org.xml.sax.ContentHandler)
       */
      public void setContentHandler(ContentHandler ch)
      {
          m_handler.setContentHandler(ch);
      }
      /**
       * This method is used to set the source locator, which might be used to
       * generated an error message.
       * @param locator the source locator
       *
       * @see org.apache.xml.serializer.ExtendedContentHandler#setSourceLocator(javax.xml.transform.SourceLocator)
       */    
      public void setSourceLocator(SourceLocator locator)
      {
          m_handler.setSourceLocator(locator);
      }
  
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ToXMLSAXHandler.java
  
  Index: ToXMLSAXHandler.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 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.xml.serializer;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.Writer;
  import java.util.Properties;
  
  import javax.xml.transform.Result;
  
  import org.w3c.dom.Node;
  import org.xml.sax.Attributes;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  import org.xml.sax.ext.LexicalHandler;
  
  /**
   * This class receives notification of SAX-like events, and with gathered
   * information over these calls it will invoke the equivalent SAX methods
   * on a handler, the ultimate output is known to be XML.
   * 
   * @author minchau
   */
  public class ToXMLSAXHandler extends ToSAXHandler
  {
  
      /**
       * Keeps track of whether output escaping is currently enabled
       */
      protected boolean m_escapeSetting = false;
  
      public ToXMLSAXHandler()
      {
          // default constructor (need to set content handler ASAP !)
          m_prefixMap = new NamespaceMappings();
          initCDATA();
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#getOutputFormat()
       */
      public Properties getOutputFormat()
      {
          return null;
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#getOutputStream()
       */
      public OutputStream getOutputStream()
      {
          return null;
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#getWriter()
       */
      public Writer getWriter()
      {
          return null;
      }
  
      /**
       * @see org.apache.xml.serializer.SerializationHandler#indent(int)
       */
      public void indent(int n) throws SAXException
      {
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#reset()
       */
      public boolean reset()
      {
          return false;
      }
  
      /**
       * @see org.apache.xml.serializer.DOMSerializer#serialize(Node)
       */
      public void serialize(Node node) throws IOException
      {
      }
  
      /**
       * @see org.apache.xml.serializer.SerializationHandler#setEscaping(boolean)
       */
      public boolean setEscaping(boolean escape) throws SAXException
      {
          boolean oldEscapeSetting = m_escapeSetting;
          m_escapeSetting = escape;
  
          if (escape) {
              processingInstruction(Result.PI_ENABLE_OUTPUT_ESCAPING, "");
          } else {
              processingInstruction(Result.PI_DISABLE_OUTPUT_ESCAPING, "");
          }
  
          return oldEscapeSetting;
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#setOutputFormat(Properties)
       */
      public void setOutputFormat(Properties format)
      {
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#setOutputStream(OutputStream)
       */
      public void setOutputStream(OutputStream output)
      {
      }
  
      /**
       * @see org.apache.xml.serializer.Serializer#setWriter(Writer)
       */
      public void setWriter(Writer writer)
      {
      }
  
      /**
       * @see org.xml.sax.ext.DeclHandler#attributeDecl(String, String, String, String, String)
       */
      public void attributeDecl(
          String arg0,
          String arg1,
          String arg2,
          String arg3,
          String arg4)
          throws SAXException
      {
      }
  
      /**
       * @see org.xml.sax.ext.DeclHandler#elementDecl(String, String)
       */
      public void elementDecl(String arg0, String arg1) throws SAXException
      {
      }
  
      /**
       * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(String, String, String)
       */
      public void externalEntityDecl(String arg0, String arg1, String arg2)
          throws SAXException
      {
      }
  
      /**
       * @see org.xml.sax.ext.DeclHandler#internalEntityDecl(String, String)
       */
      public void internalEntityDecl(String arg0, String arg1)
          throws SAXException
      {
      }
  
      /**
       * Receives notification of the end of the document.
       * @see org.xml.sax.ContentHandler#endDocument()
       */
      public void endDocument() throws SAXException
      {
  
          flushPending();
  
          // Close output document
          m_saxHandler.endDocument();
  
          super.fireEndDoc();
      }
  
      /**
       * 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 SAXException
      {
  
          m_startTagOpen = false;
  
          final String localName = getLocalName(m_elementName);
          final String uri = getNamespaceURI(m_elementName, true);
  
          // Now is time to send the startElement event
          if (m_needToCallStartDocument)
          {
              startDocumentInternal();
          }
          m_saxHandler.startElement(uri, localName, m_elementName, m_attributes);
          // we've sent the official SAX attributes on their way,
          // now we don't need them anymore.
          m_attributes.clear();
  
          if(m_state != null)
            m_state.setCurrentNode(null);
  
          pushCdataSectionState();
  
      }
  
      /**
       * Closes the open cdata tag
       */
      public void closeCDATA() throws SAXException
      {
  
          // Output closing bracket - "]]>"
          m_saxHandler.characters(ENDCDATA, 0, ENDCDATA.length);
          m_cdataTagOpen = false;
      }
  
      /**
       * @see org.xml.sax.ContentHandler#endElement(String, String, String)
       */
      public void endElement(String namespaceURI, String localName, String qName)
          throws SAXException
      {
          // Close any open elements etc.
          flushPending();
          
          if (namespaceURI == null)
          {
              if (m_elementURI != null)
                  namespaceURI = m_elementURI;
              else
                  namespaceURI = getNamespaceURI(qName, true);
          }
          
          if (localName == null)
          {
              if (m_elementLocalName != null)
                  localName = m_elementLocalName;
              else
                  localName = getLocalName(qName);
          }
  
          m_saxHandler.endElement(namespaceURI, localName, qName);
  
  		super.fireEndElem(qName);       
  
          /* Pop all namespaces at the current element depth.
           * We are not waiting for official endPrefixMapping() calls.
           */
          m_prefixMap.popNamespaces(m_currentElemDepth);
          m_currentElemDepth--;
          m_startTagOpen = false;
          // m_disableOutputEscapingStates.pop();
          m_cdataSectionStates.pop();
      }
  
      /**
       * @see org.xml.sax.ContentHandler#endPrefixMapping(String)
       */
      public void endPrefixMapping(String prefix) throws SAXException
      {
          /* poping all prefix mappings should have been done
           * in endElement() already
           */
           return;
      }
  
      /**
       * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
       */
      public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
          throws SAXException
      {
          m_saxHandler.ignorableWhitespace(arg0,arg1,arg2);
      }
  
      /**
       * @see org.xml.sax.ContentHandler#setDocumentLocator(Locator)
       */
      public void setDocumentLocator(Locator arg0)
      {
          m_saxHandler.setDocumentLocator(arg0);
      }
  
      /**
       * @see org.xml.sax.ContentHandler#skippedEntity(String)
       */
      public void skippedEntity(String arg0) throws SAXException
      {
          m_saxHandler.skippedEntity(arg0);
      }
  
      /**
       * @see org.xml.sax.ContentHandler#startPrefixMapping(String, String)
       * @ param prefix The prefix that maps to the URI
       * @ param uri The URI for the namespace
       */
      public void startPrefixMapping(String prefix, String uri)
          throws SAXException
      {
         startPrefixMapping(prefix, uri, true);
      }
  
      /**
       * Remember the prefix/uri mapping at the current nested element depth.
       *
       * @see org.xml.sax.ContentHandler#startPrefixMapping(String, String)
       * @param prefix The prefix that maps to the URI
       * @param uri The URI for the namespace
       * @param shouldFlush a flag indicating if the mapping applies to the
       * current element or an up coming child (not used).
       */
  
      public boolean startPrefixMapping(
          String prefix,
          String uri,
          boolean shouldFlush)
          throws org.xml.sax.SAXException
      {
  
          /* Remember the mapping, and at what depth it was declared
           * This is one greater than the current depth because these
           * mappings will apply to the next depth. This is in
           * consideration that startElement() will soon be called
           */
  
          boolean pushed;
          int pushDepth;
          if (shouldFlush)
          {
              flushPending();
              // the prefix mapping applies to the child element (one deeper)
              pushDepth = m_currentElemDepth + 1;
          }
          else
          {
              // the prefix mapping applies to the current element
              pushDepth = m_currentElemDepth;
          }
          pushed = m_prefixMap.pushNamespace(prefix, uri, pushDepth);
  
          if (pushed)
          {
              m_saxHandler.startPrefixMapping(prefix,uri);
              
              /* bjm: don't know if we really needto do this. The
               * callers of this object should have injected both
               * startPrefixMapping and the attributes.  We are
               * just covering our butt here.
               */
              String name;
              if (EMPTYSTRING.equals(prefix))
              {
                  name = "xmlns";
                  addAttributeAlways(XMLNS_URI, prefix, name,"CDATA",uri);
              }
              else {
                  if (!EMPTYSTRING.equals(uri)) // hack for XSLTC attribset16 test
                  {                             // that maps ns1 prefix to "" URI 
                      name = "xmlns:" + prefix;
  
                      /* for something like xmlns:abc="w3.pretend.org"
               	 	 *  the      uri is the value, that is why we pass it in the
               	 	 * value, or 5th slot of addAttributeAlways()
                   	 */
                      addAttributeAlways(XMLNS_URI, prefix, name,"CDATA",uri);
                  }
              }
          }
          return pushed;
      }
          
  
      /**
       * @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int)
       */
      public void comment(char[] arg0, int arg1, int arg2) throws SAXException
      {
          flushPending();
          if (m_lexHandler != null)
              m_lexHandler.comment(arg0, arg1, arg2);
              
          super.fireCommentEvent(arg0, arg1, arg2);
      }
  
      /**
       * @see org.xml.sax.ext.LexicalHandler#endCDATA()
       */
      public void endCDATA() throws SAXException
      {
          if (m_lexHandler != null)
              m_lexHandler.endCDATA();
      }
  
      /**
       * @see org.xml.sax.ext.LexicalHandler#endDTD()
       */
      public void endDTD() throws SAXException
      {
          if (m_lexHandler != null)
              m_lexHandler.endDTD();
      }
  
      /**
       * @see org.xml.sax.ext.LexicalHandler#startEntity(String)
       */
      public void startEntity(String arg0) throws SAXException
      {
          if (m_lexHandler != null)
              m_lexHandler.startEntity(arg0);
      }
  
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#characters(String)
       */
      public void characters(String chars) throws SAXException
      {
          final char[] arr = chars.toCharArray();
          this.characters(arr,0,arr.length);
      }
  
      /////////////////// from XSLTC //////////////
      public ToXMLSAXHandler(ContentHandler handler, String encoding)
      {
          super(handler, encoding);
  
          initCDATA();
          // initNamespaces();
          m_prefixMap = new NamespaceMappings();
      }
  
      public ToXMLSAXHandler(
          ContentHandler handler,
          LexicalHandler lex,
          String encoding)
      {
          super(handler, lex, encoding);
  
          initCDATA();
          //      initNamespaces();
          m_prefixMap = new NamespaceMappings();
      }
  
      /**
       * 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 elementNamespaceURI,
      String elementLocalName,
      String elementName) throws SAXException
      {
          startElement(
              elementNamespaceURI,elementLocalName,elementName, null);
  
  
      }
      public void startElement(String elementName) throws SAXException
      {
          startElement(null, null, elementName, null);
      }
  
  
      public void characters(char[] ch, int off, int len) throws SAXException
      {
          // System.out.println("SAXXMLOutput.characters ch = " + new String(ch, off, len));
  
          flushPending();
  
          if (m_cdataSectionStates.peekOrFalse())
          {
              startCDATA(ch, off, len);
          }
          else
          {
              m_saxHandler.characters(ch, off, len);
          }
  
  		// time to generate characters event
  		fireCharEvent(ch, off, len);
      }
      
  
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#endElement(String)
       */
      public void endElement(String elemName) throws SAXException
      {
          endElement(null, null, elemName);
      }    
  
  
      /**
       * 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 namespaceAfterStartElement(
          final String prefix,
          final String uri)
          throws SAXException
      {
          startPrefixMapping(prefix,uri,false);
      }
  
      /**
       *
       * @see org.xml.sax.ContentHandler#processingInstruction(String, String)
       * Send a processing instruction to the output document
       */
      public void processingInstruction(String target, String data)
          throws SAXException
      {
          flushPending();
  
          // Pass the processing instruction to the SAX handler
          m_saxHandler.processingInstruction(target, data);
  
          // we don't want to leave serializer to fire off this event,
          // so do it here.
          super.fireEscapingEvent(target, data);        
      }
  
      /**
       * 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 (m_prefixMap.popNamespace(prefix))
              {
                  m_saxHandler.endPrefixMapping(prefix);
                  return true;
              }
          }
          catch (SAXException e)
          {
              // falls through
          }
          return false;
      }
  
      public void startCDATA() throws SAXException
      {
  
          // Output start bracket - "<![CDATA["
          m_saxHandler.characters(BEGCDATA, 0, BEGCDATA.length);
          m_cdataTagOpen = true;
  
      }
  
      /**
       * 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["
          m_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] == '>')
              {
                  m_saxHandler.characters(ch, offset, i - offset);
                  m_saxHandler.characters(CNTCDATA, 0, CNTCDATA.length);
                  offset = i + 3;
                  i += 2; // Skip next chars ']' and '>'
              }
          }
  
          // Output the remaining characters
          if (offset < limit)
          {
              m_saxHandler.characters(ch, offset, limit - offset);
          }
          m_cdataTagOpen = true;
      }
  
      /**
      * @see org.xml.sax.ContentHandler#startElement(String, String, String, Attributes)
      */
      public void startElement(
      String namespaceURI,
      String localName,
      String name,
      Attributes atts)
          throws SAXException
      {
          flushPending();
          super.startElement(namespaceURI, localName, name, atts);
  
          // Handle document type declaration (for first element only)
           if (m_needToOutputDocTypeDecl)
           {
               String doctypeSystem = getDoctypeSystem();
               if (doctypeSystem != null && m_lexHandler != null)
               {
                   String doctypePublic = getDoctypePublic();
                   if (doctypeSystem != null)
                       m_lexHandler.startDTD(
                           name,
                           doctypePublic,
                           doctypeSystem);
               }
               m_needToOutputDocTypeDecl = false;
           }
  
          m_currentElemDepth++; // current element is one element deeper
  
          // ensurePrefixIsDeclared depends on the current depth, so
          // the previous increment is necessary where it is.
          if (namespaceURI != null)
              ensurePrefixIsDeclared(namespaceURI, name);
  
          // remember for later
          m_elementLocalName = localName;  // null if not known yet
          m_elementURI = namespaceURI;     // null if not known yet
          m_elementName = name;            // required 
  
          // add the attributes to the collected ones
          if (atts != null)
              addAttributes(atts);
  
          m_startTagOpen = true;
           
          // do we really need this CDATA section state?
          pushCdataSectionState();
     
      }
   
      private void ensurePrefixIsDeclared(String ns, String rawName)
          throws org.xml.sax.SAXException
      {
  
          if (ns != null && ns.length() > 0)
          {
              int index;
              String prefix =
                  (index = rawName.indexOf(":")) < 0
                      ? ""
                      : rawName.substring(0, index);
  
              if (null != prefix)
              {
                  String foundURI = m_prefixMap.lookupNamespace(prefix);
  
                  if ((null == foundURI) || !foundURI.equals(ns))
                  {
                      this.startPrefixMapping(prefix, ns, false);
  
                      // Bugzilla1133: Generate attribute as well as namespace event.
                      // SAX does expect both.
                      this.addAttributeAlways(
                          "http://www.w3.org/2000/xmlns/",
                          prefix,
                          "xmlns" + (prefix.length() == 0 ? "" : ":") + prefix,
                          "CDATA",
                          ns);
                  }
  
              }
          }
      }
      /**
       * Adds the given attribute to the set of attributes, and also makes sure
       * that the needed prefix/uri mapping is declared, but only if there is a
       * currently open element.
       * 
       * @param uri the URI of the attribute
       * @param localName the local name of the attribute
       * @param rawName    the qualified name of the attribute
       * @param type the type of the attribute (probably CDATA)
       * @param value the value of the attribute
       * @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
       */
      public void addAttribute(
          String uri,
          String localName,
          String rawName,
          String type,
          String value)
          throws SAXException
      {      
          if (m_startTagOpen)
          {
              ensurePrefixIsDeclared(uri, rawName);
              addAttributeAlways(uri, localName, rawName, type, value);
          }
  
      }    
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/ToXMLStream.java
  
  Index: ToXMLStream.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 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.xml.serializer;
  
  import java.io.IOException;
  
  import javax.xml.transform.ErrorListener;
  import javax.xml.transform.Result;
  import javax.xml.transform.Transformer;
  import javax.xml.transform.TransformerException;
  
  import org.apache.xml.res.XMLErrorResources;
  import org.apache.xml.res.XMLMessages;
  import org.xml.sax.SAXException;
  
  /**
   * @author minchau
   *
   */
  
  public class ToXMLStream extends ToStream
  {
  
      /**
       * remembers if we need to write out "]]>" to close the CDATA
       */
      private boolean m_cdataTagOpen = false;
  
  
      /**
       * Map that tells which XML characters should have special treatment, and it
       *  provides character to entity name lookup.
       */
      protected static CharInfo m_xmlcharInfo =
  //      new CharInfo(CharInfo.XML_ENTITIES_RESOURCE);
          CharInfo.getCharInfo(CharInfo.XML_ENTITIES_RESOURCE);
  
      /**
       * Default constructor.
       */
      public ToXMLStream()
      {
          m_charInfo = m_xmlcharInfo;
  
          initCDATA();
          // initialize namespaces
          m_prefixMap = new NamespaceMappings();
  
      }
  
      /**
       * Copy properties from another SerializerToXML.
       *
       * @param xmlListener non-null reference to a SerializerToXML object.
       */
      public void CopyFrom(ToXMLStream xmlListener)
      {
  
          m_writer = xmlListener.m_writer;
  
  
          // m_outputStream = xmlListener.m_outputStream;
          String encoding = xmlListener.getEncoding();
          setEncoding(encoding);
  
          setOmitXMLDeclaration(xmlListener.getOmitXMLDeclaration());
  
          m_startTagOpen = xmlListener.m_startTagOpen;
  
          // m_lineSep = xmlListener.m_lineSep;
          // m_lineSepLen = xmlListener.m_lineSepLen;
          m_ispreserve = xmlListener.m_ispreserve;
          m_preserves = xmlListener.m_preserves;
          m_isprevtext = xmlListener.m_isprevtext;
          m_doIndent = xmlListener.m_doIndent;
          m_currentElemDepth = xmlListener.m_currentElemDepth;
          setIndentAmount(xmlListener.getIndentAmount());
          m_startNewLine = xmlListener.m_startNewLine;
          m_needToOutputDocTypeDecl = xmlListener.m_needToOutputDocTypeDecl;
          setDoctypeSystem(xmlListener.getDoctypeSystem());
          setDoctypePublic(xmlListener.getDoctypePublic());        
          setStandalone(xmlListener.getStandalone());
          setMediaType(xmlListener.getMediaType());
          m_maxCharacter = xmlListener.m_maxCharacter;
          m_spaceBeforeClose = xmlListener.m_spaceBeforeClose;
          m_cdataStartCalled = xmlListener.m_cdataStartCalled;
  
      }
  
      /**
       * Receive notification of the beginning of a document.
       *
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       *
       * @throws org.xml.sax.SAXException
       */
      public void startDocumentInternal() throws org.xml.sax.SAXException
      {
  
          if (m_needToCallStartDocument)
          { 
              super.startDocumentInternal();
              m_needToCallStartDocument = false;
  
              if (m_inEntityRef)
                  return;
  
              m_needToOutputDocTypeDecl = true;
              m_startNewLine = false;
  
              if (getOmitXMLDeclaration() == false)
              {
                  String encoding = Encodings.getMimeEncoding(getEncoding());
                  String version = getVersion();
                  if (version == null)
                      version = "1.0";
                  String standalone;
  
                  if (m_standaloneWasSpecified)
                  {
                      standalone = " standalone=\"" + getStandalone() + "\"";
                  }
                  else
                  {
                      standalone = "";
                  }
  
                  try
                  {
                      m_writer.write("<?xml version=\"");
                      m_writer.write(version);
                      m_writer.write("\" encoding=\"");
                      m_writer.write(encoding);
                      m_writer.write('\"');
                      m_writer.write(standalone);
                      m_writer.write("?>");
                      m_writer.write(m_lineSep, 0, m_lineSepLen);
                  } 
                  catch(IOException e)
                  {
                      throw new SAXException(e);
                  }
  
              }
          }
      }
  
      /**
       * Receive notification of the end of a document.
       *
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       *
       * @throws org.xml.sax.SAXException
       */
      public void endDocument() throws org.xml.sax.SAXException
      {
          flushPending();
          if (m_doIndent && !m_isprevtext)
          {
              try
              {
              outputLineSep();
              }
              catch(IOException e)
              {
                  throw new SAXException(e);
              }
          }
  
          flushWriter();
          super.fireEndDoc();
      }
  
      /**
       * Starts a whitespace preserving section. All characters printed
       * within a preserving section are printed without indentation and
       * without consolidating multiple spaces. This is equivalent to
       * the <tt>xml:space=&quot;preserve&quot;</tt> attribute. Only XML
       * and HTML serializers need to support this method.
       * <p>
       * The contents of the whitespace preserving section will be delivered
       * through the regular <tt>characters</tt> event.
       *
       * @throws org.xml.sax.SAXException
       */
      public void startPreserving() throws org.xml.sax.SAXException
      {
  
          // Not sure this is really what we want.  -sb
          m_preserves.push(true);
  
          m_ispreserve = true;
      }
  
      /**
       * Ends a whitespace preserving section.
       *
       * @see #startPreserving
       *
       * @throws org.xml.sax.SAXException
       */
      public void endPreserving() throws org.xml.sax.SAXException
      {
  
          // Not sure this is really what we want.  -sb
          m_ispreserve = m_preserves.isEmpty() ? false : m_preserves.pop();
      }
  
      /**
       * Receive notification of a processing instruction.
       *
       * @param target The processing instruction target.
       * @param data The processing instruction data, or null if
       *        none was supplied.
       * @throws org.xml.sax.SAXException Any SAX exception, possibly
       *            wrapping another exception.
       *
       * @throws org.xml.sax.SAXException
       */
      public void processingInstruction(String target, String data)
          throws org.xml.sax.SAXException
      {
          if (m_inEntityRef)
              return;
          
          flushPending();   
  
          if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING))
          {
              startNonEscaping();
          }
          else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING))
          {
              endNonEscaping();
          }
          else
          {
              try
              {
                  if (m_startTagOpen)
                      closeStartTag();
  
                  if (shouldIndent())
                      indent();
  
                  m_writer.write('<');
                  m_writer.write('?');
                  m_writer.write(target);
  
                  if (data.length() > 0
                      && !Character.isSpaceChar(data.charAt(0)))
                      m_writer.write(' ');
  
                  int indexOfQLT = data.indexOf("?>");
  
                  if (indexOfQLT >= 0)
                  {
  
                      // See XSLT spec on error recovery of "?>" in PIs.
                      if (indexOfQLT > 0)
                      {
                          m_writer.write(data.substring(0, indexOfQLT));
                      }
  
                      m_writer.write("? >"); // add space between.
  
                      if ((indexOfQLT + 2) < data.length())
                      {
                          m_writer.write(data.substring(indexOfQLT + 2));
                      }
                  }
                  else
                  {
                      m_writer.write(data);
                  }
  
                  m_writer.write('?');
                  m_writer.write('>');
  
                  // Always output a newline char if not inside of an
                  // element. The whitespace is not significant in that
                  // case.
                  if (m_currentElemDepth <= 0)
                      m_writer.write(m_lineSep, 0, m_lineSepLen);
  
                  m_startNewLine = true;
              }
              catch(IOException e)
              {
                  throw new SAXException(e);
              }
          }
          super.fireEscapingEvent(target, data);        
      }
  
      /**
       * Receive notivication of a entityReference.
       *
       * @param name The name of the entity.
       *
       * @throws org.xml.sax.SAXException
       */
      public void entityReference(String name) throws org.xml.sax.SAXException
      {
          if (m_startTagOpen)
          {
              closeStartTag();
              m_startTagOpen = false;
          }
  
          try
          {
              if (shouldIndent())
                  indent();
  
              m_writer.write("&");
              m_writer.write(name);
              m_writer.write(";");
          }
          catch(IOException e)
          {
              throw new SAXException(e);
          }
          super.fireEntityReference(name);            
      }
  
  
      public void addAttribute(
          String uri,
          String localName,
          String rawName,
          String type,
          String value)
          throws SAXException
      {
          if (m_startTagOpen)
          {
              if (!rawName.startsWith("xmlns"))
              {
                  String prefixUsed =
                      ensureAttributesNamespaceIsDeclared(
                          uri,
                          localName,
                          rawName);
                  if (prefixUsed != null
                      && rawName != null
                      && !rawName.startsWith(prefixUsed))
                  {
                      // use a different raw name, with the prefix used in the
                      // generated namespace declaration
                      rawName = prefixUsed + ":" + localName;
  
                  }
              }
              addAttributeAlways(uri, localName, rawName, type, value);
          }
          else
          {
              /*
               * The startTag is closed, yet we are adding an attribute?
               *
               * Section: 7.1.3 Creating Attributes Adding an attribute to an
               * element after a PI (for example) has been added to it is an
               * error. The attributes can be ignored. The spec doesn't explicitly
               * say this is disallowed, as it does for child elements, but it
               * makes sense to have the same treatment.
               *
               * We choose to ignore the attribute which is added too late.
               */
              // Generate a warning of the ignored attributes
  
              // Create the warning message
              String msg = XMLMessages.createXMLMessage(
                      XMLErrorResources.ER_ILLEGAL_ATTRIBUTE_POSITION,new Object[]{ localName });
  
              try {
                  // Prepare to issue the warning message
                  Transformer tran = super.getTransformer();
                  ErrorListener errHandler = tran.getErrorListener();
  
  
                  // Issue the warning message
                  if (null != errHandler && m_sourceLocator != null)
                    errHandler.warning(new TransformerException(msg, m_sourceLocator));
                  else
                    System.out.println(msg);
                  }
              catch (Exception e){}             
          }
      }
  
      /**
       * This method escapes special characters used in attribute values
       * It is stolen from XSLTC
       */
      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(ENTITY_AMP);
                      offset = i + 1;
                      break;
                  case '"' :
                      result.append(ch, offset, i - offset).append(ENTITY_QUOT);
                      offset = i + 1;
                      break;
                  case '<' :
                      result.append(ch, offset, i - offset).append(ENTITY_LT);
                      offset = i + 1;
                      break;
                  case '>' :
                      result.append(ch, offset, i - offset).append(ENTITY_GT);
                      offset = i + 1;
                      break;
                  case '\n' :
                      result.append(ch, offset, i - offset).append(ENTITY_CRLF);
                      offset = i + 1;
                      break;
              }
          }
  
          if (offset < limit)
          {
              result.append(ch, offset, limit - offset);
          }
          return result.toString();
      }
  
      /**
       * @see org.apache.xml.serializer.ExtendedContentHandler#endElement(String)
       */
      public void endElement(String elemName) throws SAXException
      {
          endElement(null, null, elemName);
      }
  
      /**
       * From XSLTC
       * Related to startPrefixMapping ???
       */
      public void namespaceAfterStartElement(
          final String prefix,
          final String uri)
          throws SAXException
      {
  
          // hack for XSLTC with finding URI for default namespace
          if (m_elementURI == null)
          {
              String prefix1 = getPrefixPart(m_elementName);
              if (prefix1 == null && EMPTYSTRING.equals(prefix))
              {
                  // the elements URI is not known yet, and it
                  // doesn't have a prefix, and we are currently
                  // setting the uri for prefix "", so we have
                  // the uri for the element... lets remember it
                  m_elementURI = uri;
              }
          }            
          startPrefixMapping(prefix,uri,false);
          return;
  
      }
  
      /**
       * From XSLTC
       * 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 (m_prefixMap.pushNamespace(prefix, uri, m_currentElemDepth))
              {
                  startPrefixMapping(prefix, uri);
                  return true;
              }
          }
          catch (SAXException e)
          {
              // falls through
          }
          return false;
      }
  
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/TransformStateSetter.java
  
  Index: TransformStateSetter.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import javax.xml.transform.Transformer;
  
  import org.w3c.dom.Node;
  /**
   * This interface is meant to be used by a base interface to
   * TransformState, but which as only the setters which have non Xalan
   * specific types in their signature, so that there are no dependancies
   * of the serializer on Xalan.
   * 
   * @see org.apache.xalan.transformer.TransformState
   */
  public interface TransformStateSetter
  {
  
  
    /**
     * Set the current node.
     *
     * @param Node The current node.
     */
    void setCurrentNode(Node n);
  
    /**
     * Reset the state on the given transformer object.
     *
     * @param Transformer
     */
    void resetState(Transformer transformer);
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/WriterToASCI.java
  
  Index: WriterToASCI.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.Writer;
  
  
  
  /**
   * This class writes ASCII to a byte stream as quickly as possible.  For the
   * moment it does not do buffering, though I reserve the right to do some
   * buffering down the line if I can prove that it will be faster even if the
   * output stream is buffered.
   */
  public class WriterToASCI extends Writer
  {
  
    /** The byte stream to write to.  */
    private final OutputStream m_os;
  
    /**
     * Create an unbuffered ASCII writer.
     *
     *
     * @param os The byte stream to write to.
     */
    public WriterToASCI(OutputStream os)
    {
      m_os = os;
    }
  
    /**
     * Write a portion of an array of characters.
     *
     * @param  chars  Array of characters
     * @param  start   Offset from which to start writing characters
     * @param  length   Number of characters to write
     *
     * @exception  IOException  If an I/O error occurs
     *
     * @throws java.io.IOException
     */
    public void write(char chars[], int start, int length)
            throws java.io.IOException
    {
  
      int n = length+start;
  
      for (int i = start; i < n; i++)
      {
        m_os.write(chars[i]);
      }
    }
  
    /**
     * Write a single character.  The character to be written is contained in
     * the 16 low-order bits of the given integer value; the 16 high-order bits
     * are ignored.
     *
     * <p> Subclasses that intend to support efficient single-character output
     * should override this method.
     *
     * @param c  int specifying a character to be written.
     * @exception  IOException  If an I/O error occurs
     */
    public void write(int c) throws IOException
    {
      m_os.write(c);
    }
  
    /**
     * Write a string.
     *
     * @param  str  String to be written
     *
     * @exception  IOException  If an I/O error occurs
     */
    public void write(String s) throws IOException
    {
      int n = s.length();
      for (int i = 0; i < n; i++)
      {
        m_os.write(s.charAt(i));
      }
    }
  
    /**
     * Flush the stream.  If the stream has saved any characters from the
     * various write() methods in a buffer, write them immediately to their
     * intended destination.  Then, if that destination is another character or
     * byte stream, flush it.  Thus one flush() invocation will flush all the
     * buffers in a chain of Writers and OutputStreams.
     *
     * @exception  IOException  If an I/O error occurs
     */
    public void flush() throws java.io.IOException
    {
      m_os.flush();
    }
  
    /**
     * Close the stream, flushing it first.  Once a stream has been closed,
     * further write() or flush() invocations will cause an IOException to be
     * thrown.  Closing a previously-closed stream, however, has no effect.
     *
     * @exception  IOException  If an I/O error occurs
     */
    public void close() throws java.io.IOException
    {
      m_os.close();
    }
  
    /**
     * Get the output stream where the events will be serialized to.
     *
     * @return reference to the result stream, or null of only a writer was
     * set.
     */
    public OutputStream getOutputStream()
    {
      return m_os;
    }
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/WriterToUTF8.java
  
  Index: WriterToUTF8.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.UnsupportedEncodingException;
  import java.io.Writer;
  
  /**
   * This class writes ASCII to a byte stream as quickly as possible.  For the
   * moment it does not do buffering, though I reserve the right to do some
   * buffering down the line if I can prove that it will be faster even if the
   * output stream is buffered.
   */
  public class WriterToUTF8 extends Writer
  {
  
      /** A flag to force flush output to System.out when stepping with a debugger (debug only!) */
      private static final boolean DEBUG_OUT = false;
  
      /** The byte stream to write to. */
      private final OutputStream m_os;
  
      /**
       * Create an unbuffered UTF-8 writer.
       *
       *
       * @param os The byte stream to write to.
       *
       * @throws UnsupportedEncodingException
       */
      public WriterToUTF8(OutputStream os) throws UnsupportedEncodingException
      {
          m_os = os;
      }
  
      /**
       * Write a single character.  The character to be written is contained in
       * the 16 low-order bits of the given integer value; the 16 high-order bits
       * are ignored.
       *
       * <p> Subclasses that intend to support efficient single-character output
       * should override this method.
       *
       * @param c  int specifying a character to be written.
       * @exception  IOException  If an I/O error occurs
       */
      public void write(final int c) throws IOException
      {
  
          if (c < 0x80)
              m_os.write(c);
          else if (c < 0x800)
          {
              m_os.write(0xc0 + (c >> 6));
              m_os.write(0x80 + (c & 0x3f));
          }
          else
          {
              m_os.write(0xe0 + (c >> 12));
              m_os.write(0x80 + ((c >> 6) & 0x3f));
              m_os.write(0x80 + (c & 0x3f));
          }
  
          if (DEBUG_OUT)
          {
              if (c < 0x80)
              {
                  char ch = (char) c;
                  System.out.print(ch);
              }
              else if (c < 0x800)
              {
                  System.out.print(0xc0 + (c >> 6));
                  System.out.print(0x80 + (c & 0x3f));
              }
              else
              {
                  System.out.print(0xe0 + (c >> 12));
                  System.out.print(0x80 + ((c >> 6) & 0x3f));
                  System.out.print(0x80 + (c & 0x3f));
              }
              System.out.flush();
          }
          return;
      }
  
      /**
       * Write a portion of an array of characters.
       *
       * @param  chars  Array of characters
       * @param  start   Offset from which to start writing characters
       * @param  length   Number of characters to write
       *
       * @exception  IOException  If an I/O error occurs
       *
       * @throws java.io.IOException
       */
      public void write(final char chars[], final int start, final int length)
          throws java.io.IOException
      {
  
          final OutputStream os = m_os;
  
          int n = length + start;
          for (int i = start; i < n; i++)
          {
              final char c = chars[i];
  
              if (c < 0x80)
                  os.write(c);
              else if (c < 0x800)
              {
                  os.write(0xc0 + (c >> 6));
                  os.write(0x80 + (c & 0x3f));
              }
              else
              {
                  os.write(0xe0 + (c >> 12));
                  os.write(0x80 + ((c >> 6) & 0x3f));
                  os.write(0x80 + (c & 0x3f));
              }
          }
  
          if (DEBUG_OUT)
          {
              for (int i = start; i < n; i++)
              {
                  final char c = chars[i];
  
                  if (c < 0x80)
                      System.out.print(c);
                  else if (c < 0x800)
                  {
                      System.out.print(0xc0 + (c >> 6));
                      System.out.print(0x80 + (c & 0x3f));
                  }
                  else
                  {
                      System.out.print(0xe0 + (c >> 12));
                      System.out.print(0x80 + ((c >> 6) & 0x3f));
                      System.out.print(0x80 + (c & 0x3f));
                  }
              }
              System.out.flush();
          }
          return;
      }
  
      /**
       * Write a string.
       *
       * @param  s  String to be written
       *
       * @exception  IOException  If an I/O error occurs
       */
      public void write(final String s) throws IOException
      {
  
          final int n = s.length();
          final OutputStream os = m_os;
  
          for (int i = 0; i < n; i++)
          {
              final char c = s.charAt(i);
  
              if (c < 0x80)
                  os.write(c);
              else if (c < 0x800)
              {
                  os.write(0xc0 + (c >> 6));
                  os.write(0x80 + (c & 0x3f));
              }
              else
              {
                  os.write(0xe0 + (c >> 12));
                  os.write(0x80 + ((c >> 6) & 0x3f));
                  os.write(0x80 + (c & 0x3f));
              }
          }
  
          if (DEBUG_OUT)
          {
  
              for (int i = 0; i < n; i++)
              {
                  final char c = s.charAt(i);
  
                  if (c < 0x80)
                      System.out.print(c);
                  else if (c < 0x800)
                  {
                      System.out.print(0xc0 + (c >> 6));
                      System.out.print(0x80 + (c & 0x3f));
                  }
                  else
                  {
                      System.out.print(0xe0 + (c >> 12));
                      System.out.print(0x80 + ((c >> 6) & 0x3f));
                      System.out.print(0x80 + (c & 0x3f));
                  }
              }
              System.out.flush();
          }
          return;
      }
  
      /**
       * Flush the stream.  If the stream has saved any characters from the
       * various write() methods in a buffer, write them immediately to their
       * intended destination.  Then, if that destination is another character or
       * byte stream, flush it.  Thus one flush() invocation will flush all the
       * buffers in a chain of Writers and OutputStreams.
       *
       * @exception  IOException  If an I/O error occurs
       *
       * @throws java.io.IOException
       */
      public void flush() throws java.io.IOException
      {
          m_os.flush();
      }
  
      /**
       * Close the stream, flushing it first.  Once a stream has been closed,
       * further write() or flush() invocations will cause an IOException to be
       * thrown.  Closing a previously-closed stream, however, has no effect.
       *
       * @exception  IOException  If an I/O error occurs
       *
       * @throws java.io.IOException
       */
      public void close() throws java.io.IOException
      {
          m_os.close();
      }
  
      /**
       * Get the output stream where the events will be serialized to.
       *
       * @return reference to the result stream, or null of only a writer was
       * set.
       */
      public OutputStream getOutputStream()
      {
          return m_os;
      }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/WriterToUTF8Buffered.java
  
  Index: WriterToUTF8Buffered.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2003 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) 1999, Lotus
   * Development Corporation., http://www.lotus.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.UnsupportedEncodingException;
  import java.io.Writer;
  
  
  /**
   * This class writes ASCII to a byte stream as quickly as possible.  For the
   * moment it does not do buffering, though I reserve the right to do some
   * buffering down the line if I can prove that it will be faster even if the
   * output stream is buffered.
   */
  public final class WriterToUTF8Buffered extends Writer
  {
      
    /** number of characters that the buffer can hold.
     * This is a fixed constant is used rather than buf.lenght for performance.
     */
    private static final int buf_length=16*1024;
    
    /** The byte stream to write to. (sc & sb remove final to compile in JDK 1.1.8) */
    private final OutputStream m_os;
  
    /**
     * The internal buffer where data is stored.
     * (sc & sb remove final to compile in JDK 1.1.8)
     */
    private final byte buf[];
  
    /**
     * The number of valid bytes in the buffer. This value is always
     * in the range <tt>0</tt> through <tt>buf.length</tt>; elements
     * <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid
     * byte data.
     */
    private int count;
  
    /**
     * Create an buffered UTF-8 writer.
     *
     *
     * @param   out    the underlying output stream.
     *
     * @throws UnsupportedEncodingException
     */
    public WriterToUTF8Buffered(OutputStream out)
            throws UnsupportedEncodingException
    {
        m_os = out;
        // get 3 extra bytes to make buffer overflow checking simpler and faster
        // we won't have to keep checking for a few extra characters
        buf = new byte[buf_length + 3];
        count = 0;
        
  //      the old body of this constructor, before the buffersize was changed to a constant      
  //      this(out, 8*1024);
    }
  
    /**
     * Create an buffered UTF-8 writer to write data to the
     * specified underlying output stream with the specified buffer
     * size.
     *
     * @param   out    the underlying output stream.
     * @param   size   the buffer size.
     * @exception IllegalArgumentException if size <= 0.
     */
  //  public WriterToUTF8Buffered(final OutputStream out, final int size)
  //  {
  //
  //    m_os = out;
  //
  //    if (size <= 0)
  //    {
  //      throw new IllegalArgumentException(
  //        SerializerMessages.createMessage(SerializerErrorResources.ER_BUFFER_SIZE_LESSTHAN_ZERO, null)); //"Buffer size <= 0");
  //    }
  //
  //    buf = new byte[size];
  //    count = 0;
  //  }
  
    /**
     * Write a single character.  The character to be written is contained in
     * the 16 low-order bits of the given integer value; the 16 high-order bits
     * are ignored.
     *
     * <p> Subclasses that intend to support efficient single-character output
     * should override this method.
     *
     * @param c  int specifying a character to be written.
     * @exception  IOException  If an I/O error occurs
     */
    public void write(final int c) throws IOException
    {
      
      /* If we are close to the end of the buffer then flush it.
       * Remember the buffer can hold a few more characters than buf_length
       */ 
      if (count >= buf_length)
          flushBuffer();
  
      if (c < 0x80)
      {
         buf[count++] = (byte) (c);
      }
      else if (c < 0x800)
      {
        buf[count++] = (byte) (0xc0 + (c >> 6));
        buf[count++] = (byte) (0x80 + (c & 0x3f));
      }
      else
      {
        buf[count++] = (byte) (0xe0 + (c >> 12));
        buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
        buf[count++] = (byte) (0x80 + (c & 0x3f));
      }
    }
  
    /**
     * Write a portion of an array of characters.
     *
     * @param  chars  Array of characters
     * @param  start   Offset from which to start writing characters
     * @param  length   Number of characters to write
     *
     * @exception  IOException  If an I/O error occurs
     *
     * @throws java.io.IOException
     */
    private final void writeDirect(
            final char chars[], final int start, final int length)
              throws java.io.IOException
    {
  
      final OutputStream os = m_os;
  
      final int n = length+start;
      for (int i = start; i < n; i++)
      {
        final char c = chars[i];
  
        if (c < 0x80)
          os.write(c);
        else if (c < 0x800)
        {
          os.write(0xc0 + (c >> 6));
          os.write(0x80 + (c & 0x3f));
        }
        else
        {
          os.write(0xe0 + (c >> 12));
          os.write(0x80 + ((c >> 6) & 0x3f));
          os.write(0x80 + (c & 0x3f));
        }
      }
    }
  
    /**
     * Write a string.
     *
     * @param  s  String to be written
     *
     * @exception  IOException  If an I/O error occurs
     */
    private final void writeDirect(final String s) throws IOException
    {
  
      final int n = s.length();
      final OutputStream os = m_os;
  
      for (int i = 0; i < n; i++)
      {
        final char c = s.charAt(i);
  
        if (c < 0x80)
          os.write(c);
        else if (c < 0x800)
        {
          os.write(0xc0 + (c >> 6));
          os.write(0x80 + (c & 0x3f));
        }
        else
        {
          os.write(0xe0 + (c >> 12));
          os.write(0x80 + ((c >> 6) & 0x3f));
          os.write(0x80 + (c & 0x3f));
        }
      }
    }
  
    /**
     * Write a portion of an array of characters.
     *
     * @param  chars  Array of characters
     * @param  start   Offset from which to start writing characters
     * @param  length   Number of characters to write
     *
     * @exception  IOException  If an I/O error occurs
     *
     * @throws java.io.IOException
     */
    public void write(final char chars[], final int start, final int length)
            throws java.io.IOException
    {
  
      // We multiply the length by three since this is the maximum length
      // of the characters that we can put into the buffer.  It is possible
      // for each Unicode character to expand to three bytes.
  
      int lengthx3 = (length << 1) + length;
  
      if (lengthx3 >= buf_length)
      {
  
        /* If the request length exceeds the size of the output buffer,
           flush the output buffer and then write the data directly.
           In this way buffered streams will cascade harmlessly. */
        flushBuffer();
        writeDirect(chars, start, length);
  
        return;
      }
  
      if (lengthx3 > buf_length - count)
      {
        flushBuffer();
      }
  
      final OutputStream os = m_os;
      final int n = length+start;
      for (int i = start; i < n; i++)
      {
        final char c = chars[i];
  
        if (c < 0x80)
          buf[count++] = (byte) (c);
        else if (c < 0x800)
        {
          buf[count++] = (byte) (0xc0 + (c >> 6));
          buf[count++] = (byte) (0x80 + (c & 0x3f));
        }
        else
        {
          buf[count++] = (byte) (0xe0 + (c >> 12));
          buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
          buf[count++] = (byte) (0x80 + (c & 0x3f));
        }
      }
  
    }
  
    /**
     * Write a string.
     *
     * @param  s  String to be written
     *
     * @exception  IOException  If an I/O error occurs
     */
    public void write(final String s) throws IOException
    {
  
      final int length = s.length();
  
      // We multiply the length by three since this is the maximum length
      // of the characters that we can put into the buffer.  It is possible
      // for each Unicode character to expand to three bytes.
  
      int lengthx3 = (length << 1) + length;
  
      if (lengthx3 >= buf_length)
      {
  
        /* If the request length exceeds the size of the output buffer,
           flush the output buffer and then write the data directly.
           In this way buffered streams will cascade harmlessly. */
        flushBuffer();
        writeDirect(s);
  
        return;
      }
  
      if (lengthx3 > buf_length - count)
      {
        flushBuffer();
      }
  
      final OutputStream os = m_os;
  
      for (int i = 0; i < length; i++)
      {
        final char c = s.charAt(i);
  
        if (c < 0x80)
          buf[count++] = (byte) (c);
        else if (c < 0x800)
        {
          buf[count++] = (byte) (0xc0 + (c >> 6));
          buf[count++] = (byte) (0x80 + (c & 0x3f));
        }
        else
        {
          buf[count++] = (byte) (0xe0 + (c >> 12));
          buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
          buf[count++] = (byte) (0x80 + (c & 0x3f));
        }
      }
  
    }
  
    /**
     * Flush the internal buffer
     *
     * @throws IOException
     */
    public void flushBuffer() throws IOException
    {
  
      if (count > 0)
      {
        m_os.write(buf, 0, count);
  
        count = 0;
      }
    }
  
    /**
     * Flush the stream.  If the stream has saved any characters from the
     * various write() methods in a buffer, write them immediately to their
     * intended destination.  Then, if that destination is another character or
     * byte stream, flush it.  Thus one flush() invocation will flush all the
     * buffers in a chain of Writers and OutputStreams.
     *
     * @exception  IOException  If an I/O error occurs
     *
     * @throws java.io.IOException
     */
    public void flush() throws java.io.IOException
    {
      flushBuffer();
      m_os.flush();
    }
  
    /**
     * Close the stream, flushing it first.  Once a stream has been closed,
     * further write() or flush() invocations will cause an IOException to be
     * thrown.  Closing a previously-closed stream, however, has no effect.
     *
     * @exception  IOException  If an I/O error occurs
     *
     * @throws java.io.IOException
     */
    public void close() throws java.io.IOException
    {
      flushBuffer();
      m_os.close();
    }
  
    /**
     * Get the output stream where the events will be serialized to.
     *
     * @return reference to the result stream, or null of only a writer was
     * set.
     */
    public OutputStream getOutputStream()
    {
      return m_os;
    }
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/XMLEntities.res
  
  Index: XMLEntities.res
  ===================================================================
  # $Id: XMLEntities.res,v 1.1 2003/04/01 19:24:54 mkwan Exp $
  #
  # @version $Revision: 1.1 $ $Date: 2003/04/01 19:24:54 $
  # @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
  # This file must be encoded in UTF-8; see org.apache.xml.serializer.CharInfo
  #
  # Character entity references for markup-significant
  #
  quot 34
  amp 38
  lt 60
  gt 62
  
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/XSLOutputAttributes.java
  
  Index: XSLOutputAttributes.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2003 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) 2003, International Business
   * Machines, Inc., http://www.ibm.com.  For more information on the Apache
   * Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.xml.serializer;
  
  import java.util.Vector;
  
  /**
   * This interface has methods associated with the XSLT xsl:output attribues
   * specified in the stylesheet that effect the format of the document output.
   * 
   * In an XSLT stylesheet these attributes appear for example as:
   * <pre>
   * <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/> 
   * </pre>
   * The xsl:output attributes covered in this interface are:
   * <pre>
   * version
   * encoding
   * omit-xml-declarations
   * standalone
   * doctype-public
   * doctype-system
   * cdata-section-elements
   * indent
   * media-type
   * </pre>
   * 
   * The one attribute not covered in this interface is <code>method</code> as
   * this value is implicitly chosen by the serializer that is created, for
   * example ToXMLStream vs. ToHTMLStream or another one.
   */
  public interface XSLOutputAttributes
  {
      /**
       * Returns the previously set value of the value to be used as the public
       * identifier in the document type declaration (DTD).
       *
       *@return the public identifier to be used in the DOCTYPE declaration in the
       * output document.
       */
      public String getDoctypePublic();
      /**
       * Returns the previously set value of the value to be used
       * as the system identifier in the document type declaration (DTD).
       * @return the system identifier to be used in the DOCTYPE declaration in
       * the output document.
       *
       */ 
      public String getDoctypeSystem();
      /**
       * @return the character encoding to be used in the output document.
       */    
      public String getEncoding();
      /**
  	 * @return true if the output document should be indented to visually
  	 * indicate its structure.
       */    
      public boolean getIndent();
      
      /**
       * @return the number of spaces to indent for each indentation level.
       */
      public int getIndentAmount();
      /**
       * @return the mediatype the media-type or MIME type associated with the
       * output document.
       */    
      public String getMediaType();
      /**
       * @return true if the XML declaration is to be omitted from the output
       * document.
       */    
      public boolean getOmitXMLDeclaration();
      /**
        * @return a value of "yes" if the <code>standalone</code> delaration is to
        * be included in the output document.
        */    
      public String getStandalone();
      /**
       * @return the version of the output format.
       */    
      public String getVersion();
  
  
  
  
  
  
      /**
       * Sets the value coming from the xsl:output cdata-section-elements
       * stylesheet property.
       * 
       * This sets the elements whose text elements are to be output as CDATA
       * sections.
       * @param URI_and_localNames pairs of namespace URI and local names that
       * identify elements whose text elements are to be output as CDATA sections.
       * The namespace of the local element must be the given URI to match. The
       * qName is not given because the prefix does not matter, only the namespace
       * URI to which that prefix would map matters, so the prefix itself is not
       * relevant in specifying which elements have their text to be output as
       * CDATA sections.
       */
      public void setCdataSectionElements(Vector URI_and_localNames);
  
      /** Set the value coming from the xsl:output doctype-public and doctype-system stylesheet properties
       * @param system the system identifier to be used in the DOCTYPE declaration
       * in the output document.
       * @param pub the public identifier to be used in the DOCTYPE declaration in
       * the output document.
       */
      public void setDoctype(String system, String pub);
  
      /** Set the value coming from the xsl:output doctype-public stylesheet attribute.
        * @param doctype the public identifier to be used in the DOCTYPE
        * declaration in the output document.
        */
      public void setDoctypePublic(String doctype);
      /** Set the value coming from the xsl:output doctype-system stylesheet attribute.
        * @param doctype the system identifier to be used in the DOCTYPE
        * declaration in the output document.
        */
      public void setDoctypeSystem(String doctype);
      /**
       * Sets the character encoding coming from the xsl:output encoding stylesheet attribute.
       * @param encoding the character encoding
       */
      public void setEncoding(String encoding);
      /**
       * Sets the value coming from the xsl:output indent stylesheet
       * attribute.
       * @param indent true if the output document should be indented to visually
       * indicate its structure.
       */
      public void setIndent(boolean indent);
      /**
       * Sets the value coming from the xsl:output media-type stylesheet attribute.
       * @param mediatype the media-type or MIME type associated with the output
       * document.
       */
      public void setMediaType(String mediatype);
      /**
       * Sets the value coming from the xsl:output omit-xml-declaration stylesheet attribute
       * @param b true if the XML declaration is to be omitted from the output
       * document.
       */
      public void setOmitXMLDeclaration(boolean b);
      /**
       * Sets the value coming from the xsl:output standalone stylesheet attribute.
       * @param standalone a value of "yes" indicates that the
       * <code>standalone</code> delaration is to be included in the output
       * document.
       */
      public void setStandalone(String standalone);
      /**
       * Sets the value coming from the xsl:output version attribute.
       * @param version the version of the output format.
       */
      public void setVersion(String version);
  
  }
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/output_html.properties
  
  Index: output_html.properties
  ===================================================================
  #
  # Specify defaults when method="html".  These defaults use output_xml.properties 
  # as a base.
  #
  
  # XSLT properties do not need namespace qualification.
  method=html
  indent=yes
  media-type=text/html
  version=4.0
  
  # Xalan-specific output properties.  These can be overridden in the stylesheet 
  # assigning a xalan namespace.  For example:
  # <xsl:stylesheet version="1.0"
  #          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  #          xmlns:xalan="http://xml.apache.org/xalan">
  #  <xsl:output method="html" encoding="UTF-8"
  #              xalan:content-handler="MyContentHandler"/>
  #  ...
  # Note that the colon after the protocol needs to be escaped.
  {http\u003a//xml.apache.org/xalan}indent-amount=0
  {http\u003a//xml.apache.org/xalan}content-handler=org.apache.xml.serializer.ToHTMLStream
  {http\u003a//xml.apache.org/xalan}entities=org/apache/xml/serializer/HTMLEntities.res
  {http\u003a//xml.apache.org/xalan}use-url-escaping=yes
  {http\u003a//xml.apache.org/xalan}omit-meta-tag=no
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/output_text.properties
  
  Index: output_text.properties
  ===================================================================
  #
  # Specify defaults when method="text".
  #
  
  # XSLT properties do not need namespace qualification.
  method=text
  media-type=text/plain
  
  # Xalan-specific output properties.  These can be overridden in the stylesheet 
  # assigning a xalan namespace.  For example:
  # <xsl:stylesheet version="1.0"
  #          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  #          xmlns:xalan="http://xml.apache.org/xalan">
  #  <xsl:output method="html" encoding="UTF-8"
  #              xalan:content-handler="MyContentHandler"/>
  #  ...
  # Note that the colon after the protocol needs to be escaped.
  {http\u003a//xml.apache.org/xalan}content-handler=org.apache.xml.serializer.ToTextStream
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/output_unknown.properties
  
  Index: output_unknown.properties
  ===================================================================
  #
  # Specify defaults when no method="..." is specified.
  # This type of output will quickly switch to "xml" or "html"
  # depending on the first element name.
  #
  
  # XSLT properties do not need namespace qualification.
  method=xml
  version=1.0
  encoding=UTF-8
  indent=no
  omit-xml-declaration=no
  standalone=no
  media-type=text/xml
  
  # Xalan-specific output properties.  These can be overridden in the stylesheet 
  # assigning a xalan namespace.  For example:
  # <xsl:stylesheet version="1.0"
  #          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  #          xmlns:xalan="http://xml.apache.org/xalan">
  #  <xsl:output method="html" encoding="UTF-8"
  #              xalan:content-handler="MyContentHandler"/>
  #  ...
  # Note that the colon after the protocol needs to be escaped.
  {http\u003a//xml.apache.org/xalan}indent-amount=0
  {http\u003a//xml.apache.org/xalan}content-handler=org.apache.xml.serializer.ToUnknownStream
  
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/output_xml.properties
  
  Index: output_xml.properties
  ===================================================================
  #
  # Specify defaults when method="xml".  These defaults serve as a base for 
  # other defaults, such as output_html and output_text.
  #
  
  # XSLT properties do not need namespace qualification.
  method=xml
  version=1.0
  encoding=UTF-8
  indent=no
  omit-xml-declaration=no
  standalone=no
  media-type=text/xml
  
  # Xalan-specific output properties.  These can be overridden in the stylesheet 
  # assigning a xalan namespace.  For example:
  # <xsl:stylesheet version="1.0"
  #          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  #          xmlns:xalan="http://xml.apache.org/xalan">
  #  <xsl:output method="html" encoding="UTF-8"
  #              xalan:content-handler="MyContentHandler"/>
  #  ...
  # Note that the colon after the protocol needs to be escaped.
  {http\u003a//xml.apache.org/xalan}indent-amount=0
  {http\u003a//xml.apache.org/xalan}content-handler=org.apache.xml.serializer.ToXMLStream
  {http\u003a//xml.apache.org/xalan}entities=org/apache/xml/serializer/XMLEntities.res
  
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xml/serializer/package.html
  
  Index: package.html
  ===================================================================
  <html>
    <title>Xalan Serializer Package.</title>
    <body>
      <p>Processes SAX events into streams.</p>
      
      <p>The {@link org.apache.xml.serializer.SerializerFactory} is used to 
      create a {@link org.apache.xml.serializer.Serializer} from a set of 
      output properties (see {@link javax.xml.transform.OutputKeys}).</p>
      <p>{@link org.apache.xml.serializer.ToStream} acts as the main 
      baseclass for the Xalan serializer implementations.  
      {@link org.apache.xml.serializer.ToHTMLStream} derives from this 
      to implement HTML serialization.  
      {@link org.apache.xml.serializer.ToTextStream}
      implements plain text serialization.
      {@link org.apache.xml.serializer.ToXMLStream}
      implements XML serialization.
      </p>
      <p>XML mapping from characters to entity references is defined in 
      XMLEntities.res.  HTML entity reference mapping is defined in HTMLEntities.res.
      </p>
      <p>Encoding information is defined in {@link org.apache.xml.serializer.Encodings}.</p>
   </body>
  </html>
  
  
  
  
  

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