Save This Page
Home » openjdk-7 » com.sun.org.apache.xml.internal » serializer » [javadoc | source]
    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: ToXMLStream.java,v 1.2.4.2 2005/09/15 12:01:25 suresh_emailid Exp $
   22    */
   23   package com.sun.org.apache.xml.internal.serializer;
   24   
   25   import java.io.IOException;
   26   
   27   import javax.xml.transform.ErrorListener;
   28   import javax.xml.transform.Result;
   29   import javax.xml.transform.Transformer;
   30   import javax.xml.transform.TransformerException;
   31   
   32   import com.sun.org.apache.xml.internal.serializer.utils.MsgKey;
   33   import com.sun.org.apache.xml.internal.serializer.utils.Utils;
   34   import org.xml.sax.SAXException;
   35   
   36   /**
   37    * This class converts SAX or SAX-like calls to a
   38    * serialized xml document.  The xsl:output method is "xml".
   39    *
   40    * This class is used explicitly in code generated by XSLTC,
   41    * so it is "public", but it should
   42    * be viewed as internal or package private, this is not an API.
   43    *
   44    * @xsl.usage internal
   45    */
   46   public final class ToXMLStream extends ToStream
   47   {
   48   
   49       /**
   50        * remembers if we need to write out "]]>" to close the CDATA
   51        */
   52       boolean m_cdataTagOpen = false;
   53   
   54   
   55       /**
   56        * Map that tells which XML characters should have special treatment, and it
   57        *  provides character to entity name lookup.
   58        */
   59       private static CharInfo m_xmlcharInfo =
   60   //      new CharInfo(CharInfo.XML_ENTITIES_RESOURCE);
   61           CharInfo.getCharInfo(CharInfo.XML_ENTITIES_RESOURCE, Method.XML);
   62   
   63       /**
   64        * Default constructor.
   65        */
   66       public ToXMLStream()
   67       {
   68           m_charInfo = m_xmlcharInfo;
   69   
   70           initCDATA();
   71           // initialize namespaces
   72           m_prefixMap = new NamespaceMappings();
   73   
   74       }
   75   
   76       /**
   77        * Copy properties from another SerializerToXML.
   78        *
   79        * @param xmlListener non-null reference to a SerializerToXML object.
   80        */
   81       public void CopyFrom(ToXMLStream xmlListener)
   82       {
   83   
   84           m_writer = xmlListener.m_writer;
   85   
   86   
   87           // m_outputStream = xmlListener.m_outputStream;
   88           String encoding = xmlListener.getEncoding();
   89           setEncoding(encoding);
   90   
   91           setOmitXMLDeclaration(xmlListener.getOmitXMLDeclaration());
   92   
   93           m_ispreserve = xmlListener.m_ispreserve;
   94           m_preserves = xmlListener.m_preserves;
   95           m_isprevtext = xmlListener.m_isprevtext;
   96           m_doIndent = xmlListener.m_doIndent;
   97           setIndentAmount(xmlListener.getIndentAmount());
   98           m_startNewLine = xmlListener.m_startNewLine;
   99           m_needToOutputDocTypeDecl = xmlListener.m_needToOutputDocTypeDecl;
  100           setDoctypeSystem(xmlListener.getDoctypeSystem());
  101           setDoctypePublic(xmlListener.getDoctypePublic());
  102           setStandalone(xmlListener.getStandalone());
  103           setMediaType(xmlListener.getMediaType());
  104           m_maxCharacter = xmlListener.m_maxCharacter;
  105           m_encodingInfo = xmlListener.m_encodingInfo;
  106           m_spaceBeforeClose = xmlListener.m_spaceBeforeClose;
  107           m_cdataStartCalled = xmlListener.m_cdataStartCalled;
  108   
  109       }
  110   
  111       /**
  112        * Receive notification of the beginning of a document.
  113        *
  114        * @throws org.xml.sax.SAXException Any SAX exception, possibly
  115        *            wrapping another exception.
  116        *
  117        * @throws org.xml.sax.SAXException
  118        */
  119       public void startDocumentInternal() throws org.xml.sax.SAXException
  120       {
  121   
  122           if (m_needToCallStartDocument)
  123           {
  124               super.startDocumentInternal();
  125               m_needToCallStartDocument = false;
  126   
  127               if (m_inEntityRef)
  128                   return;
  129   
  130               m_needToOutputDocTypeDecl = true;
  131               m_startNewLine = false;
  132               /* The call to getXMLVersion() might emit an error message
  133                * and we should emit this message regardless of if we are
  134                * writing out an XML header or not.
  135                */
  136               if (getOmitXMLDeclaration() == false)
  137               {
  138                   String encoding = Encodings.getMimeEncoding(getEncoding());
  139                   String version = getVersion();
  140                   if (version == null)
  141                       version = "1.0";
  142                   String standalone;
  143   
  144                   if (m_standaloneWasSpecified)
  145                   {
  146                       standalone = " standalone=\"" + getStandalone() + "\"";
  147                   }
  148                   else
  149                   {
  150                       standalone = "";
  151                   }
  152   
  153                   try
  154                   {
  155                       final java.io.Writer writer = m_writer;
  156                       writer.write("<?xml version=\"");
  157                       writer.write(version);
  158                       writer.write("\" encoding=\"");
  159                       writer.write(encoding);
  160                       writer.write('\"');
  161                       writer.write(standalone);
  162                       writer.write("?>");
  163                       if (m_doIndent)
  164                           writer.write(m_lineSep, 0, m_lineSepLen);
  165                   }
  166                   catch(IOException e)
  167                   {
  168                       throw new SAXException(e);
  169                   }
  170   
  171               }
  172           }
  173       }
  174   
  175       /**
  176        * Receive notification of the end of a document.
  177        *
  178        * @throws org.xml.sax.SAXException Any SAX exception, possibly
  179        *            wrapping another exception.
  180        *
  181        * @throws org.xml.sax.SAXException
  182        */
  183       public void endDocument() throws org.xml.sax.SAXException
  184       {
  185           flushPending();
  186           if (m_doIndent && !m_isprevtext)
  187           {
  188               try
  189               {
  190               outputLineSep();
  191               }
  192               catch(IOException e)
  193               {
  194                   throw new SAXException(e);
  195               }
  196           }
  197   
  198           flushWriter();
  199   
  200           if (m_tracer != null)
  201               super.fireEndDoc();
  202       }
  203   
  204       /**
  205        * Starts a whitespace preserving section. All characters printed
  206        * within a preserving section are printed without indentation and
  207        * without consolidating multiple spaces. This is equivalent to
  208        * the <tt>xml:space=&quot;preserve&quot;</tt> attribute. Only XML
  209        * and HTML serializers need to support this method.
  210        * <p>
  211        * The contents of the whitespace preserving section will be delivered
  212        * through the regular <tt>characters</tt> event.
  213        *
  214        * @throws org.xml.sax.SAXException
  215        */
  216       public void startPreserving() throws org.xml.sax.SAXException
  217       {
  218   
  219           // Not sure this is really what we want.  -sb
  220           m_preserves.push(true);
  221   
  222           m_ispreserve = true;
  223       }
  224   
  225       /**
  226        * Ends a whitespace preserving section.
  227        *
  228        * @see #startPreserving
  229        *
  230        * @throws org.xml.sax.SAXException
  231        */
  232       public void endPreserving() throws org.xml.sax.SAXException
  233       {
  234   
  235           // Not sure this is really what we want.  -sb
  236           m_ispreserve = m_preserves.isEmpty() ? false : m_preserves.pop();
  237       }
  238   
  239       /**
  240        * Receive notification of a processing instruction.
  241        *
  242        * @param target The processing instruction target.
  243        * @param data The processing instruction data, or null if
  244        *        none was supplied.
  245        * @throws org.xml.sax.SAXException Any SAX exception, possibly
  246        *            wrapping another exception.
  247        *
  248        * @throws org.xml.sax.SAXException
  249        */
  250       public void processingInstruction(String target, String data)
  251           throws org.xml.sax.SAXException
  252       {
  253           if (m_inEntityRef)
  254               return;
  255   
  256           flushPending();
  257   
  258           if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING))
  259           {
  260               startNonEscaping();
  261           }
  262           else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING))
  263           {
  264               endNonEscaping();
  265           }
  266           else
  267           {
  268               try
  269               {
  270                   if (m_elemContext.m_startTagOpen)
  271                   {
  272                       closeStartTag();
  273                       m_elemContext.m_startTagOpen = false;
  274                   }
  275                   else if (m_needToCallStartDocument)
  276                       startDocumentInternal();
  277   
  278                   if (shouldIndent())
  279                       indent();
  280   
  281                   final java.io.Writer writer = m_writer;
  282                   writer.write("<?");
  283                   writer.write(target);
  284   
  285                   if (data.length() > 0
  286                       && !Character.isSpaceChar(data.charAt(0)))
  287                       writer.write(' ');
  288   
  289                   int indexOfQLT = data.indexOf("?>");
  290   
  291                   if (indexOfQLT >= 0)
  292                   {
  293   
  294                       // See XSLT spec on error recovery of "?>" in PIs.
  295                       if (indexOfQLT > 0)
  296                       {
  297                           writer.write(data.substring(0, indexOfQLT));
  298                       }
  299   
  300                       writer.write("? >"); // add space between.
  301   
  302                       if ((indexOfQLT + 2) < data.length())
  303                       {
  304                           writer.write(data.substring(indexOfQLT + 2));
  305                       }
  306                   }
  307                   else
  308                   {
  309                       writer.write(data);
  310                   }
  311   
  312                   writer.write('?');
  313                   writer.write('>');
  314   
  315                   // Always output a newline char if not inside of an
  316                   // element. The whitespace is not significant in that
  317                   // case.
  318                   if (m_elemContext.m_currentElemDepth <= 0)
  319                       writer.write(m_lineSep, 0, m_lineSepLen);
  320   
  321                   m_startNewLine = true;
  322               }
  323               catch(IOException e)
  324               {
  325                   throw new SAXException(e);
  326               }
  327           }
  328   
  329           if (m_tracer != null)
  330               super.fireEscapingEvent(target, data);
  331       }
  332   
  333       /**
  334        * Receive notivication of a entityReference.
  335        *
  336        * @param name The name of the entity.
  337        *
  338        * @throws org.xml.sax.SAXException
  339        */
  340       public void entityReference(String name) throws org.xml.sax.SAXException
  341       {
  342           if (m_elemContext.m_startTagOpen)
  343           {
  344               closeStartTag();
  345               m_elemContext.m_startTagOpen = false;
  346           }
  347   
  348           try
  349           {
  350               if (shouldIndent())
  351                   indent();
  352   
  353               final java.io.Writer writer = m_writer;
  354               writer.write('&');
  355               writer.write(name);
  356               writer.write(';');
  357           }
  358           catch(IOException e)
  359           {
  360               throw new SAXException(e);
  361           }
  362   
  363           if (m_tracer != null)
  364               super.fireEntityReference(name);
  365       }
  366   
  367       /**
  368        * This method is used to add an attribute to the currently open element.
  369        * The caller has guaranted that this attribute is unique, which means that it
  370        * not been seen before and will not be seen again.
  371        *
  372        * @param name the qualified name of the attribute
  373        * @param value the value of the attribute which can contain only
  374        * ASCII printable characters characters in the range 32 to 127 inclusive.
  375        * @param flags the bit values of this integer give optimization information.
  376        */
  377       public void addUniqueAttribute(String name, String value, int flags)
  378           throws SAXException
  379       {
  380           if (m_elemContext.m_startTagOpen)
  381           {
  382   
  383               try
  384               {
  385                   final String patchedName = patchName(name);
  386                   final java.io.Writer writer = m_writer;
  387                   if ((flags & NO_BAD_CHARS) > 0 && m_xmlcharInfo.onlyQuotAmpLtGt)
  388                   {
  389                       // "flags" has indicated that the characters
  390                       // '>'  '<'   '&'  and '"' are not in the value and
  391                       // m_htmlcharInfo has recorded that there are no other
  392                       // entities in the range 32 to 127 so we write out the
  393                       // value directly
  394   
  395                       writer.write(' ');
  396                       writer.write(patchedName);
  397                       writer.write("=\"");
  398                       writer.write(value);
  399                       writer.write('"');
  400                   }
  401                   else
  402                   {
  403                       writer.write(' ');
  404                       writer.write(patchedName);
  405                       writer.write("=\"");
  406                       writeAttrString(writer, value, this.getEncoding());
  407                       writer.write('"');
  408                   }
  409               } catch (IOException e) {
  410                   throw new SAXException(e);
  411               }
  412           }
  413       }
  414   
  415       /**
  416        * Add an attribute to the current element.
  417        * @param uri the URI associated with the element name
  418        * @param localName local part of the attribute name
  419        * @param rawName   prefix:localName
  420        * @param type
  421        * @param value the value of the attribute
  422        * @param xslAttribute true if this attribute is from an xsl:attribute,
  423        * false if declared within the elements opening tag.
  424        * @throws SAXException
  425        */
  426       public void addAttribute(
  427           String uri,
  428           String localName,
  429           String rawName,
  430           String type,
  431           String value,
  432           boolean xslAttribute)
  433           throws SAXException
  434       {
  435           if (m_elemContext.m_startTagOpen)
  436           {
  437               boolean was_added = addAttributeAlways(uri, localName, rawName, type, value, xslAttribute);
  438   
  439   
  440               /*
  441                * We don't run this block of code if:
  442                * 1. The attribute value was only replaced (was_added is false).
  443                * 2. The attribute is from an xsl:attribute element (that is handled
  444                *    in the addAttributeAlways() call just above.
  445                * 3. The name starts with "xmlns", i.e. it is a namespace declaration.
  446                */
  447               if (was_added && !xslAttribute && !rawName.startsWith("xmlns"))
  448               {
  449                   String prefixUsed =
  450                       ensureAttributesNamespaceIsDeclared(
  451                           uri,
  452                           localName,
  453                           rawName);
  454                   if (prefixUsed != null
  455                       && rawName != null
  456                       && !rawName.startsWith(prefixUsed))
  457                   {
  458                       // use a different raw name, with the prefix used in the
  459                       // generated namespace declaration
  460                       rawName = prefixUsed + ":" + localName;
  461   
  462                   }
  463               }
  464               addAttributeAlways(uri, localName, rawName, type, value, xslAttribute);
  465           }
  466           else
  467           {
  468               /*
  469                * The startTag is closed, yet we are adding an attribute?
  470                *
  471                * Section: 7.1.3 Creating Attributes Adding an attribute to an
  472                * element after a PI (for example) has been added to it is an
  473                * error. The attributes can be ignored. The spec doesn't explicitly
  474                * say this is disallowed, as it does for child elements, but it
  475                * makes sense to have the same treatment.
  476                *
  477                * We choose to ignore the attribute which is added too late.
  478                */
  479               // Generate a warning of the ignored attributes
  480   
  481               // Create the warning message
  482               String msg = Utils.messages.createMessage(
  483                       MsgKey.ER_ILLEGAL_ATTRIBUTE_POSITION,new Object[]{ localName });
  484   
  485               try {
  486                   // Prepare to issue the warning message
  487                   Transformer tran = super.getTransformer();
  488                   ErrorListener errHandler = tran.getErrorListener();
  489   
  490   
  491                   // Issue the warning message
  492                   if (null != errHandler && m_sourceLocator != null)
  493                     errHandler.warning(new TransformerException(msg, m_sourceLocator));
  494                   else
  495                     System.out.println(msg);
  496                   }
  497               catch (Exception e){}
  498           }
  499       }
  500   
  501       /**
  502        * @see ExtendedContentHandler#endElement(String)
  503        */
  504       public void endElement(String elemName) throws SAXException
  505       {
  506           endElement(null, null, elemName);
  507       }
  508   
  509       /**
  510        * This method is used to notify the serializer of a namespace mapping (or node)
  511        * that applies to the current element whose startElement() call has already been seen.
  512        * The official SAX startPrefixMapping(prefix,uri) is to define a mapping for a child
  513        * element that is soon to be seen with a startElement() call. The official SAX call
  514        * does not apply to the current element, hence the reason for this method.
  515        */
  516       public void namespaceAfterStartElement(
  517           final String prefix,
  518           final String uri)
  519           throws SAXException
  520       {
  521   
  522           // hack for XSLTC with finding URI for default namespace
  523           if (m_elemContext.m_elementURI == null)
  524           {
  525               String prefix1 = getPrefixPart(m_elemContext.m_elementName);
  526               if (prefix1 == null && EMPTYSTRING.equals(prefix))
  527               {
  528                   // the elements URI is not known yet, and it
  529                   // doesn't have a prefix, and we are currently
  530                   // setting the uri for prefix "", so we have
  531                   // the uri for the element... lets remember it
  532                   m_elemContext.m_elementURI = uri;
  533               }
  534           }
  535           startPrefixMapping(prefix,uri,false);
  536           return;
  537   
  538       }
  539   
  540       /**
  541        * From XSLTC
  542        * Declare a prefix to point to a namespace URI. Inform SAX handler
  543        * if this is a new prefix mapping.
  544        */
  545       protected boolean pushNamespace(String prefix, String uri)
  546       {
  547           try
  548           {
  549               if (m_prefixMap.pushNamespace(
  550                   prefix, uri, m_elemContext.m_currentElemDepth))
  551               {
  552                   startPrefixMapping(prefix, uri);
  553                   return true;
  554               }
  555           }
  556           catch (SAXException e)
  557           {
  558               // falls through
  559           }
  560           return false;
  561       }
  562       /**
  563        * Try's to reset the super class and reset this class for
  564        * re-use, so that you don't need to create a new serializer
  565        * (mostly for performance reasons).
  566        *
  567        * @return true if the class was successfuly reset.
  568        */
  569       public boolean reset()
  570       {
  571           boolean wasReset = false;
  572           if (super.reset())
  573           {
  574               resetToXMLStream();
  575               wasReset = true;
  576           }
  577           return wasReset;
  578       }
  579   
  580       /**
  581        * Reset all of the fields owned by ToStream class
  582        *
  583        */
  584       private void resetToXMLStream()
  585       {
  586           this.m_cdataTagOpen = false;
  587   
  588       }
  589   
  590       /**
  591        * This method checks for the XML version of output document.
  592        * If XML version of output document is not specified, then output
  593        * document is of version XML 1.0.
  594        * If XML version of output doucment is specified, but it is not either
  595        * XML 1.0 or XML 1.1, a warning message is generated, the XML Version of
  596        * output document is set to XML 1.0 and processing continues.
  597        * @return string (XML version)
  598        */
  599       private String getXMLVersion()
  600       {
  601           String xmlVersion = getVersion();
  602           if(xmlVersion == null || xmlVersion.equals(XMLVERSION10))
  603           {
  604               xmlVersion = XMLVERSION10;
  605           }
  606           else if(xmlVersion.equals(XMLVERSION11))
  607           {
  608               xmlVersion = XMLVERSION11;
  609           }
  610           else
  611           {
  612               String msg = Utils.messages.createMessage(
  613                                  MsgKey.ER_XML_VERSION_NOT_SUPPORTED,new Object[]{ xmlVersion });
  614               try
  615               {
  616                   // Prepare to issue the warning message
  617                   Transformer tran = super.getTransformer();
  618                   ErrorListener errHandler = tran.getErrorListener();
  619                   // Issue the warning message
  620                   if (null != errHandler && m_sourceLocator != null)
  621                       errHandler.warning(new TransformerException(msg, m_sourceLocator));
  622                   else
  623                       System.out.println(msg);
  624               }
  625               catch (Exception e){}
  626               xmlVersion = XMLVERSION10;
  627           }
  628           return xmlVersion;
  629       }
  630   }

Save This Page
Home » openjdk-7 » com.sun.org.apache.xml.internal » serializer » [javadoc | source]