/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 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.xalan.serialize;

import java.io.Writer;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.IOException;

import java.util.Enumeration;
import java.util.Stack;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Properties;
import java.util.BitSet;

import org.xml.sax.*;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.ext.DeclHandler;

import org.w3c.dom.Node;

import org.apache.xalan.serialize.Serializer;
import org.apache.xalan.serialize.DOMSerializer;
import org.apache.xml.utils.QName;
import org.apache.xalan.templates.OutputProperties;
import org.apache.xml.utils.BoolStack;
import org.apache.xml.utils.TreeWalker;
import org.apache.xml.utils.WrappedRuntimeException;
import org.apache.xml.utils.SystemIDResolver;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.res.XSLMessages;
import org.apache.xpath.res.XPATHErrorResources;

import javax.xml.transform.Result;
import javax.xml.transform.OutputKeys;

/**
 * <meta name="usage" content="general"/>
 * SerializerToXML formats SAX-style events into XML.
 */
public class SerializerToXML
        implements ContentHandler, LexicalHandler, DeclHandler, Serializer,
                   DOMSerializer
{

  /**
   * The writer where the XML will be written.
   */
  protected Writer m_writer = null;

  /** True if we control the buffer, and we should flush the output on endDocument. */
  boolean m_shouldFlush = true;

  //  /** The output stream where the result stream is written. */
  //  protected OutputStream m_outputStream = System.out;

  /**
   * The character encoding.  Must match the encoding used for the printWriter.
   */
  protected String m_encoding = null;

  /**
   * Assume java encoding names are the same as the ISO encoding names if this is true.
   */
  static boolean javaEncodingIsISO = false;

  /**
   * Tells if we should write the XML declaration.
   */
  public boolean m_shouldNotWriteXMLHeader = false;

  /**
   * Tells the XML version, for writing out to the XML decl.
   */
  public String m_version = null;

  /**
   * A stack of Boolean objects that tell if the given element
   * has children.
   */
  protected BoolStack m_elemStack = new BoolStack();

  /** Stack to keep track of disabling output escaping. */
  protected BoolStack m_disableOutputEscapingStates = new BoolStack();

  /** True will be pushed, if characters should be in CDATA section blocks. */
  protected BoolStack m_cdataSectionStates = new BoolStack();

  /** List of QNames obtained from the xsl:output properties. */
  protected Vector m_cdataSectionNames = null;

  /** True if the current characters should be in CDATA blocks. */
  protected boolean m_inCData = false;

  /**
   * Tell if the character escaping should be disabled for the current state.
   *
   * @return true if the character escaping should be disabled.
   */
  protected boolean isEscapingDisabled()
  {
    return m_disableOutputEscapingStates.peekOrFalse();
  }

  /**
   * Tell if the characters in the current state should be put in
   * cdata section blocks.
   *
   * @return true if the characters in the current state should be put in
   * cdata section blocks.
   */
  protected boolean isCDataSection()
  {
    return m_inCData || m_cdataSectionStates.peekOrFalse();
  }

  /**
   * 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;

  /**
   * Output a system-dependent line break.
   *
   * @throws org.xml.sax.SAXException
   */
  protected final void outputLineSep() throws org.xml.sax.SAXException
  {

    try
    {
      m_writer.write(m_lineSep, 0, m_lineSepLen);
    }
    catch (IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /**
   * State flag to tell if preservation of whitespace
   * is important.
   */
  protected boolean m_ispreserve = false;

  /**
   * Stack to keep track of whether or not we need to
   * preserve whitespace.
   */
  protected BoolStack m_preserves = new BoolStack();

  /**
   * 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;

  /**
   * Flag to tell if indenting (pretty-printing) is on.
   */
  protected boolean m_doIndent = false;

  /**
   * Flag to keep track of the indent amount.
   */
  protected int m_currentIndent = 0;

  /**
   * Amount to indent.
   */
  public int m_indentAmount = 0;

  /**
   * Current level of indent.
   */
  protected int level = 0;

  /**
   * Flag to signal that a newline should be added.
   */
  boolean m_startNewLine;

  /**
   * 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 System ID for the doc type.
   */
  String m_doctypeSystem;

  /**
   * The public ID for the doc type.
   */
  String m_doctypePublic;

  /**
   * The standalone value for the doctype.
   */
  boolean m_standalone = false;

  /**
   * True if standalone was specified.
   */
  boolean m_standaloneWasSpecified = false;

  /**
   * The mediatype.  Not used right now.
   */
  String m_mediatype;

  /**
   * Tells if we're in an EntityRef event.
   */
  protected boolean m_inEntityRef = false;

  /**
   * Tells if we're in an internal document type subset.
   */
  private boolean m_inDoctype = 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);

  /**
   * 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;

  /**
   * Flag to quickly tell if the encoding is UTF8.
   */
  boolean m_isUTF8 = false;

  /**
   * The maximum character size before we have to resort
   * to escaping.
   */
  protected int m_maxCharacter = Encodings.getLastPrintable();

  /**
   * Add space before '/>' for XHTML.
   */
  public boolean m_spaceBeforeClose = false;

  /** The xsl:output properties. */
  protected Properties m_format;

  /** Indicate whether running in Debug mode */
  private static final boolean DEBUG = false;

  /** This flag is set while receiving events from the external DTD */
  private boolean m_inExternalDTD = false;

  /**
   * Default constructor.
   */
  public SerializerToXML()
  {
    m_charInfo = m_xmlcharInfo;
  }

  /**
   * Copy properties from another SerializerToXML.
   *
   * @param xmlListener non-null reference to a SerializerToXML object.
   */
  public void CopyFrom(SerializerToXML xmlListener)
  {

    m_writer = xmlListener.m_writer;

    // m_outputStream = xmlListener.m_outputStream;
    m_encoding = xmlListener.m_encoding;
    javaEncodingIsISO = xmlListener.javaEncodingIsISO;
    m_shouldNotWriteXMLHeader = xmlListener.m_shouldNotWriteXMLHeader;

    // m_shouldNotWriteXMLHeader = xmlListener.m_shouldNotWriteXMLHeader;
    m_elemStack = xmlListener.m_elemStack;

    // 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_currentIndent = xmlListener.m_currentIndent;
    m_indentAmount = xmlListener.m_indentAmount;
    level = xmlListener.level;
    m_startNewLine = xmlListener.m_startNewLine;
    m_needToOutputDocTypeDecl = xmlListener.m_needToOutputDocTypeDecl;
    m_doctypeSystem = xmlListener.m_doctypeSystem;
    m_doctypePublic = xmlListener.m_doctypePublic;
    m_standalone = xmlListener.m_standalone;
    m_mediatype = xmlListener.m_mediatype;
    m_maxCharacter = xmlListener.m_maxCharacter;
    m_spaceBeforeClose = xmlListener.m_spaceBeforeClose;
    m_inCData = xmlListener.m_inCData;

    // m_pos = xmlListener.m_pos;
    m_pos = 0;
  }

  /**
   * 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
   */
  public synchronized void init(Writer writer, Properties format)
  {
    init(writer, format, false);
  }

  /**
   * 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 shouldFlush)
  {

    m_shouldFlush = shouldFlush;
    m_writer = writer;
    m_format = format;
    m_cdataSectionNames =
      OutputProperties.getQNameProperties(OutputKeys.CDATA_SECTION_ELEMENTS,
                                          format);
    m_indentAmount =
      OutputProperties.getIntProperty(OutputProperties.S_KEY_INDENT_AMOUNT,
                                      format);
    m_doIndent = OutputProperties.getBooleanProperty(OutputKeys.INDENT,
            format);
    m_shouldNotWriteXMLHeader =
      OutputProperties.getBooleanProperty(OutputKeys.OMIT_XML_DECLARATION,
                                          format);
    m_doctypeSystem = format.getProperty(OutputKeys.DOCTYPE_SYSTEM);
    m_doctypePublic = format.getProperty(OutputKeys.DOCTYPE_PUBLIC);
    m_standaloneWasSpecified = (null != format.get(OutputKeys.STANDALONE));
    m_standalone = OutputProperties.getBooleanProperty(OutputKeys.STANDALONE,
            format);
    m_mediatype = format.getProperty(OutputKeys.MEDIA_TYPE);

    if (null != m_doctypePublic)
    {
      if (m_doctypePublic.startsWith("-//W3C//DTD XHTML"))
        m_spaceBeforeClose = true;
    }

    // initCharsMap();
    if (null == m_encoding)
      m_encoding =
        Encodings.getMimeEncoding(format.getProperty(OutputKeys.ENCODING));

    m_isUTF8 = m_encoding.equals(Encodings.DEFAULT_MIME_ENCODING);
    m_maxCharacter = Encodings.getLastPrintable(m_encoding);

    // Access this only from the Hashtable level... we don't want to 
    // get default properties.
    String entitiesFileName =
      (String) format.get(OutputProperties.S_KEY_ENTITIES);

    if (null != entitiesFileName)
    {
      try
      {
        m_charInfo = null;

        if (null == m_charInfos)
        {
          synchronized (m_xmlcharInfo)
          {
            if (null == m_charInfos)  // secondary check
              m_charInfos = new Hashtable();
          }
        }
        else
        {
          m_charInfo = (CharInfo) m_charInfos.get(entitiesFileName);
        }

        if (null == m_charInfo)
        {
          try
          {
            m_charInfo = new CharInfo(entitiesFileName);
          }
          catch(Exception e)
          {
          	m_charInfo = null;
          }
        }

        if (null == m_charInfo)
        {
          String absoluteEntitiesFileName;

          if (entitiesFileName.indexOf(':') < 0)
          {
            absoluteEntitiesFileName =
              SystemIDResolver.getAbsoluteURIFromRelative(entitiesFileName);
          }
          else
          {
            absoluteEntitiesFileName =
              SystemIDResolver.getAbsoluteURI(entitiesFileName, null);
          }

          m_charInfo = new CharInfo(absoluteEntitiesFileName);

          m_charInfos.put(entitiesFileName, m_charInfo);
        }
      }
      catch (javax.xml.transform.TransformerException te)
      {
        throw new org.apache.xml.utils.WrappedRuntimeException(te);
      }
    }
  }

  /**
   * 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
   */
  public synchronized void init(OutputStream output, Properties format)
          throws UnsupportedEncodingException
  {

    if (null == format)
    {
      OutputProperties op = new OutputProperties(Method.XML);

      format = op.getProperties();
    }

    m_encoding =
      Encodings.getMimeEncoding(format.getProperty(OutputKeys.ENCODING));

    if (m_encoding.equalsIgnoreCase("UTF-8"))
    {
      m_isUTF8 = true;
      if(output instanceof java.io.BufferedOutputStream)
      {
        init(new WriterToUTF8(output), format, true);
      }
      else if(output instanceof java.io.FileOutputStream)
      {
        init(new WriterToUTF8Buffered(output), format, true);
      }
      else
      {
        // Not sure what to do in this case.  I'm going to be conservative 
        // and not buffer.
        init(new WriterToUTF8(output), format, true);
      }
      
    }
    else if (m_encoding.equals("WINDOWS-1250")
             || m_encoding.equals("US-ASCII") || m_encoding.equals("ASCII"))
    {
      init(new WriterToASCI(output), format, true);
    }
    else
    {
      Writer osw;

      try
      {
        osw = Encodings.getWriter(output, m_encoding);
      }
      catch (UnsupportedEncodingException uee)
      {
        System.out.println("Warning: encoding \"" + m_encoding
                           + "\" not supported" + ", using "
                           + Encodings.DEFAULT_MIME_ENCODING);

        m_encoding = Encodings.DEFAULT_MIME_ENCODING;
        osw = Encodings.getWriter(output, m_encoding);
      }

      m_maxCharacter = Encodings.getLastPrintable(m_encoding);

      init(osw, format, true);
    }
    
  }

  /**
   * 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.
   * @see org.xml.sax.Locator
   */
  public void setDocumentLocator(Locator locator)
  {

    // I don't do anything with this yet.
  }

  /**
   * Output the doc type declaration.
   *
   * @param name non-null reference to document type name.
   * NEEDSDOC @param closeDecl
   *
   * @throws org.xml.sax.SAXException
   */
  void outputDocTypeDecl(String name, boolean closeDecl)
          throws org.xml.sax.SAXException
  {
    try
    {
      final Writer writer = m_writer;
  
      writer.write("<!DOCTYPE ");
      writer.write(name);
  
      if (null != m_doctypePublic)
      {
        writer.write(" PUBLIC \"");
        writer.write(m_doctypePublic);
        writer.write('\"');
      }
  
      if (null != m_doctypeSystem)
      {
        if (null == m_doctypePublic)
          writer.write(" SYSTEM \"");
        else
          writer.write(" \"");
  
        writer.write(m_doctypeSystem);
  
        if (closeDecl)
        {
          writer.write("\">");
          writer.write(m_lineSep, 0, m_lineSepLen);;
        }
        else
          writer.write('\"');
      }
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /**
   * 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 org.xml.sax.SAXException
  {

    try
    {
      final Writer writer = m_writer;
      writer.write("<!ENTITY ");
      writer.write(name);
      writer.write(" \"");
      writer.write(value);
      writer.write("\">");
      writer.write(m_lineSep, 0, m_lineSepLen);
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /**
   * 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 startDocument() throws org.xml.sax.SAXException
  {

    if (m_inEntityRef)
      return;

    m_needToOutputDocTypeDecl = true;
    m_startNewLine = false;

    if (m_shouldNotWriteXMLHeader == false)
    {
      String encoding = Encodings.getMimeEncoding(m_encoding);
      String version = (null == m_version) ? "1.0" : m_version;
      String standalone;

      if (m_standaloneWasSpecified)
      {
        standalone = " standalone=\"" + (m_standalone ? "yes" : "no") + "\"";
      }
      else
      {
        standalone = "";
      }

      try
      {
        final Writer writer = m_writer;
        writer.write("<?xml version=\"");
        writer.write(version);
        writer.write("\" encoding=\"");
        writer.write(encoding);
        writer.write('\"');
        writer.write(standalone);
        writer.write("?>");
        writer.write(m_lineSep, 0, m_lineSepLen);
      }
      catch(IOException ioe)
      {
        throw new SAXException(ioe);
      }
    }
  }

  /**
   * 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
  {

    if (m_doIndent &&!m_isprevtext)
    {
      outputLineSep();
    }

    flushWriter();
  }

  /**
   * 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
  {
    m_doctypeSystem = systemId;
    m_doctypePublic = publicId;

    if ((true == m_needToOutputDocTypeDecl))  // && (null != m_doctypeSystem))
    {
      outputDocTypeDecl(name, false);
    }

    m_needToOutputDocTypeDecl = false;
    m_inDoctype = true;
  }

  /**
   * 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_inDoctype)
        m_writer.write("]>");
      else
      {
        m_writer.write('>');
      }
  
      m_writer.write(m_lineSep, 0, m_lineSepLen);
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }

    // Do nothing for now.
  }

  /**
   * Begin the scope of a prefix-URI Namespace mapping.
   * @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{}

  /**
   * 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{}

  /**
   * 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.
   */
  protected static final boolean subPartMatch(String p, String t)
  {
    return (p == t) || ((null != p) && (p.equals(t)));
  }

  /**
   * 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.
   * @param qnames Vector of qualified names of elements, or null.
   * @param state The stack where the state should be pushed.
   */
  protected void pushState(String namespaceURI, String localName,
                           Vector qnames, BoolStack state)
  {

    boolean b;

    if (null != qnames)
    {
      b = false;

      if ((null != namespaceURI) && namespaceURI.length() == 0)
        namespaceURI = null;

      int nElems = qnames.size();

      for (int i = 0; i < nElems; i++)
      {
        QName q = (QName) qnames.elementAt(i);

        if (q.getLocalName().equals(localName)
                && subPartMatch(namespaceURI, q.getNamespaceURI()))
        {
          b = true;

          break;
        }
      }
    }
    else
    {
      b = state.peekOrFalse();
    }

    state.push(b);
  }

  /**
   * Receive notification of the beginning 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.
   * @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 (DEBUG)
    {
      System.out.println("SerializerToXML - startElement: " + namespaceURI
                         + ", " + localName);

      int n = atts.getLength();

      for (int i = 0; i < n; i++)
      {
        System.out.println("atts[" + i + "]: " + atts.getQName(i) + " = "
                           + atts.getValue(i));
      }

      if (null == namespaceURI)
      {
        (new RuntimeException(localName
                              + " has a null namespace!")).printStackTrace();
      }
    }

    if (m_inEntityRef)
      return;

    if ((true == m_needToOutputDocTypeDecl) && (null != m_doctypeSystem))
    {
      outputDocTypeDecl(name, true);
    }

    m_needToOutputDocTypeDecl = false;

    writeParentTagEnd();
    pushState(namespaceURI, localName, m_cdataSectionNames,
              m_cdataSectionStates);

    // pushState(namespaceURI, localName, m_format.getNonEscapingElements(),
    //          m_disableOutputEscapingStates);
    m_ispreserve = false;

    //  System.out.println(name+": m_doIndent = "+m_doIndent+", m_ispreserve = "+m_ispreserve+", m_isprevtext = "+m_isprevtext);
    if (shouldIndent() && m_startNewLine)
    {
      indent(m_currentIndent);
    }

    m_startNewLine = true;

    try
    {
      m_writer.write('<');
      m_writer.write(name);
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }

    int nAttrs = atts.getLength();

    for (int i = 0; i < nAttrs; i++)
    {
      processAttribute(atts.getQName(i), atts.getValue(i));
    }

    // Flag the current element as not yet having any children.
    openElementForChildren();

    m_currentIndent += m_indentAmount;
    m_isprevtext = false;
  }

  /**
   * Check to see if a parent's ">" has been written, and, if
   * it has not, write it.
   *
   * @throws org.xml.sax.SAXException
   */
  protected void writeParentTagEnd() throws org.xml.sax.SAXException
  {

    // See if the parent element has already been flagged as having children.
    if (!m_elemStack.peekOrTrue())
    {
      try
      {
        m_writer.write('>');
      }
      catch(IOException ioe)
      {
        throw new SAXException(ioe);
      }

      m_isprevtext = false;

      m_elemStack.setTop(true);
      m_preserves.push(m_ispreserve);
    }
  }

  /**
   * Flag the current element as not yet having any
   * children.
   */
  protected void openElementForChildren()
  {

    // Flag the current element as not yet having any children.
    m_elemStack.push(false);
  }

  /**
   * Tell if child nodes have been added to the current
   * element.  Must be called in balance with openElementForChildren().
   *
   * @return true if child nodes were added.
   */
  protected boolean childNodesWereAdded()
  {
    return m_elemStack.isEmpty() ? false : m_elemStack.pop();
  }

  /**
   * 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;

    m_currentIndent -= m_indentAmount;

    boolean hasChildNodes = childNodesWereAdded();

    try
    {
      final Writer writer = m_writer;
      if (hasChildNodes)
      {
        if (shouldIndent())
          indent(m_currentIndent);
  
        writer.write('<');
        writer.write('/');
        writer.write(name);
        writer.write('>');
      }
      else
      {
        if (m_spaceBeforeClose)
          writer.write(" />");
        else
          writer.write("/>");
      }
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }

    if (hasChildNodes)
    {
      m_ispreserve = m_preserves.isEmpty() ? false : m_preserves.pop();
    }

    m_isprevtext = false;

    // m_disableOutputEscapingStates.pop();
    m_cdataSectionStates.pop();
  }

  /**
   * Process an attribute.
   * @param   name   The name of the attribute.
   * @param   value   The value of the attribute.
   *
   * @throws org.xml.sax.SAXException
   */
  protected void processAttribute(String name, String value)
          throws org.xml.sax.SAXException
  {
    try
    {
      final Writer writer = m_writer;
      writer.write(' ');
      writer.write(name);
      writer.write("=\"");
      writeAttrString(value, m_encoding);
      writer.write('\"');
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /**
   * 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);
  }

  /**
   * Ends an un-escaping section.
   *
   * @see #startNonEscaping
   *
   * @throws org.xml.sax.SAXException
   */
  public void endNonEscaping() throws org.xml.sax.SAXException
  {
    m_disableOutputEscapingStates.pop();
  }

  /**
   * 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;

    if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING))
    {
      startNonEscaping();
    }
    else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING))
    {
      endNonEscaping();
    }
    else
    {
      try
      {
        final Writer writer = m_writer;
        writeParentTagEnd();
  
        if (shouldIndent())
          indent(m_currentIndent);
  
        writer.write('<');
        writer.write('?');
        writer.write(target);
  
        if (data.length() > 0 &&!Character.isSpaceChar(data.charAt(0)))
          writer.write(' ');
  
        int indexOfQLT = data.indexOf("?>");
  
        if (indexOfQLT >= 0)
        {
  
          // See XSLT spec on error recovery of "?>" in PIs.
          if (indexOfQLT > 0)
          {
            writer.write(data.substring(0, indexOfQLT));
          }
  
          writer.write("? >");  // add space between.
  
          if ((indexOfQLT + 2) < data.length())
          {
            writer.write(data.substring(indexOfQLT + 2));
          }
        }
        else
        {
          writer.write(data);
        }
  
        writer.write('?');
        writer.write('>');
  
        // Always output a newline char if not inside of an 
        // element. The whitespace is not significant in that
        // case.
        if (m_elemStack.isEmpty())
          writer.write(m_lineSep, 0, m_lineSepLen);
  
        m_startNewLine = true;
      }
      catch(IOException ioe)
      {
        throw new SAXException(ioe);
      }
    }
  }

  /**
   * 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
  {

    if (m_inEntityRef)
      return;

    writeParentTagEnd();

    if (shouldIndent())
      indent(m_currentIndent);

    try
    {
      final Writer writer = m_writer;
      writer.write("<!--");
      writer.write(ch, start, length);
      writer.write("-->");
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }

    m_startNewLine = true;
  }

  /**
   * 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_inCData = true;
  }

  /**
   * 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
  {
    m_inCData = false;
  }

  /**
   * 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 void cdata(char ch[], int start, int length)
          throws org.xml.sax.SAXException
  {

    try
    {
      writeParentTagEnd();

      m_ispreserve = true;

      if (shouldIndent())
        indent(m_currentIndent);

      boolean writeCDataBrackets = (((length >= 1) && canConvert(ch[start])));

      if (writeCDataBrackets)
      {
        m_writer.write("<![CDATA[");
      }

      // m_writer.write(ch, start, length);
      if (isEscapingDisabled())
      {
        charactersRaw(ch, start, length);
      }
      else
        writeNormalizedChars(ch, start, length, true);

      if (writeCDataBrackets)
      {
        m_writer.write("]]>");
      }
    }
    catch (IOException ioe)
    {
      throw new org.xml.sax.SAXException(
        XSLMessages.createXPATHMessage(XPATHErrorResources.ER_OIERROR, null),
        ioe);  //"IO error", ioe);
    }
  }

  /** The current position in the m_charBuf or m_byteBuf. */
  protected int m_pos = 0;

  /**
   * Append a character to the buffer.
   *
   * @param b byte to be written to result stream.
   *
   * @throws org.xml.sax.SAXException
   */
  protected final void accum(char b) throws org.xml.sax.SAXException
  {

    try
    {
      m_writer.write(b);
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }
  
  /**
   * Append a character to the buffer.
   *
   * @param chars non-null reference to character array.
   * @param start Start of characters to be written.
   * @param length Number of characters to be written.
   *
   * @throws org.xml.sax.SAXException
   */
  protected final void accum(char chars[], int start, int length)
          throws org.xml.sax.SAXException
  {

    try
    {
      m_writer.write(chars, start, length);
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }
  /**
   * Append a character to the buffer.
   *
   * @param s non-null reference to string to be written to the character buffer.
   *
   * @throws org.xml.sax.SAXException
   */
  protected final void accum(String s) throws org.xml.sax.SAXException
  {

    try
    {
      m_writer.write(s);
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /**
   * Flush the formatter's result stream.
   *
   * @throws org.xml.sax.SAXException
   */
  public 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);
      }
    }
  }

  /**
   * 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)
      return;

    //    if (m_inEntityRef)
    //      return;
    //    else 
    if (m_inCData || m_cdataSectionStates.peekOrFalse())
    {
      cdata(chars, start, length);

      return;
    }
    
    try
    {
      
      if (m_disableOutputEscapingStates.peekOrFalse())
      {
        charactersRaw(chars, start, length);
  
        return;
      }
    
      final Writer writer = m_writer;
      if (!m_elemStack.peekOrTrue())
      {
        writer.write('>');
  
        m_isprevtext = false;
  
        m_elemStack.setTop(true);
        m_preserves.push(m_ispreserve);
      }
  
      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;
  
      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;
        }
  
        if ((canConvert(ch) && (!specialsMap.get(ch))) || ('"' == ch))
        {
          lengthClean++;
        }
        else
        {
          if (lengthClean > 0)
          {
            writer.write(chars, startClean, lengthClean);
  
            lengthClean = 0;
          }
  
          if (CharInfo.S_LINEFEED == ch)
          {
            writer.write(m_lineSep, 0, m_lineSepLen);
  
            startClean = i + 1;
          }
          else
          {
            startClean = accumDefaultEscape(ch, i, chars, end, false);
            i = startClean - 1;
          }
        }
      }
  
      if (lengthClean > 0)
      {
        writer.write(chars, startClean, lengthClean);
      }
    
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }


    m_isprevtext = true;
  }

  /**
   * 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
   */
  public void charactersRaw(char ch[], int start, int length)
          throws org.xml.sax.SAXException
  {

    try
    {
      if (m_inEntityRef)
        return;
  
      writeParentTagEnd();
  
      m_ispreserve = true;
  
      m_writer.write(ch, start, length);
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /**
   * 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;
  }

  /**
   * 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 org.xml.sax.SAXException
  {

    int next;

    if (i + 1 >= end)
    {
      throw new org.xml.sax.SAXException(
        XSLMessages.createXPATHMessage(
          XPATHErrorResources.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 org.xml.sax.SAXException(
          XSLMessages.createXPATHMessage(
            XPATHErrorResources.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;
  }

  /**
   * 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, org.xml.sax.SAXException
  {

    // 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;
  }

  /**
   * 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 && (!canConvert(c)))
      {
        if (i != 0)
          m_writer.write("]]>");

        // 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)))
          m_writer.write("<![CDATA[");
      }
      else if (isCData
               && ((i < (end - 2)) && (']' == c) && (']' == ch[i + 1])
                   && ('>' == ch[i + 2])))
      {
        m_writer.write("]]]]><![CDATA[>");

        i += 2;
      }
      else
      {
        if (canConvert(c))
        {
          m_writer.write(c);
        }

        // This needs to go into a function... 
        else 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(';');
        }
      }
    }
  }

  /**
   * 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 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;
  }

  /**
   * 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;
  }

  /**
   * 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
  {
    writeParentTagEnd();

    if (shouldIndent())
      indent(m_currentIndent);

    try
    {
      final Writer writer = m_writer;
      writer.write("&");
      writer.write(name);
      writer.write(";");
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }

  }

  // 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
    {
      final Writer writer = m_writer;
      if (m_inDoctype)
      {
        writer.write(" [");
        writer.write(m_lineSep, 0, m_lineSepLen);
  
        m_inDoctype = false;
      }
  
      writer.write("<!ELEMENT ");
      writer.write(name);
      writer.write(' ');
      writer.write(model);
      writer.write('>');
      writer.write(m_lineSep, 0, m_lineSepLen);
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /** NEEDSDOC Field m_elemName          */
  private String m_elemName = "";

  /**
   * 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
    {
      final Writer writer = m_writer;
      if (m_inDoctype)
      {
        writer.write(" [");
        writer.write(m_lineSep, 0, m_lineSepLen);
  
        m_inDoctype = false;
      }

       
      writer.write("<!ATTLIST ");
      writer.write(eName);
      writer.write(" "); 

      writer.write(aName);
      writer.write(" ");
      writer.write(type);
      if(valueDefault!=null)
      {
	writer.write(" ");
	writer.write(valueDefault);
      }
  
      //m_writer.write(" ");
      //m_writer.write(value);
      writer.write(">");
      writer.write(m_lineSep, 0, m_lineSepLen);
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /**
   * 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 ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /**
   * 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{}

  /**
   * 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 org.xml.sax.SAXException
   */
  protected int accumDefaultEntity(
          char ch, int i, char[] chars, int len, boolean escLF)
            throws org.xml.sax.SAXException
  {

    try
    {
      if (!escLF && CharInfo.S_LINEFEED == ch)
      {
        m_writer.write(m_lineSep, 0, m_lineSepLen);
      }
      else
      {
        if (m_charInfo.isSpecial(ch))
        {
          String entityRef = m_charInfo.getEntityNameForChar(ch);
  
          if (null != entityRef)
          {
            final Writer writer = m_writer;
            writer.write('&');
            writer.write(entityRef);
            writer.write(';');
          }
          else
            return i;
        }
        else
          return i;
      }
  
      return i + 1;
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /**
   * 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(
          char ch, int i, char[] chars, int len, boolean escLF)
            throws org.xml.sax.SAXException
  {

    int pos = accumDefaultEntity(ch, i, chars, len, escLF);

    if (i == pos)
    {
      pos++;

      try
      {
        if (0xd800 <= ch && ch < 0xdc00)
        {
  
          // UTF-16 surrogate
          int next;
  
          if (i + 1 >= len)
          {
            throw new org.xml.sax.SAXException(
              XSLMessages.createXPATHMessage(
                XPATHErrorResources.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 org.xml.sax.SAXException(
                XSLMessages.createXPATHMessage(
                  XPATHErrorResources.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;
          }
  
          m_writer.write("&#");
          m_writer.write(Integer.toString(next));
          m_writer.write(";");
  
          /*} else if (null != ctbc && !ctbc.canConvert(ch)) {
          sb.append("&#x");
          sb.append(Integer.toString((int)ch, 16));
          sb.append(";");*/
        }
        else
        {
          if (!canConvert(ch) || (m_charInfo.isSpecial(ch)))
          {
            m_writer.write("&#");
            m_writer.write(Integer.toString(ch));
            m_writer.write(";");
          }
          else
          {
            m_writer.write(ch);
          }
        }
      }
      catch(IOException ioe)
      {
        throw new SAXException(ioe);
      }
    }

    return pos;
  }
  
  /**
   * Opaque reference to the sun.io.CharToByteConverter for this 
   * encoding.
   */
  Object m_charToByteConverter = null;
  
  /**
   * Method reference to the sun.io.CharToByteConverter#canConvert method 
   * for this encoding.  Invalid if m_charToByteConverter is null.
   */
  java.lang.reflect.Method m_canConvertMeth;
  
  /**
   * Boolean that tells if we already tried to get the converter.
   */
  boolean m_triedToGetConverter = false;
  
  /**
   * Tell if this character can be written without escaping.
   */
  public boolean canConvert(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(m_encoding);
        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 );
  }


  /**
   * 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 org.xml.sax.SAXException
   */
  public void writeAttrString(String string, String encoding)
          throws org.xml.sax.SAXException
  {

    try
    {
      final char[] stringChars = string.toCharArray();
      final int len = stringChars.length;
      final Writer writer = m_writer;
  
      for (int i = 0; i < len; i++)
      {
        char ch = stringChars[i];
  
        if (canConvert(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(ch, i, stringChars, len, true);
        }
      }
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /**
   * 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);
  }

  /**
   * 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.
   */
  public void printSpace(int n) throws org.xml.sax.SAXException
  {

    try
    {
      for (int i = 0; i < n; i++)
      {
        m_writer.write(' ');
      }
    }
    catch(IOException ioe)
    {
      throw new SAXException(ioe);
    }
  }

  /**
   * Prints a newline character and <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 during writing.
   */
  public void indent(int n) throws org.xml.sax.SAXException
  {

    if (m_startNewLine)
      outputLineSep();

    if (m_doIndent)
    {
      printSpace(n);
    }
  }

  /**
   * 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
    {
      init(output, m_format);
    }
    catch (UnsupportedEncodingException uee)
    {

      // Should have been warned in init, I guess...
    }
  }

  /**
   * 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;
  }

  /**
   * 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)
  {
    m_writer = writer;
  }

  /**
   * 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;
  }

  /**
   * 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);

    m_shouldFlush = shouldFlush;
  }

  /**
   * Returns the output format for this serializer.
   *
   * @return The output format in use
   */
  public Properties getOutputFormat()
  {
    return m_format;
  }

  /**
   * 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;
  }

  /**
   * 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
  {
    return this;  // for now
  }

  /**
   * 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()
  {
    return false;
  }

  /**
   * 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.xpath.DOM2Helper());

      walker.traverse(node);
    }
    catch (org.xml.sax.SAXException se)
    {
      throw new WrappedRuntimeException(se);
    }
  }
}  //ToXMLStringVisitor

