jaxp/src/com/sun/org/apache/xml/internal/serializer/SerializerBase.java
changeset 12457 c348e06f0e82
parent 6 7f561c08de6b
child 12458 d601e4bba306
equal deleted inserted replaced
12324:1d7e6da6adc8 12457:c348e06f0e82
       
     1 /*
       
     2  * reserved comment block
       
     3  * DO NOT REMOVE OR ALTER!
       
     4  */
       
     5 /*
       
     6  * Copyright 2001-2004 The Apache Software Foundation.
       
     7  *
       
     8  * Licensed under the Apache License, Version 2.0 (the "License");
       
     9  * you may not use this file except in compliance with the License.
       
    10  * You may obtain a copy of the License at
       
    11  *
       
    12  *     http://www.apache.org/licenses/LICENSE-2.0
       
    13  *
       
    14  * Unless required by applicable law or agreed to in writing, software
       
    15  * distributed under the License is distributed on an "AS IS" BASIS,
       
    16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    17  * See the License for the specific language governing permissions and
       
    18  * limitations under the License.
       
    19  */
       
    20 /*
       
    21  * $Id: SerializerBase.java,v 1.5 2006/04/14 12:09:19 sunithareddy Exp $
       
    22  */
       
    23 package com.sun.org.apache.xml.internal.serializer;
       
    24 
       
    25 import java.io.IOException;
       
    26 import java.util.Vector;
       
    27 
       
    28 import javax.xml.transform.SourceLocator;
       
    29 import javax.xml.transform.Transformer;
       
    30 
       
    31 import com.sun.org.apache.xml.internal.serializer.utils.MsgKey;
       
    32 import com.sun.org.apache.xml.internal.serializer.utils.Utils;
       
    33 import org.xml.sax.Attributes;
       
    34 import org.xml.sax.ContentHandler;
       
    35 import org.xml.sax.Locator;
       
    36 import org.xml.sax.SAXException;
       
    37 import org.xml.sax.SAXParseException;
       
    38 import org.xml.sax.ext.Locator2;
       
    39 
       
    40 
       
    41 /**
       
    42  * This class acts as a base class for the XML "serializers"
       
    43  * and the stream serializers.
       
    44  * It contains a number of common fields and methods.
       
    45  *
       
    46  * @xsl.usage internal
       
    47  */
       
    48 public abstract class SerializerBase
       
    49     implements SerializationHandler, SerializerConstants
       
    50 {
       
    51 
       
    52 
       
    53     /**
       
    54      * To fire off the end element trace event
       
    55      * @param name Name of element
       
    56      */
       
    57     protected void fireEndElem(String name)
       
    58         throws org.xml.sax.SAXException
       
    59     {
       
    60         if (m_tracer != null)
       
    61         {
       
    62             flushMyWriter();
       
    63             m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDELEMENT,name, (Attributes)null);
       
    64         }
       
    65     }
       
    66 
       
    67     /**
       
    68      * Report the characters trace event
       
    69      * @param chars  content of characters
       
    70      * @param start  starting index of characters to output
       
    71      * @param length  number of characters to output
       
    72      */
       
    73     protected void fireCharEvent(char[] chars, int start, int length)
       
    74         throws org.xml.sax.SAXException
       
    75     {
       
    76         if (m_tracer != null)
       
    77         {
       
    78             flushMyWriter();
       
    79             m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CHARACTERS, chars, start,length);
       
    80         }
       
    81     }
       
    82 
       
    83     /**
       
    84      * true if we still need to call startDocumentInternal()
       
    85          */
       
    86     protected boolean m_needToCallStartDocument = true;
       
    87 
       
    88     /** True if a trailing "]]>" still needs to be written to be
       
    89      * written out. Used to merge adjacent CDATA sections
       
    90      */
       
    91     protected boolean m_cdataTagOpen = false;
       
    92 
       
    93     /**
       
    94      * All the attributes of the current element, collected from
       
    95      * startPrefixMapping() calls, or addAddtribute() calls, or
       
    96      * from the SAX attributes in a startElement() call.
       
    97      */
       
    98     protected AttributesImplSerializer m_attributes = new AttributesImplSerializer();
       
    99 
       
   100     /**
       
   101      * Tells if we're in an EntityRef event.
       
   102      */
       
   103     protected boolean m_inEntityRef = false;
       
   104 
       
   105     /** This flag is set while receiving events from the external DTD */
       
   106     protected boolean m_inExternalDTD = false;
       
   107 
       
   108     /**
       
   109      * The System ID for the doc type.
       
   110      */
       
   111     private String m_doctypeSystem;
       
   112 
       
   113     /**
       
   114      * The public ID for the doc type.
       
   115      */
       
   116     private String m_doctypePublic;
       
   117 
       
   118     /**
       
   119      * Flag to tell that we need to add the doctype decl, which we can't do
       
   120      * until the first element is encountered.
       
   121      */
       
   122     boolean m_needToOutputDocTypeDecl = true;
       
   123 
       
   124     /**
       
   125      * The character encoding.  Must match the encoding used for the
       
   126      * printWriter.
       
   127      */
       
   128     private String m_encoding = null;
       
   129 
       
   130     /**
       
   131      * Tells if we should write the XML declaration.
       
   132      */
       
   133     private boolean m_shouldNotWriteXMLHeader = false;
       
   134 
       
   135     /**
       
   136      * The standalone value for the doctype.
       
   137      */
       
   138     private String m_standalone;
       
   139 
       
   140     /**
       
   141      * True if standalone was specified.
       
   142      */
       
   143     protected boolean m_standaloneWasSpecified = false;
       
   144 
       
   145     /**
       
   146      * Flag to tell if indenting (pretty-printing) is on.
       
   147      */
       
   148     protected boolean m_doIndent = false;
       
   149     /**
       
   150      * Amount to indent.
       
   151      */
       
   152     protected int m_indentAmount = 0;
       
   153 
       
   154     /**
       
   155      * Tells the XML version, for writing out to the XML decl.
       
   156      */
       
   157     private String m_version = null;
       
   158 
       
   159     /**
       
   160      * The mediatype.  Not used right now.
       
   161      */
       
   162     private String m_mediatype;
       
   163 
       
   164     /**
       
   165      * The transformer that was around when this output handler was created (if
       
   166      * any).
       
   167      */
       
   168     private Transformer m_transformer;
       
   169 
       
   170     /**
       
   171      * Pairs of local names and corresponding URIs of CDATA sections. This list
       
   172      * comes from the cdata-section-elements attribute. Every second one is a
       
   173      * local name, and every other second one is the URI for the local name.
       
   174      */
       
   175     protected Vector m_cdataSectionElements = null;
       
   176 
       
   177     /**
       
   178      * Namespace support, that keeps track of currently defined
       
   179      * prefix/uri mappings. As processed elements come and go, so do
       
   180      * the associated mappings for that element.
       
   181      */
       
   182     protected NamespaceMappings m_prefixMap;
       
   183 
       
   184     /**
       
   185      * Handle for firing generate events.  This interface may be implemented
       
   186      * by the referenced transformer object.
       
   187      */
       
   188     protected SerializerTrace m_tracer;
       
   189 
       
   190     protected SourceLocator m_sourceLocator;
       
   191 
       
   192 
       
   193     /**
       
   194      * The writer to send output to. This field is only used in the ToStream
       
   195      * serializers, but exists here just so that the fireStartDoc() and
       
   196      * other fire... methods can flush this writer when tracing.
       
   197      */
       
   198     protected java.io.Writer m_writer = null;
       
   199 
       
   200     /**
       
   201      * A reference to "stack frame" corresponding to
       
   202      * the current element. Such a frame is pushed at a startElement()
       
   203      * and popped at an endElement(). This frame contains information about
       
   204      * the element, such as its namespace URI.
       
   205      */
       
   206     protected ElemContext m_elemContext = new ElemContext();
       
   207 
       
   208     /**
       
   209      * A utility buffer for converting Strings passed to
       
   210      * character() methods to character arrays.
       
   211      * Reusing this buffer means not creating a new character array
       
   212      * everytime and it runs faster.
       
   213      */
       
   214     protected char[] m_charsBuff = new char[60];
       
   215 
       
   216     /**
       
   217      * A utility buffer for converting Strings passed to
       
   218      * attribute methods to character arrays.
       
   219      * Reusing this buffer means not creating a new character array
       
   220      * everytime and it runs faster.
       
   221      */
       
   222     protected char[] m_attrBuff = new char[30];
       
   223 
       
   224     private Locator m_locator = null;
       
   225 
       
   226     protected boolean m_needToCallSetDocumentInfo = true;
       
   227 
       
   228     /**
       
   229      * Receive notification of a comment.
       
   230      *
       
   231      * @see ExtendedLexicalHandler#comment(String)
       
   232      */
       
   233     public void comment(String data) throws SAXException
       
   234     {
       
   235         final int length = data.length();
       
   236         if (length > m_charsBuff.length)
       
   237         {
       
   238             m_charsBuff = new char[length * 2 + 1];
       
   239         }
       
   240         data.getChars(0, length, m_charsBuff, 0);
       
   241         comment(m_charsBuff, 0, length);
       
   242     }
       
   243 
       
   244     /**
       
   245      * If at runtime, when the qname of the attribute is
       
   246      * known, another prefix is specified for the attribute, then we can
       
   247      * patch or hack the name with this method. For
       
   248      * a qname of the form "ns?:otherprefix:name", this function patches the
       
   249      * qname by simply ignoring "otherprefix".
       
   250      * TODO: This method is a HACK! We do not have access to the
       
   251      * XML file, it sometimes generates a NS prefix of the form "ns?" for
       
   252      * an attribute.
       
   253      */
       
   254     protected String patchName(String qname)
       
   255     {
       
   256 
       
   257 
       
   258         final int lastColon = qname.lastIndexOf(':');
       
   259 
       
   260         if (lastColon > 0) {
       
   261             final int firstColon = qname.indexOf(':');
       
   262             final String prefix = qname.substring(0, firstColon);
       
   263             final String localName = qname.substring(lastColon + 1);
       
   264 
       
   265         // If uri is "" then ignore prefix
       
   266             final String uri = m_prefixMap.lookupNamespace(prefix);
       
   267             if (uri != null && uri.length() == 0) {
       
   268                 return localName;
       
   269             }
       
   270             else if (firstColon != lastColon) {
       
   271                 return prefix + ':' + localName;
       
   272             }
       
   273         }
       
   274         return qname;
       
   275     }
       
   276 
       
   277     /**
       
   278      * Returns the local name of a qualified name. If the name has no prefix,
       
   279      * then it works as the identity (SAX2).
       
   280      * @param qname the qualified name
       
   281      * @return the name, but excluding any prefix and colon.
       
   282      */
       
   283     protected static String getLocalName(String qname)
       
   284     {
       
   285         final int col = qname.lastIndexOf(':');
       
   286         return (col > 0) ? qname.substring(col + 1) : qname;
       
   287     }
       
   288 
       
   289     /**
       
   290      * Receive an object for locating the origin of SAX document events.
       
   291      *
       
   292      * @param locator An object that can return the location of any SAX document
       
   293      * event.
       
   294      *
       
   295      * Receive an object for locating the origin of SAX document events.
       
   296      *
       
   297      * <p>SAX parsers are strongly encouraged (though not absolutely
       
   298      * required) to supply a locator: if it does so, it must supply
       
   299      * the locator to the application by invoking this method before
       
   300      * invoking any of the other methods in the DocumentHandler
       
   301      * interface.</p>
       
   302      *
       
   303      * <p>The locator allows the application to determine the end
       
   304      * position of any document-related event, even if the parser is
       
   305      * not reporting an error.  Typically, the application will
       
   306      * use this information for reporting its own errors (such as
       
   307      * character content that does not match an application's
       
   308      * business rules).  The information returned by the locator
       
   309      * is probably not sufficient for use with a search engine.</p>
       
   310      *
       
   311      * <p>Note that the locator will return correct information only
       
   312      * during the invocation of the events in this interface.  The
       
   313      * application should not attempt to use it at any other time.</p>
       
   314      */
       
   315     public void setDocumentLocator(Locator locator)
       
   316     {
       
   317         m_locator = locator;
       
   318     }
       
   319 
       
   320     /**
       
   321      * Adds the given attribute to the set of collected attributes , but only if
       
   322      * there is a currently open element.
       
   323      *
       
   324      * An element is currently open if a startElement() notification has
       
   325      * occured but the start of the element has not yet been written to the
       
   326      * output.  In the stream case this means that we have not yet been forced
       
   327      * to close the elements opening tag by another notification, such as a
       
   328      * character notification.
       
   329      *
       
   330      * @param uri the URI of the attribute
       
   331      * @param localName the local name of the attribute
       
   332      * @param rawName    the qualified name of the attribute
       
   333      * @param type the type of the attribute (probably CDATA)
       
   334      * @param value the value of the attribute
       
   335      * @param XSLAttribute true if this attribute is coming from an xsl:attriute element
       
   336      * @see ExtendedContentHandler#addAttribute(String, String, String, String, String)
       
   337      */
       
   338     public void addAttribute(
       
   339         String uri,
       
   340         String localName,
       
   341         String rawName,
       
   342         String type,
       
   343         String value,
       
   344         boolean XSLAttribute)
       
   345         throws SAXException
       
   346     {
       
   347         if (m_elemContext.m_startTagOpen)
       
   348         {
       
   349             addAttributeAlways(uri, localName, rawName, type, value, XSLAttribute);
       
   350         }
       
   351 
       
   352     }
       
   353 
       
   354     /**
       
   355      * Adds the given attribute to the set of attributes, even if there is
       
   356      * no currently open element. This is useful if a SAX startPrefixMapping()
       
   357      * should need to add an attribute before the element name is seen.
       
   358      *
       
   359      * @param uri the URI of the attribute
       
   360      * @param localName the local name of the attribute
       
   361      * @param rawName   the qualified name of the attribute
       
   362      * @param type the type of the attribute (probably CDATA)
       
   363      * @param value the value of the attribute
       
   364      * @param XSLAttribute true if this attribute is coming from an xsl:attribute element
       
   365      * @return true if the attribute was added,
       
   366      * false if an existing value was replaced.
       
   367      */
       
   368     public boolean addAttributeAlways(
       
   369         String uri,
       
   370         String localName,
       
   371         String rawName,
       
   372         String type,
       
   373         String value,
       
   374         boolean XSLAttribute)
       
   375     {
       
   376         boolean was_added;
       
   377 //            final int index =
       
   378 //                (localName == null || uri == null) ?
       
   379 //                m_attributes.getIndex(rawName):m_attributes.getIndex(uri, localName);
       
   380             int index;
       
   381 //            if (localName == null || uri == null){
       
   382 //                index = m_attributes.getIndex(rawName);
       
   383 //            }
       
   384 //            else {
       
   385 //                index = m_attributes.getIndex(uri, localName);
       
   386 //            }
       
   387 
       
   388             if (localName == null || uri == null || uri.length() == 0)
       
   389                 index = m_attributes.getIndex(rawName);
       
   390             else {
       
   391                 index = m_attributes.getIndex(uri,localName);
       
   392             }
       
   393             if (index >= 0)
       
   394             {
       
   395                 /* We've seen the attribute before.
       
   396                  * We may have a null uri or localName, but all
       
   397                  * we really want to re-set is the value anyway.
       
   398                  */
       
   399                 m_attributes.setValue(index,value);
       
   400                 was_added = false;
       
   401             }
       
   402             else
       
   403             {
       
   404                 // the attribute doesn't exist yet, create it
       
   405                 m_attributes.addAttribute(uri, localName, rawName, type, value);
       
   406                 was_added = true;
       
   407             }
       
   408             return was_added;
       
   409 
       
   410     }
       
   411 
       
   412 
       
   413     /**
       
   414      *  Adds  the given attribute to the set of collected attributes,
       
   415      * but only if there is a currently open element.
       
   416      *
       
   417      * @param name the attribute's qualified name
       
   418      * @param value the value of the attribute
       
   419      */
       
   420     public void addAttribute(String name, final String value)
       
   421     {
       
   422         if (m_elemContext.m_startTagOpen)
       
   423         {
       
   424             final String patchedName = patchName(name);
       
   425             final String localName = getLocalName(patchedName);
       
   426             final String uri = getNamespaceURI(patchedName, false);
       
   427 
       
   428             addAttributeAlways(uri,localName, patchedName, "CDATA", value, false);
       
   429          }
       
   430     }
       
   431 
       
   432     /**
       
   433      * Adds the given xsl:attribute to the set of collected attributes,
       
   434      * but only if there is a currently open element.
       
   435      *
       
   436      * @param name the attribute's qualified name (prefix:localName)
       
   437      * @param value the value of the attribute
       
   438      * @param uri the URI that the prefix of the name points to
       
   439      */
       
   440     public void addXSLAttribute(String name, final String value, final String uri)
       
   441     {
       
   442         if (m_elemContext.m_startTagOpen)
       
   443         {
       
   444             final String patchedName = patchName(name);
       
   445             final String localName = getLocalName(patchedName);
       
   446 
       
   447             addAttributeAlways(uri,localName, patchedName, "CDATA", value, true);
       
   448          }
       
   449     }
       
   450 
       
   451     /**
       
   452      * Add the given attributes to the currently collected ones. These
       
   453      * attributes are always added, regardless of whether on not an element
       
   454      * is currently open.
       
   455      * @param atts List of attributes to add to this list
       
   456      */
       
   457     public void addAttributes(Attributes atts) throws SAXException
       
   458     {
       
   459 
       
   460         int nAtts = atts.getLength();
       
   461         for (int i = 0; i < nAtts; i++)
       
   462         {
       
   463             String uri = atts.getURI(i);
       
   464 
       
   465             if (null == uri)
       
   466                 uri = "";
       
   467 
       
   468             addAttributeAlways(
       
   469                 uri,
       
   470                 atts.getLocalName(i),
       
   471                 atts.getQName(i),
       
   472                 atts.getType(i),
       
   473                 atts.getValue(i),
       
   474                 false);
       
   475 
       
   476         }
       
   477     }
       
   478 
       
   479     /**
       
   480      * Return a {@link ContentHandler} interface into this serializer.
       
   481      * If the serializer does not support the {@link ContentHandler}
       
   482      * interface, it should return null.
       
   483      *
       
   484      * @return A {@link ContentHandler} interface into this serializer,
       
   485      *  or null if the serializer is not SAX 2 capable
       
   486      * @throws IOException An I/O exception occured
       
   487      */
       
   488     public ContentHandler asContentHandler() throws IOException
       
   489     {
       
   490         return this;
       
   491     }
       
   492 
       
   493     /**
       
   494      * Report the end of an entity.
       
   495      *
       
   496      * @param name The name of the entity that is ending.
       
   497      * @throws org.xml.sax.SAXException The application may raise an exception.
       
   498      * @see #startEntity
       
   499      */
       
   500     public void endEntity(String name) throws org.xml.sax.SAXException
       
   501     {
       
   502         if (name.equals("[dtd]"))
       
   503             m_inExternalDTD = false;
       
   504         m_inEntityRef = false;
       
   505 
       
   506         if (m_tracer != null)
       
   507             this.fireEndEntity(name);
       
   508     }
       
   509 
       
   510     /**
       
   511      * Flush and close the underlying java.io.Writer. This method applies to
       
   512      * ToStream serializers, not ToSAXHandler serializers.
       
   513      * @see ToStream
       
   514      */
       
   515     public void close()
       
   516     {
       
   517         // do nothing (base behavior)
       
   518     }
       
   519 
       
   520     /**
       
   521      * Initialize global variables
       
   522      */
       
   523     protected void initCDATA()
       
   524     {
       
   525         // CDATA stack
       
   526         //        _cdataStack = new Stack();
       
   527         //        _cdataStack.push(new Integer(-1)); // push dummy value
       
   528     }
       
   529 
       
   530     /**
       
   531      * Returns the character encoding to be used in the output document.
       
   532      * @return the character encoding to be used in the output document.
       
   533      */
       
   534     public String getEncoding()
       
   535     {
       
   536         return m_encoding;
       
   537     }
       
   538 
       
   539    /**
       
   540      * Sets the character encoding coming from the xsl:output encoding stylesheet attribute.
       
   541      * @param m_encoding the character encoding
       
   542      */
       
   543     public void setEncoding(String m_encoding)
       
   544     {
       
   545         this.m_encoding = m_encoding;
       
   546     }
       
   547 
       
   548     /**
       
   549      * Sets the value coming from the xsl:output omit-xml-declaration stylesheet attribute
       
   550      * @param b true if the XML declaration is to be omitted from the output
       
   551      * document.
       
   552      */
       
   553     public void setOmitXMLDeclaration(boolean b)
       
   554     {
       
   555         this.m_shouldNotWriteXMLHeader = b;
       
   556     }
       
   557 
       
   558 
       
   559     /**
       
   560      * @return true if the XML declaration is to be omitted from the output
       
   561      * document.
       
   562      */
       
   563     public boolean getOmitXMLDeclaration()
       
   564     {
       
   565         return m_shouldNotWriteXMLHeader;
       
   566     }
       
   567 
       
   568     /**
       
   569      * Returns the previously set value of the value to be used as the public
       
   570      * identifier in the document type declaration (DTD).
       
   571      *
       
   572      *@return the public identifier to be used in the DOCTYPE declaration in the
       
   573      * output document.
       
   574      */
       
   575     public String getDoctypePublic()
       
   576     {
       
   577         return m_doctypePublic;
       
   578     }
       
   579 
       
   580     /** Set the value coming from the xsl:output doctype-public stylesheet attribute.
       
   581       * @param doctypePublic the public identifier to be used in the DOCTYPE
       
   582       * declaration in the output document.
       
   583       */
       
   584     public void setDoctypePublic(String doctypePublic)
       
   585     {
       
   586         this.m_doctypePublic = doctypePublic;
       
   587     }
       
   588 
       
   589 
       
   590     /**
       
   591      * Returns the previously set value of the value to be used
       
   592      * as the system identifier in the document type declaration (DTD).
       
   593          * @return the system identifier to be used in the DOCTYPE declaration in
       
   594          * the output document.
       
   595      *
       
   596      */
       
   597     public String getDoctypeSystem()
       
   598     {
       
   599         return m_doctypeSystem;
       
   600     }
       
   601 
       
   602     /** Set the value coming from the xsl:output doctype-system stylesheet attribute.
       
   603       * @param doctypeSystem the system identifier to be used in the DOCTYPE
       
   604       * declaration in the output document.
       
   605       */
       
   606     public void setDoctypeSystem(String doctypeSystem)
       
   607     {
       
   608         this.m_doctypeSystem = doctypeSystem;
       
   609     }
       
   610 
       
   611     /** Set the value coming from the xsl:output doctype-public and doctype-system stylesheet properties
       
   612      * @param doctypeSystem the system identifier to be used in the DOCTYPE
       
   613      * declaration in the output document.
       
   614      * @param doctypePublic the public identifier to be used in the DOCTYPE
       
   615      * declaration in the output document.
       
   616      */
       
   617     public void setDoctype(String doctypeSystem, String doctypePublic)
       
   618     {
       
   619         this.m_doctypeSystem = doctypeSystem;
       
   620         this.m_doctypePublic = doctypePublic;
       
   621     }
       
   622 
       
   623     /**
       
   624      * Sets the value coming from the xsl:output standalone stylesheet attribute.
       
   625      * @param standalone a value of "yes" indicates that the
       
   626      * <code>standalone</code> delaration is to be included in the output
       
   627      * document. This method remembers if the value was explicitly set using
       
   628      * this method, verses if the value is the default value.
       
   629      */
       
   630     public void setStandalone(String standalone)
       
   631     {
       
   632         if (standalone != null)
       
   633         {
       
   634             m_standaloneWasSpecified = true;
       
   635             setStandaloneInternal(standalone);
       
   636         }
       
   637     }
       
   638     /**
       
   639      * Sets the XSL standalone attribute, but does not remember if this is a
       
   640      * default or explicite setting.
       
   641      * @param standalone "yes" | "no"
       
   642      */
       
   643     protected void setStandaloneInternal(String standalone)
       
   644     {
       
   645         if ("yes".equals(standalone))
       
   646             m_standalone = "yes";
       
   647         else
       
   648             m_standalone = "no";
       
   649 
       
   650     }
       
   651 
       
   652     /**
       
   653      * Gets the XSL standalone attribute
       
   654      * @return a value of "yes" if the <code>standalone</code> delaration is to
       
   655      * be included in the output document.
       
   656      *  @see XSLOutputAttributes#getStandalone()
       
   657      */
       
   658     public String getStandalone()
       
   659     {
       
   660         return m_standalone;
       
   661     }
       
   662 
       
   663     /**
       
   664      * @return true if the output document should be indented to visually
       
   665      * indicate its structure.
       
   666      */
       
   667     public boolean getIndent()
       
   668     {
       
   669         return m_doIndent;
       
   670     }
       
   671     /**
       
   672      * Gets the mediatype the media-type or MIME type associated with the output
       
   673      * document.
       
   674      * @return the mediatype the media-type or MIME type associated with the
       
   675      * output document.
       
   676      */
       
   677     public String getMediaType()
       
   678     {
       
   679         return m_mediatype;
       
   680     }
       
   681 
       
   682     /**
       
   683      * Gets the version of the output format.
       
   684      * @return the version of the output format.
       
   685      */
       
   686     public String getVersion()
       
   687     {
       
   688         return m_version;
       
   689     }
       
   690 
       
   691     /**
       
   692      * Sets the value coming from the xsl:output version attribute.
       
   693      * @param version the version of the output format.
       
   694      * @see SerializationHandler#setVersion(String)
       
   695      */
       
   696     public void setVersion(String version)
       
   697     {
       
   698         m_version = version;
       
   699     }
       
   700 
       
   701     /**
       
   702      * Sets the value coming from the xsl:output media-type stylesheet attribute.
       
   703      * @param mediaType the non-null media-type or MIME type associated with the
       
   704      * output document.
       
   705      * @see javax.xml.transform.OutputKeys#MEDIA_TYPE
       
   706      * @see SerializationHandler#setMediaType(String)
       
   707      */
       
   708     public void setMediaType(String mediaType)
       
   709     {
       
   710         m_mediatype = mediaType;
       
   711     }
       
   712 
       
   713     /**
       
   714      * @return the number of spaces to indent for each indentation level.
       
   715      */
       
   716     public int getIndentAmount()
       
   717     {
       
   718         return m_indentAmount;
       
   719     }
       
   720 
       
   721     /**
       
   722      * Sets the indentation amount.
       
   723      * @param m_indentAmount The m_indentAmount to set
       
   724      */
       
   725     public void setIndentAmount(int m_indentAmount)
       
   726     {
       
   727         this.m_indentAmount = m_indentAmount;
       
   728     }
       
   729 
       
   730     /**
       
   731      * Sets the value coming from the xsl:output indent stylesheet
       
   732      * attribute.
       
   733      * @param doIndent true if the output document should be indented to
       
   734      * visually indicate its structure.
       
   735      * @see XSLOutputAttributes#setIndent(boolean)
       
   736      */
       
   737     public void setIndent(boolean doIndent)
       
   738     {
       
   739         m_doIndent = doIndent;
       
   740     }
       
   741 
       
   742     /**
       
   743      * This method is used when a prefix/uri namespace mapping
       
   744      * is indicated after the element was started with a
       
   745      * startElement() and before and endElement().
       
   746      * startPrefixMapping(prefix,uri) would be used before the
       
   747      * startElement() call.
       
   748      * @param uri the URI of the namespace
       
   749      * @param prefix the prefix associated with the given URI.
       
   750      *
       
   751      * @see ExtendedContentHandler#namespaceAfterStartElement(String, String)
       
   752      */
       
   753     public void namespaceAfterStartElement(String uri, String prefix)
       
   754         throws SAXException
       
   755     {
       
   756         // default behavior is to do nothing
       
   757     }
       
   758 
       
   759     /**
       
   760      * Return a {@link DOMSerializer} interface into this serializer. If the
       
   761      * serializer does not support the {@link DOMSerializer} interface, it should
       
   762      * return null.
       
   763      *
       
   764      * @return A {@link DOMSerializer} interface into this serializer,  or null
       
   765      * if the serializer is not DOM capable
       
   766      * @throws IOException An I/O exception occured
       
   767      * @see Serializer#asDOMSerializer()
       
   768      */
       
   769     public DOMSerializer asDOMSerializer() throws IOException
       
   770     {
       
   771         return this;
       
   772     }
       
   773 
       
   774     /**
       
   775      * Push a boolean state based on if the name of the current element
       
   776      * is found in the list of qnames.  A state is only pushed if
       
   777      * there were some cdata-section-names were specified.
       
   778      * <p>
       
   779      * Hidden parameters are the vector of qualified elements specified in
       
   780      * cdata-section-names attribute, and the m_cdataSectionStates stack
       
   781      * onto which whether the current element is in the list is pushed (true or
       
   782      * false). Other hidden parameters are the current elements namespaceURI,
       
   783      * localName and qName
       
   784      */
       
   785     protected boolean isCdataSection()
       
   786     {
       
   787 
       
   788         boolean b = false;
       
   789 
       
   790         if (null != m_cdataSectionElements)
       
   791         {
       
   792             if (m_elemContext.m_elementLocalName == null)
       
   793                 m_elemContext.m_elementLocalName =
       
   794                     getLocalName(m_elemContext.m_elementName);
       
   795             if (m_elemContext.m_elementURI == null)
       
   796             {
       
   797                 String prefix = getPrefixPart(m_elemContext.m_elementName);
       
   798                 if (prefix != null)
       
   799                     m_elemContext.m_elementURI =
       
   800                         m_prefixMap.lookupNamespace(prefix);
       
   801 
       
   802             }
       
   803 
       
   804             if ((null != m_elemContext.m_elementURI)
       
   805                 && m_elemContext.m_elementURI.length() == 0)
       
   806                 m_elemContext.m_elementURI = null;
       
   807 
       
   808             int nElems = m_cdataSectionElements.size();
       
   809 
       
   810             // loop through 2 at a time, as these are pairs of URI and localName
       
   811             for (int i = 0; i < nElems; i += 2)
       
   812             {
       
   813                 String uri = (String) m_cdataSectionElements.elementAt(i);
       
   814                 String loc = (String) m_cdataSectionElements.elementAt(i + 1);
       
   815                 if (loc.equals(m_elemContext.m_elementLocalName)
       
   816                     && subPartMatch(m_elemContext.m_elementURI, uri))
       
   817                 {
       
   818                     b = true;
       
   819 
       
   820                     break;
       
   821                 }
       
   822             }
       
   823         }
       
   824         return b;
       
   825     }
       
   826 
       
   827     /**
       
   828      * Tell if two strings are equal, without worry if the first string is null.
       
   829      *
       
   830      * @param p String reference, which may be null.
       
   831      * @param t String reference, which may be null.
       
   832      *
       
   833      * @return true if strings are equal.
       
   834      */
       
   835     private static final boolean subPartMatch(String p, String t)
       
   836     {
       
   837         return (p == t) || ((null != p) && (p.equals(t)));
       
   838     }
       
   839 
       
   840     /**
       
   841      * Returns the local name of a qualified name.
       
   842      * If the name has no prefix,
       
   843      * then it works as the identity (SAX2).
       
   844      *
       
   845      * @param qname a qualified name
       
   846      * @return returns the prefix of the qualified name,
       
   847      * or null if there is no prefix.
       
   848      */
       
   849     protected static final String getPrefixPart(String qname)
       
   850     {
       
   851         final int col = qname.indexOf(':');
       
   852         return (col > 0) ? qname.substring(0, col) : null;
       
   853         //return (col > 0) ? qname.substring(0,col) : "";
       
   854     }
       
   855 
       
   856     /**
       
   857      * Some users of the serializer may need the current namespace mappings
       
   858      * @return the current namespace mappings (prefix/uri)
       
   859      * @see ExtendedContentHandler#getNamespaceMappings()
       
   860      */
       
   861     public NamespaceMappings getNamespaceMappings()
       
   862     {
       
   863         return m_prefixMap;
       
   864     }
       
   865 
       
   866     /**
       
   867      * Returns the prefix currently pointing to the given URI (if any).
       
   868      * @param namespaceURI the uri of the namespace in question
       
   869      * @return a prefix pointing to the given URI (if any).
       
   870      * @see ExtendedContentHandler#getPrefix(String)
       
   871      */
       
   872     public String getPrefix(String namespaceURI)
       
   873     {
       
   874         String prefix = m_prefixMap.lookupPrefix(namespaceURI);
       
   875         return prefix;
       
   876     }
       
   877 
       
   878     /**
       
   879      * Returns the URI of an element or attribute. Note that default namespaces
       
   880      * do not apply directly to attributes.
       
   881      * @param qname a qualified name
       
   882      * @param isElement true if the qualified name is the name of
       
   883      * an element.
       
   884      * @return returns the namespace URI associated with the qualified name.
       
   885      */
       
   886     public String getNamespaceURI(String qname, boolean isElement)
       
   887     {
       
   888         String uri = EMPTYSTRING;
       
   889         int col = qname.lastIndexOf(':');
       
   890         final String prefix = (col > 0) ? qname.substring(0, col) : EMPTYSTRING;
       
   891 
       
   892         if (!EMPTYSTRING.equals(prefix) || isElement)
       
   893         {
       
   894             if (m_prefixMap != null)
       
   895             {
       
   896                 uri = m_prefixMap.lookupNamespace(prefix);
       
   897                 if (uri == null && !prefix.equals(XMLNS_PREFIX))
       
   898                 {
       
   899                     throw new RuntimeException(
       
   900                         Utils.messages.createMessage(
       
   901                             MsgKey.ER_NAMESPACE_PREFIX,
       
   902                             new Object[] { qname.substring(0, col) }  ));
       
   903                 }
       
   904             }
       
   905         }
       
   906         return uri;
       
   907     }
       
   908 
       
   909     /**
       
   910      * Returns the URI of prefix (if any)
       
   911      *
       
   912          * @param prefix the prefix whose URI is searched for
       
   913      * @return the namespace URI currently associated with the
       
   914      * prefix, null if the prefix is undefined.
       
   915      */
       
   916     public String getNamespaceURIFromPrefix(String prefix)
       
   917     {
       
   918         String uri = null;
       
   919         if (m_prefixMap != null)
       
   920             uri = m_prefixMap.lookupNamespace(prefix);
       
   921         return uri;
       
   922     }
       
   923 
       
   924     /**
       
   925      * Entity reference event.
       
   926      *
       
   927      * @param name Name of entity
       
   928      *
       
   929      * @throws org.xml.sax.SAXException
       
   930      */
       
   931     public void entityReference(String name) throws org.xml.sax.SAXException
       
   932     {
       
   933 
       
   934         flushPending();
       
   935 
       
   936         startEntity(name);
       
   937         endEntity(name);
       
   938 
       
   939         if (m_tracer != null)
       
   940                     fireEntityReference(name);
       
   941     }
       
   942 
       
   943     /**
       
   944      * Sets the transformer associated with this serializer
       
   945      * @param t the transformer associated with this serializer.
       
   946      * @see SerializationHandler#setTransformer(Transformer)
       
   947      */
       
   948     public void setTransformer(Transformer t)
       
   949     {
       
   950         m_transformer = t;
       
   951 
       
   952         // If this transformer object implements the SerializerTrace interface
       
   953         // then assign m_tracer to the transformer object so it can be used
       
   954         // to fire trace events.
       
   955         if ((m_transformer instanceof SerializerTrace) &&
       
   956             (((SerializerTrace) m_transformer).hasTraceListeners())) {
       
   957            m_tracer = (SerializerTrace) m_transformer;
       
   958         } else {
       
   959            m_tracer = null;
       
   960         }
       
   961     }
       
   962     /**
       
   963      * Gets the transformer associated with this serializer
       
   964      * @return returns the transformer associated with this serializer.
       
   965      * @see SerializationHandler#getTransformer()
       
   966      */
       
   967     public Transformer getTransformer()
       
   968     {
       
   969         return m_transformer;
       
   970     }
       
   971 
       
   972     /**
       
   973      * This method gets the nodes value as a String and uses that String as if
       
   974      * it were an input character notification.
       
   975      * @param node the Node to serialize
       
   976      * @throws org.xml.sax.SAXException
       
   977      */
       
   978     public void characters(org.w3c.dom.Node node)
       
   979         throws org.xml.sax.SAXException
       
   980     {
       
   981         flushPending();
       
   982         String data = node.getNodeValue();
       
   983         if (data != null)
       
   984         {
       
   985             final int length = data.length();
       
   986             if (length > m_charsBuff.length)
       
   987             {
       
   988                 m_charsBuff = new char[length * 2 + 1];
       
   989             }
       
   990             data.getChars(0, length, m_charsBuff, 0);
       
   991             characters(m_charsBuff, 0, length);
       
   992         }
       
   993     }
       
   994 
       
   995 
       
   996     /**
       
   997      * @see org.xml.sax.ErrorHandler#error(SAXParseException)
       
   998      */
       
   999     public void error(SAXParseException exc) throws SAXException {
       
  1000     }
       
  1001 
       
  1002     /**
       
  1003      * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException)
       
  1004      */
       
  1005     public void fatalError(SAXParseException exc) throws SAXException {
       
  1006 
       
  1007       m_elemContext.m_startTagOpen = false;
       
  1008 
       
  1009     }
       
  1010 
       
  1011     /**
       
  1012      * @see org.xml.sax.ErrorHandler#warning(SAXParseException)
       
  1013      */
       
  1014     public void warning(SAXParseException exc) throws SAXException
       
  1015     {
       
  1016     }
       
  1017 
       
  1018     /**
       
  1019      * To fire off start entity trace event
       
  1020      * @param name Name of entity
       
  1021      */
       
  1022     protected void fireStartEntity(String name)
       
  1023         throws org.xml.sax.SAXException
       
  1024     {
       
  1025         if (m_tracer != null)
       
  1026         {
       
  1027             flushMyWriter();
       
  1028             m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENTITYREF, name);
       
  1029         }
       
  1030     }
       
  1031 
       
  1032     /**
       
  1033      * Report the characters event
       
  1034      * @param chars  content of characters
       
  1035      * @param start  starting index of characters to output
       
  1036      * @param length  number of characters to output
       
  1037      */
       
  1038 //    protected void fireCharEvent(char[] chars, int start, int length)
       
  1039 //        throws org.xml.sax.SAXException
       
  1040 //    {
       
  1041 //        if (m_tracer != null)
       
  1042 //            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CHARACTERS, chars, start,length);
       
  1043 //    }
       
  1044 //
       
  1045 
       
  1046     /**
       
  1047      * This method is only used internally when flushing the writer from the
       
  1048      * various fire...() trace events.  Due to the writer being wrapped with
       
  1049      * SerializerTraceWriter it may cause the flush of these trace events:
       
  1050      * EVENTTYPE_OUTPUT_PSEUDO_CHARACTERS
       
  1051      * EVENTTYPE_OUTPUT_CHARACTERS
       
  1052      * which trace the output written to the output stream.
       
  1053      *
       
  1054      */
       
  1055     private void flushMyWriter()
       
  1056     {
       
  1057         if (m_writer != null)
       
  1058         {
       
  1059             try
       
  1060             {
       
  1061                 m_writer.flush();
       
  1062             }
       
  1063             catch(IOException ioe)
       
  1064             {
       
  1065 
       
  1066             }
       
  1067         }
       
  1068     }
       
  1069     /**
       
  1070      * Report the CDATA trace event
       
  1071      * @param chars  content of CDATA
       
  1072      * @param start  starting index of characters to output
       
  1073      * @param length  number of characters to output
       
  1074      */
       
  1075     protected void fireCDATAEvent(char[] chars, int start, int length)
       
  1076         throws org.xml.sax.SAXException
       
  1077     {
       
  1078                 if (m_tracer != null)
       
  1079         {
       
  1080             flushMyWriter();
       
  1081                         m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_CDATA, chars, start,length);
       
  1082         }
       
  1083     }
       
  1084 
       
  1085     /**
       
  1086      * Report the comment trace event
       
  1087      * @param chars  content of comment
       
  1088      * @param start  starting index of comment to output
       
  1089      * @param length  number of characters to output
       
  1090      */
       
  1091     protected void fireCommentEvent(char[] chars, int start, int length)
       
  1092         throws org.xml.sax.SAXException
       
  1093     {
       
  1094                 if (m_tracer != null)
       
  1095         {
       
  1096             flushMyWriter();
       
  1097                         m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_COMMENT, new String(chars, start, length));
       
  1098         }
       
  1099     }
       
  1100 
       
  1101 
       
  1102     /**
       
  1103      * To fire off end entity trace event
       
  1104      * @param name Name of entity
       
  1105      */
       
  1106     public void fireEndEntity(String name)
       
  1107         throws org.xml.sax.SAXException
       
  1108     {
       
  1109         if (m_tracer != null)
       
  1110             flushMyWriter();
       
  1111         // we do not need to handle this.
       
  1112     }
       
  1113 
       
  1114     /**
       
  1115      * To fire off start document trace  event
       
  1116      */
       
  1117      protected void fireStartDoc()
       
  1118         throws org.xml.sax.SAXException
       
  1119     {
       
  1120         if (m_tracer != null)
       
  1121         {
       
  1122             flushMyWriter();
       
  1123             m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_STARTDOCUMENT);
       
  1124         }
       
  1125     }
       
  1126 
       
  1127 
       
  1128     /**
       
  1129      * To fire off end document trace event
       
  1130      */
       
  1131     protected void fireEndDoc()
       
  1132         throws org.xml.sax.SAXException
       
  1133     {
       
  1134         if (m_tracer != null)
       
  1135         {
       
  1136             flushMyWriter();
       
  1137             m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDDOCUMENT);
       
  1138         }
       
  1139     }
       
  1140 
       
  1141     /**
       
  1142      * Report the start element trace event. This trace method needs to be
       
  1143      * called just before the attributes are cleared.
       
  1144      *
       
  1145      * @param elemName the qualified name of the element
       
  1146      *
       
  1147      */
       
  1148     protected void fireStartElem(String elemName)
       
  1149         throws org.xml.sax.SAXException
       
  1150     {
       
  1151         if (m_tracer != null)
       
  1152         {
       
  1153             flushMyWriter();
       
  1154             m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_STARTELEMENT,
       
  1155                 elemName, m_attributes);
       
  1156         }
       
  1157     }
       
  1158 
       
  1159 
       
  1160     /**
       
  1161      * To fire off the end element event
       
  1162      * @param name Name of element
       
  1163      */
       
  1164 //    protected void fireEndElem(String name)
       
  1165 //        throws org.xml.sax.SAXException
       
  1166 //    {
       
  1167 //        if (m_tracer != null)
       
  1168 //            m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENDELEMENT,name, (Attributes)null);
       
  1169 //    }
       
  1170 
       
  1171 
       
  1172     /**
       
  1173      * To fire off the PI trace event
       
  1174      * @param name Name of PI
       
  1175      */
       
  1176     protected void fireEscapingEvent(String name, String data)
       
  1177         throws org.xml.sax.SAXException
       
  1178     {
       
  1179 
       
  1180         if (m_tracer != null)
       
  1181         {
       
  1182             flushMyWriter();
       
  1183             m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_PI,name, data);
       
  1184         }
       
  1185     }
       
  1186 
       
  1187 
       
  1188     /**
       
  1189      * To fire off the entity reference trace event
       
  1190      * @param name Name of entity reference
       
  1191      */
       
  1192     protected void fireEntityReference(String name)
       
  1193         throws org.xml.sax.SAXException
       
  1194     {
       
  1195         if (m_tracer != null)
       
  1196         {
       
  1197             flushMyWriter();
       
  1198             m_tracer.fireGenerateEvent(SerializerTrace.EVENTTYPE_ENTITYREF,name, (Attributes)null);
       
  1199         }
       
  1200     }
       
  1201 
       
  1202     /**
       
  1203      * Receive notification of the beginning of a document.
       
  1204      * This method is never a self generated call,
       
  1205      * but only called externally.
       
  1206      *
       
  1207      * <p>The SAX parser will invoke this method only once, before any
       
  1208      * other methods in this interface or in DTDHandler (except for
       
  1209      * setDocumentLocator).</p>
       
  1210      *
       
  1211      * @throws org.xml.sax.SAXException Any SAX exception, possibly
       
  1212      *            wrapping another exception.
       
  1213      *
       
  1214      * @throws org.xml.sax.SAXException
       
  1215      */
       
  1216     public void startDocument() throws org.xml.sax.SAXException
       
  1217     {
       
  1218 
       
  1219         // if we do get called with startDocument(), handle it right away
       
  1220         startDocumentInternal();
       
  1221         m_needToCallStartDocument = false;
       
  1222         return;
       
  1223     }
       
  1224 
       
  1225     /**
       
  1226      * This method handles what needs to be done at a startDocument() call,
       
  1227      * whether from an external caller, or internally called in the
       
  1228      * serializer.  For historical reasons the serializer is flexible to
       
  1229      * startDocument() not always being called.
       
  1230      * Even if no external call is
       
  1231      * made into startDocument() this method will always be called as a self
       
  1232      * generated internal startDocument, it handles what needs to be done at a
       
  1233      * startDocument() call.
       
  1234      *
       
  1235      * This method exists just to make sure that startDocument() is only ever
       
  1236      * called from an external caller, which in principle is just a matter of
       
  1237      * style.
       
  1238      *
       
  1239      * @throws SAXException
       
  1240      */
       
  1241     protected void startDocumentInternal() throws org.xml.sax.SAXException
       
  1242     {
       
  1243         if (m_tracer != null)
       
  1244             this.fireStartDoc();
       
  1245 
       
  1246     }
       
  1247 
       
  1248     /* This method extracts version and encoding information from SAX events.
       
  1249      */
       
  1250     protected void setDocumentInfo() {
       
  1251         if (m_locator == null)
       
  1252                 return;
       
  1253         try{
       
  1254             String strVersion = ((Locator2)m_locator).getXMLVersion();
       
  1255             if (strVersion != null)
       
  1256                 setVersion(strVersion);
       
  1257             /*String strEncoding = ((Locator2)m_locator).getEncoding();
       
  1258             if (strEncoding != null)
       
  1259                 setEncoding(strEncoding); */
       
  1260 
       
  1261         }catch(ClassCastException e){}
       
  1262     }
       
  1263 
       
  1264     /**
       
  1265      * This method is used to set the source locator, which might be used to
       
  1266      * generated an error message.
       
  1267      * @param locator the source locator
       
  1268      *
       
  1269      * @see ExtendedContentHandler#setSourceLocator(javax.xml.transform.SourceLocator)
       
  1270      */
       
  1271     public void setSourceLocator(SourceLocator locator)
       
  1272     {
       
  1273         m_sourceLocator = locator;
       
  1274     }
       
  1275 
       
  1276 
       
  1277     /**
       
  1278      * Used only by TransformerSnapshotImpl to restore the serialization
       
  1279      * to a previous state.
       
  1280      *
       
  1281      * @param mappings NamespaceMappings
       
  1282      */
       
  1283     public void setNamespaceMappings(NamespaceMappings mappings) {
       
  1284         m_prefixMap = mappings;
       
  1285     }
       
  1286 
       
  1287     public boolean reset()
       
  1288     {
       
  1289         resetSerializerBase();
       
  1290         return true;
       
  1291     }
       
  1292 
       
  1293     /**
       
  1294      * Reset all of the fields owned by SerializerBase
       
  1295      *
       
  1296      */
       
  1297     private void resetSerializerBase()
       
  1298     {
       
  1299         this.m_attributes.clear();
       
  1300         this.m_cdataSectionElements = null;
       
  1301         this.m_elemContext = new ElemContext();
       
  1302         this.m_doctypePublic = null;
       
  1303         this.m_doctypeSystem = null;
       
  1304         this.m_doIndent = false;
       
  1305         this.m_encoding = null;
       
  1306         this.m_indentAmount = 0;
       
  1307         this.m_inEntityRef = false;
       
  1308         this.m_inExternalDTD = false;
       
  1309         this.m_mediatype = null;
       
  1310         this.m_needToCallStartDocument = true;
       
  1311         this.m_needToOutputDocTypeDecl = false;
       
  1312         if (this.m_prefixMap != null)
       
  1313             this.m_prefixMap.reset();
       
  1314         this.m_shouldNotWriteXMLHeader = false;
       
  1315         this.m_sourceLocator = null;
       
  1316         this.m_standalone = null;
       
  1317         this.m_standaloneWasSpecified = false;
       
  1318         this.m_tracer = null;
       
  1319         this.m_transformer = null;
       
  1320         this.m_version = null;
       
  1321         // don't set writer to null, so that it might be re-used
       
  1322         //this.m_writer = null;
       
  1323     }
       
  1324 
       
  1325     /**
       
  1326      * Returns true if the serializer is used for temporary output rather than
       
  1327      * final output.
       
  1328      *
       
  1329      * This concept is made clear in the XSLT 2.0 draft.
       
  1330      */
       
  1331     final boolean inTemporaryOutputState()
       
  1332     {
       
  1333         /* This is a hack. We should really be letting the serializer know
       
  1334          * that it is in temporary output state with an explicit call, but
       
  1335          * from a pragmatic point of view (for now anyways) having no output
       
  1336          * encoding at all, not even the default UTF-8 indicates that the serializer
       
  1337          * is being used for temporary RTF.
       
  1338          */
       
  1339         return (getEncoding() == null);
       
  1340 
       
  1341     }
       
  1342 
       
  1343     /**
       
  1344      * This method adds an attribute the the current element,
       
  1345      * but should not be used for an xsl:attribute child.
       
  1346      * @see ExtendedContentHandler#addAttribute(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
       
  1347      */
       
  1348     public void addAttribute(String uri, String localName, String rawName, String type, String value) throws SAXException
       
  1349     {
       
  1350         if (m_elemContext.m_startTagOpen)
       
  1351         {
       
  1352             addAttributeAlways(uri, localName, rawName, type, value, false);
       
  1353         }
       
  1354     }
       
  1355 
       
  1356     /**
       
  1357      * @see org.xml.sax.DTDHandler#notationDecl(java.lang.String, java.lang.String, java.lang.String)
       
  1358      */
       
  1359     public void notationDecl(String arg0, String arg1, String arg2)
       
  1360         throws SAXException {
       
  1361         // This method just provides a definition to satisfy the interface
       
  1362         // A particular sub-class of SerializerBase provides the implementation (if desired)
       
  1363     }
       
  1364 
       
  1365     /**
       
  1366      * @see org.xml.sax.DTDHandler#unparsedEntityDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
       
  1367      */
       
  1368     public void unparsedEntityDecl(
       
  1369         String arg0,
       
  1370         String arg1,
       
  1371         String arg2,
       
  1372         String arg3)
       
  1373         throws SAXException {
       
  1374         // This method just provides a definition to satisfy the interface
       
  1375         // A particular sub-class of SerializerBase provides the implementation (if desired)
       
  1376     }
       
  1377 
       
  1378     /**
       
  1379      * If set to false the serializer does not expand DTD entities,
       
  1380      * but leaves them as is, the default value is true.
       
  1381      */
       
  1382     public void setDTDEntityExpansion(boolean expand) {
       
  1383         // This method just provides a definition to satisfy the interface
       
  1384         // A particular sub-class of SerializerBase provides the implementation (if desired)
       
  1385     }
       
  1386 
       
  1387 }