1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 package com.sun.org.apache.xml.internal.serialize;
  22 
  23 import java.io.IOException;
  24 import java.io.OutputStream;
  25 import java.io.StringWriter;
  26 import java.io.UnsupportedEncodingException;
  27 import java.io.Writer;
  28 import java.lang.reflect.Method;
  29 import java.util.ArrayList;
  30 
  31 import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl;
  32 import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl;
  33 import com.sun.org.apache.xerces.internal.dom.DOMLocatorImpl;
  34 import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter;
  35 import com.sun.org.apache.xerces.internal.dom.DOMNormalizer;
  36 import com.sun.org.apache.xerces.internal.dom.DOMStringListImpl;
  37 import com.sun.org.apache.xerces.internal.impl.Constants;
  38 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
  39 import com.sun.org.apache.xerces.internal.util.DOMUtil;
  40 import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
  41 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  42 import com.sun.org.apache.xerces.internal.util.XML11Char;
  43 import com.sun.org.apache.xerces.internal.util.XMLChar;
  44 import org.w3c.dom.Attr;
  45 import org.w3c.dom.Comment;
  46 import org.w3c.dom.DOMConfiguration;
  47 import org.w3c.dom.DOMError;
  48 import org.w3c.dom.DOMErrorHandler;
  49 import org.w3c.dom.DOMException;
  50 import org.w3c.dom.DOMStringList;
  51 import org.w3c.dom.Document;
  52 import org.w3c.dom.DocumentFragment;
  53 import org.w3c.dom.Element;
  54 import org.w3c.dom.NamedNodeMap;
  55 import org.w3c.dom.Node;
  56 import org.w3c.dom.ProcessingInstruction;
  57 import org.w3c.dom.ls.LSException;
  58 import org.w3c.dom.ls.LSOutput;
  59 import org.w3c.dom.ls.LSSerializer;
  60 import org.w3c.dom.ls.LSSerializerFilter;
  61 
  62 /**
  63  * EXPERIMENTAL: Implemenatation of DOM Level 3 org.w3c.ls.LSSerializer by
  64  * delegating serialization calls to <CODE>XMLSerializer</CODE>. LSSerializer
  65  * provides an API for serializing (writing) a DOM document out in an XML
  66  * document. The XML data is written to an output stream. During serialization
  67  * of XML data, namespace fixup is done when possible as defined in DOM Level 3
  68  * Core, Appendix B.
  69  *
  70  * @author Elena Litani, IBM
  71  * @author Gopal Sharma, Sun Microsystems
  72  * @author Arun Yadav, Sun Microsystems
  73  * @author Sunitha Reddy, Sun Microsystems
  74  *
  75  * @deprecated As of JDK 1.9, Xerces 2.9.0, replaced by
  76  * {@link com.sun.org.apache.xml.internal.serializer.dom3.LSSerializerImpl}
  77  */
  78 public class DOMSerializerImpl implements LSSerializer, DOMConfiguration {
  79 
  80     // TODO: When DOM Level 3 goes to REC replace method calls using
  81     // reflection for: getXmlEncoding, getInputEncoding and getXmlEncoding
  82     // with regular static calls on the Document object.
  83     // data
  84     // serializer
  85     private XMLSerializer serializer;
  86 
  87     // XML 1.1 serializer
  88     private XML11Serializer xml11Serializer;
  89 
  90     //Recognized parameters
  91     private DOMStringList fRecognizedParameters;
  92 
  93     /**
  94      * REVISIT: Currently we handle 3 different configurations, would be nice
  95      * just have one configuration that has different recognized parameters
  96      * depending if it is used in Core/LS.
  97      */
  98     protected short features = 0;
  99 
 100     protected final static short NAMESPACES = 0x1 << 0;
 101     protected final static short WELLFORMED = 0x1 << 1;
 102     protected final static short ENTITIES = 0x1 << 2;
 103     protected final static short CDATA = 0x1 << 3;
 104     protected final static short SPLITCDATA = 0x1 << 4;
 105     protected final static short COMMENTS = 0x1 << 5;
 106     protected final static short DISCARDDEFAULT = 0x1 << 6;
 107     protected final static short INFOSET = 0x1 << 7;
 108     protected final static short XMLDECL = 0x1 << 8;
 109     protected final static short NSDECL = 0x1 << 9;
 110     protected final static short DOM_ELEMENT_CONTENT_WHITESPACE = 0x1 << 10;
 111     protected final static short PRETTY_PRINT = 0x1 << 11;
 112 
 113     // well-formness checking
 114     private DOMErrorHandler fErrorHandler = null;
 115     private final DOMErrorImpl fError = new DOMErrorImpl();
 116     private final DOMLocatorImpl fLocator = new DOMLocatorImpl();
 117 
 118     /**
 119      * Constructs a new LSSerializer. The constructor turns on the namespace
 120      * support in <code>XMLSerializer</code> and initializes the following
 121      * fields: fNSBinder, fLocalNSBinder, fSymbolTable, fEmptySymbol,
 122      * fXmlSymbol, fXmlnsSymbol, fNamespaceCounter, fFeatures.
 123      */
 124     public DOMSerializerImpl() {
 125         // set default features
 126         features |= NAMESPACES;
 127         features |= ENTITIES;
 128         features |= COMMENTS;
 129         features |= CDATA;
 130         features |= SPLITCDATA;
 131         features |= WELLFORMED;
 132         features |= NSDECL;
 133         features |= DOM_ELEMENT_CONTENT_WHITESPACE;
 134         features |= DISCARDDEFAULT;
 135         features |= XMLDECL;
 136 
 137         serializer = new XMLSerializer();
 138         initSerializer(serializer);
 139     }
 140 
 141     //
 142     // LSSerializer methods
 143     //
 144     public DOMConfiguration getDomConfig() {
 145         return this;
 146     }
 147 
 148     /**
 149      * DOM L3-EXPERIMENTAL: Setter for boolean and object parameters
 150      */
 151     public void setParameter(String name, Object value) throws DOMException {
 152         if (value instanceof Boolean) {
 153             boolean state = ((Boolean) value).booleanValue();
 154             if (name.equalsIgnoreCase(Constants.DOM_INFOSET)) {
 155                 if (state) {
 156                     features &= ~ENTITIES;
 157                     features &= ~CDATA;
 158                     features |= NAMESPACES;
 159                     features |= NSDECL;
 160                     features |= WELLFORMED;
 161                     features |= COMMENTS;
 162                 }
 163                 // false does not have any effect
 164             } else if (name.equalsIgnoreCase(Constants.DOM_XMLDECL)) {
 165                 features
 166                         = (short) (state ? features | XMLDECL : features & ~XMLDECL);
 167             } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
 168                 features
 169                         = (short) (state
 170                         ? features | NAMESPACES
 171                         : features & ~NAMESPACES);
 172                 serializer.fNamespaces = state;
 173             } else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
 174                 features
 175                         = (short) (state
 176                         ? features | SPLITCDATA
 177                         : features & ~SPLITCDATA);
 178             } else if (name.equalsIgnoreCase(Constants.DOM_DISCARD_DEFAULT_CONTENT)) {
 179                 features
 180                         = (short) (state
 181                         ? features | DISCARDDEFAULT
 182                         : features & ~DISCARDDEFAULT);
 183             } else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
 184                 features
 185                         = (short) (state
 186                         ? features | WELLFORMED
 187                         : features & ~WELLFORMED);
 188             } else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
 189                 features
 190                         = (short) (state
 191                         ? features | ENTITIES
 192                         : features & ~ENTITIES);
 193             } else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
 194                 features
 195                         = (short) (state
 196                         ? features | CDATA
 197                         : features & ~CDATA);
 198             } else if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
 199                 features
 200                         = (short) (state
 201                         ? features | COMMENTS
 202                         : features & ~COMMENTS);
 203             } else if (name.equalsIgnoreCase(Constants.DOM_FORMAT_PRETTY_PRINT)) {
 204                 features
 205                         = (short) (state
 206                         ? features | PRETTY_PRINT
 207                         : features & ~PRETTY_PRINT);
 208             } else if (name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
 209                     || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
 210                     || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
 211                     || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
 212                     || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
 213                 //  || name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)) {
 214                 // true is not supported
 215                 if (state) {
 216                     String msg
 217                             = DOMMessageFormatter.formatMessage(
 218                                     DOMMessageFormatter.DOM_DOMAIN,
 219                                     "FEATURE_NOT_SUPPORTED",
 220                                     new Object[]{name});
 221                     throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 222                 }
 223             } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
 224                 //namespace-declaration has effect only if namespaces is true
 225                 features
 226                         = (short) (state
 227                         ? features | NSDECL
 228                         : features & ~NSDECL);
 229                 serializer.fNamespacePrefixes = state;
 230             } else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
 231                     || name.equalsIgnoreCase(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
 232                 // false is not supported
 233                 if (!state) {
 234                     String msg
 235                             = DOMMessageFormatter.formatMessage(
 236                                     DOMMessageFormatter.DOM_DOMAIN,
 237                                     "FEATURE_NOT_SUPPORTED",
 238                                     new Object[]{name});
 239                     throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 240                 }
 241             } else {
 242                 String msg
 243                         = DOMMessageFormatter.formatMessage(
 244                                 DOMMessageFormatter.DOM_DOMAIN,
 245                                 "FEATURE_NOT_FOUND",
 246                                 new Object[]{name});
 247                 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 248             }
 249         } else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
 250             if (value == null || value instanceof DOMErrorHandler) {
 251                 fErrorHandler = (DOMErrorHandler) value;
 252             } else {
 253                 String msg
 254                         = DOMMessageFormatter.formatMessage(
 255                                 DOMMessageFormatter.DOM_DOMAIN,
 256                                 "TYPE_MISMATCH_ERR",
 257                                 new Object[]{name});
 258                 throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
 259             }
 260         } else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)
 261                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)
 262                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)
 263                 || name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
 264                 && value != null) {
 265             String msg
 266                     = DOMMessageFormatter.formatMessage(
 267                             DOMMessageFormatter.DOM_DOMAIN,
 268                             "FEATURE_NOT_SUPPORTED",
 269                             new Object[]{name});
 270             throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 271         } else {
 272             String msg
 273                     = DOMMessageFormatter.formatMessage(
 274                             DOMMessageFormatter.DOM_DOMAIN,
 275                             "FEATURE_NOT_FOUND",
 276                             new Object[]{name});
 277             throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
 278         }
 279     }
 280 
 281     /**
 282      * DOM L3-EXPERIMENTAL: Check if parameter can be set
 283      */
 284     public boolean canSetParameter(String name, Object state) {
 285         if (state == null) {
 286             return true;
 287         }
 288 
 289         if (state instanceof Boolean) {
 290             boolean value = ((Boolean) state).booleanValue();
 291             if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)
 292                 || name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)
 293                 || name.equalsIgnoreCase(Constants.DOM_DISCARD_DEFAULT_CONTENT)
 294                 || name.equalsIgnoreCase(Constants.DOM_XMLDECL)
 295                 || name.equalsIgnoreCase(Constants.DOM_WELLFORMED)
 296                 || name.equalsIgnoreCase(Constants.DOM_INFOSET)
 297                 || name.equalsIgnoreCase(Constants.DOM_ENTITIES)
 298                 || name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)
 299                 || name.equalsIgnoreCase(Constants.DOM_COMMENTS)
 300                 || name.equalsIgnoreCase(Constants.DOM_FORMAT_PRETTY_PRINT)
 301                 || name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
 302                 // both values supported
 303                 return true;
 304             } else if (name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
 305                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
 306                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
 307                 || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
 308                 || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
 309                 // || name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)) {
 310                 // true is not supported
 311                 return !value;
 312             } else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
 313                 || name.equalsIgnoreCase(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
 314                 // false is not supported
 315                 return value;
 316             }
 317         } else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)
 318                 && state == null || state instanceof DOMErrorHandler) {
 319             return true;
 320         }
 321 
 322         return false;
 323     }
 324 
 325     /**
 326      * DOM Level 3 Core CR - Experimental.
 327      *
 328      * The list of the parameters supported by this
 329      * <code>DOMConfiguration</code> object and for which at least one value can
 330      * be set by the application. Note that this list can also contain parameter
 331      * names defined outside this specification.
 332      */
 333     public DOMStringList getParameterNames() {
 334 
 335         if (fRecognizedParameters == null) {
 336             ArrayList parameters = new ArrayList();
 337 
 338             //Add DOM recognized parameters
 339             //REVISIT: Would have been nice to have a list of
 340             //recognized parameters.
 341             parameters.add(Constants.DOM_NAMESPACES);
 342             parameters.add(Constants.DOM_SPLIT_CDATA);
 343             parameters.add(Constants.DOM_DISCARD_DEFAULT_CONTENT);
 344             parameters.add(Constants.DOM_XMLDECL);
 345             parameters.add(Constants.DOM_CANONICAL_FORM);
 346             parameters.add(Constants.DOM_VALIDATE_IF_SCHEMA);
 347             parameters.add(Constants.DOM_VALIDATE);
 348             parameters.add(Constants.DOM_CHECK_CHAR_NORMALIZATION);
 349             parameters.add(Constants.DOM_DATATYPE_NORMALIZATION);
 350             parameters.add(Constants.DOM_FORMAT_PRETTY_PRINT);
 351             //parameters.add(Constants.DOM_NORMALIZE_CHARACTERS);
 352             parameters.add(Constants.DOM_WELLFORMED);
 353             parameters.add(Constants.DOM_INFOSET);
 354             parameters.add(Constants.DOM_NAMESPACE_DECLARATIONS);
 355             parameters.add(Constants.DOM_ELEMENT_CONTENT_WHITESPACE);
 356             parameters.add(Constants.DOM_ENTITIES);
 357             parameters.add(Constants.DOM_CDATA_SECTIONS);
 358             parameters.add(Constants.DOM_COMMENTS);
 359             parameters.add(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS);
 360             parameters.add(Constants.DOM_ERROR_HANDLER);
 361             //parameters.add(Constants.DOM_SCHEMA_LOCATION);
 362             //parameters.add(Constants.DOM_SCHEMA_TYPE);
 363 
 364             //Add recognized xerces features and properties
 365             fRecognizedParameters = new DOMStringListImpl(parameters);
 366         }
 367 
 368         return fRecognizedParameters;
 369     }
 370 
 371     /**
 372      * DOM L3-EXPERIMENTAL: Getter for boolean and object parameters
 373      */
 374     public Object getParameter(String name) throws DOMException {
 375         if (name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)) {
 376             return null;
 377         } else if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
 378             return ((features & COMMENTS) != 0) ? Boolean.TRUE : Boolean.FALSE;
 379         } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
 380             return (features & NAMESPACES) != 0 ? Boolean.TRUE : Boolean.FALSE;
 381         } else if (name.equalsIgnoreCase(Constants.DOM_XMLDECL)) {
 382             return (features & XMLDECL) != 0 ? Boolean.TRUE : Boolean.FALSE;
 383         } else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
 384             return (features & CDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
 385         } else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
 386             return (features & ENTITIES) != 0 ? Boolean.TRUE : Boolean.FALSE;
 387         } else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
 388             return (features & SPLITCDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
 389         } else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
 390             return (features & WELLFORMED) != 0 ? Boolean.TRUE : Boolean.FALSE;
 391         } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
 392             return (features & NSDECL) != 0 ? Boolean.TRUE : Boolean.FALSE;
 393         } else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
 394                 || name.equalsIgnoreCase(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
 395             return Boolean.TRUE;
 396         } else if (name.equalsIgnoreCase(Constants.DOM_DISCARD_DEFAULT_CONTENT)) {
 397             return ((features & DISCARDDEFAULT) != 0) ? Boolean.TRUE : Boolean.FALSE;
 398         } else if (name.equalsIgnoreCase(Constants.DOM_FORMAT_PRETTY_PRINT)) {
 399             return ((features & PRETTY_PRINT) != 0) ? Boolean.TRUE : Boolean.FALSE;
 400         } else if (name.equalsIgnoreCase(Constants.DOM_INFOSET)) {
 401             if ((features & ENTITIES) == 0
 402                     && (features & CDATA) == 0
 403                     && (features & NAMESPACES) != 0
 404                     && (features & NSDECL) != 0
 405                     && (features & WELLFORMED) != 0
 406                     && (features & COMMENTS) != 0) {
 407                 return Boolean.TRUE;
 408             }
 409             return Boolean.FALSE;
 410         } else if (name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
 411                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
 412                 || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
 413                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
 414                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
 415                 || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
 416             return Boolean.FALSE;
 417         } else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
 418             return fErrorHandler;
 419         } else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)
 420                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)
 421                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
 422             String msg
 423                     = DOMMessageFormatter.formatMessage(
 424                             DOMMessageFormatter.DOM_DOMAIN,
 425                             "FEATURE_NOT_SUPPORTED",
 426                             new Object[]{name});
 427             throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 428         } else {
 429             String msg
 430                     = DOMMessageFormatter.formatMessage(
 431                             DOMMessageFormatter.DOM_DOMAIN,
 432                             "FEATURE_NOT_FOUND",
 433                             new Object[]{name});
 434             throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
 435         }
 436     }
 437 
 438     /**
 439      * DOM L3 EXPERIMENTAL: Serialize the specified node as described above in
 440      * the description of <code>LSSerializer</code>. The result of serializing
 441      * the node is returned as a string. Writing a Document or Entity node
 442      * produces a serialized form that is well formed XML. Writing other node
 443      * types produces a fragment of text in a form that is not fully defined by
 444      * this document, but that should be useful to a human for debugging or
 445      * diagnostic purposes.
 446      *
 447      * @param wnode The node to be written.
 448      * @return Returns the serialized data
 449      * @exception DOMException DOMSTRING_SIZE_ERR: The resulting string is too
 450      * long to fit in a <code>DOMString</code>.
 451      * @exception LSException SERIALIZE_ERR: Unable to serialize the node. DOM
 452      * applications should attach a <code>DOMErrorHandler</code> using the
 453      * parameter &quot;<i>error-handler</i>&quot; to get details on error.
 454      */
 455     public String writeToString(Node wnode) throws DOMException, LSException {
 456         // determine which serializer to use:
 457         XMLSerializer ser = null;
 458         String ver = _getXmlVersion(wnode);
 459         if (ver != null && ver.equals("1.1")) {
 460             if (xml11Serializer == null) {
 461                 xml11Serializer = new XML11Serializer();
 462                 initSerializer(xml11Serializer);
 463             }
 464             // copy setting from "main" serializer to XML 1.1 serializer
 465             copySettings(serializer, xml11Serializer);
 466             ser = xml11Serializer;
 467         } else {
 468             ser = serializer;
 469         }
 470 
 471         StringWriter destination = new StringWriter();
 472         try {
 473             prepareForSerialization(ser, wnode);
 474             ser._format.setEncoding("UTF-16");
 475             ser.setOutputCharStream(destination);
 476             if (wnode.getNodeType() == Node.DOCUMENT_NODE) {
 477                 ser.serialize((Document) wnode);
 478             } else if (wnode.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
 479                 ser.serialize((DocumentFragment) wnode);
 480             } else if (wnode.getNodeType() == Node.ELEMENT_NODE) {
 481                 ser.serialize((Element) wnode);
 482             } else if (wnode.getNodeType() == Node.TEXT_NODE
 483                     || wnode.getNodeType() == Node.COMMENT_NODE
 484                     || wnode.getNodeType() == Node.ENTITY_REFERENCE_NODE
 485                     || wnode.getNodeType() == Node.CDATA_SECTION_NODE
 486                     || wnode.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
 487                 ser.serialize(wnode);
 488             } else {
 489                 String msg = DOMMessageFormatter.formatMessage(
 490                         DOMMessageFormatter.SERIALIZER_DOMAIN,
 491                         "unable-to-serialize-node", null);
 492                 if (ser.fDOMErrorHandler != null) {
 493                     DOMErrorImpl error = new DOMErrorImpl();
 494                     error.fType = "unable-to-serialize-node";
 495                     error.fMessage = msg;
 496                     error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
 497                     ser.fDOMErrorHandler.handleError(error);
 498                 }
 499                 throw new LSException(LSException.SERIALIZE_ERR, msg);
 500             }
 501         } catch (LSException lse) {
 502             // Rethrow LSException.
 503             throw lse;
 504         } catch (RuntimeException e) {
 505             if (e == DOMNormalizer.abort) {
 506                 // stopped at user request
 507                 return null;
 508             }
 509             throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
 510         } catch (IOException ioe) {
 511             // REVISIT: A generic IOException doesn't provide enough information
 512             // to determine that the serialized document is too large to fit
 513             // into a string. This could have thrown for some other reason. -- mrglavas
 514             String msg = DOMMessageFormatter.formatMessage(
 515                     DOMMessageFormatter.DOM_DOMAIN,
 516                     "STRING_TOO_LONG",
 517                     new Object[]{ioe.getMessage()});
 518             throw new DOMException(DOMException.DOMSTRING_SIZE_ERR, msg);
 519         } finally {
 520             ser.clearDocumentState();
 521         }
 522         return destination.toString();
 523     }
 524 
 525     /**
 526      * DOM L3 EXPERIMENTAL: The end-of-line sequence of characters to be used in
 527      * the XML being written out. The only permitted values are these:
 528      * <dl>
 529      * <dt><code>null</code></dt>
 530      * <dd>
 531      * Use a default end-of-line sequence. DOM implementations should choose the
 532      * default to match the usual convention for text files in the environment
 533      * being used. Implementations must choose a default sequence that matches
 534      * one of those allowed by 2.11 "End-of-Line Handling". </dd>
 535      * <dt>CR</dt>
 536      * <dd>The carriage-return character (#xD).</dd>
 537      * <dt>CR-LF</dt>
 538      * <dd> The carriage-return and line-feed characters (#xD #xA). </dd>
 539      * <dt>LF</dt>
 540      * <dd> The line-feed character (#xA). </dd>
 541      * </dl>
 542      * <br>The default value for this attribute is <code>null</code>.
 543      */
 544     public void setNewLine(String newLine) {
 545         serializer._format.setLineSeparator(newLine);
 546     }
 547 
 548     /**
 549      * DOM L3 EXPERIMENTAL: The end-of-line sequence of characters to be used in
 550      * the XML being written out. The only permitted values are these:
 551      * <dl>
 552      * <dt><code>null</code></dt>
 553      * <dd>
 554      * Use a default end-of-line sequence. DOM implementations should choose the
 555      * default to match the usual convention for text files in the environment
 556      * being used. Implementations must choose a default sequence that matches
 557      * one of those allowed by 2.11 "End-of-Line Handling". </dd>
 558      * <dt>CR</dt>
 559      * <dd>The carriage-return character (#xD).</dd>
 560      * <dt>CR-LF</dt>
 561      * <dd> The carriage-return and line-feed characters (#xD #xA). </dd>
 562      * <dt>LF</dt>
 563      * <dd> The line-feed character (#xA). </dd>
 564      * </dl>
 565      * <br>The default value for this attribute is <code>null</code>.
 566      */
 567     public String getNewLine() {
 568         return serializer._format.getLineSeparator();
 569     }
 570 
 571     /**
 572      * When the application provides a filter, the serializer will call out to
 573      * the filter before serializing each Node. Attribute nodes are never passed
 574      * to the filter. The filter implementation can choose to remove the node
 575      * from the stream or to terminate the serialization early.
 576      */
 577     public LSSerializerFilter getFilter() {
 578         return serializer.fDOMFilter;
 579     }
 580 
 581     /**
 582      * When the application provides a filter, the serializer will call out to
 583      * the filter before serializing each Node. Attribute nodes are never passed
 584      * to the filter. The filter implementation can choose to remove the node
 585      * from the stream or to terminate the serialization early.
 586      */
 587     public void setFilter(LSSerializerFilter filter) {
 588         serializer.fDOMFilter = filter;
 589     }
 590 
 591     // this initializes a newly-created serializer
 592     private void initSerializer(XMLSerializer ser) {
 593         ser.fNSBinder = new NamespaceSupport();
 594         ser.fLocalNSBinder = new NamespaceSupport();
 595         ser.fSymbolTable = new SymbolTable();
 596     }
 597 
 598     // copies all settings that could have been modified
 599     // by calls to LSSerializer methods from one serializer to another.
 600     // IMPORTANT:  if new methods are implemented or more settings of
 601     // the serializer are made alterable, this must be
 602     // reflected in this method!
 603     private void copySettings(XMLSerializer src, XMLSerializer dest) {
 604         dest.fDOMErrorHandler = fErrorHandler;
 605         dest._format.setEncoding(src._format.getEncoding());
 606         dest._format.setLineSeparator(src._format.getLineSeparator());
 607         dest.fDOMFilter = src.fDOMFilter;
 608     }//copysettings
 609 
 610     /**
 611      * Serialize the specified node as described above in the general
 612      * description of the <code>LSSerializer</code> interface. The output is
 613      * written to the supplied <code>LSOutput</code>.
 614      * <br> When writing to a <code>LSOutput</code>, the encoding is found by
 615      * looking at the encoding information that is reachable through the
 616      * <code>LSOutput</code> and the item to be written (or its owner document)
 617      * in this order:
 618      * <ol>
 619      * <li> <code>LSOutput.encoding</code>,
 620      * </li>
 621      * <li>
 622      * <code>Document.actualEncoding</code>,
 623      * </li>
 624      * <li>
 625      * <code>Document.xmlEncoding</code>.
 626      * </li>
 627      * </ol>
 628      * <br> If no encoding is reachable through the above properties, a default
 629      * encoding of "UTF-8" will be used.
 630      * <br> If the specified encoding is not supported an "unsupported-encoding"
 631      * error is raised.
 632      * <br> If no output is specified in the <code>LSOutput</code>, a
 633      * "no-output-specified" error is raised.
 634      *
 635      * @param node The node to serialize.
 636      * @param destination The destination for the serialized DOM.
 637      * @return Returns <code>true</code> if <code>node</code> was successfully
 638      * serialized and <code>false</code> in case the node couldn't be
 639      * serialized.
 640      */
 641     public boolean write(Node node, LSOutput destination) throws LSException {
 642 
 643         if (node == null) {
 644             return false;
 645         }
 646 
 647         XMLSerializer ser = null;
 648         String ver = _getXmlVersion(node);
 649         //determine which serializer to use:
 650         if (ver != null && ver.equals("1.1")) {
 651             if (xml11Serializer == null) {
 652                 xml11Serializer = new XML11Serializer();
 653                 initSerializer(xml11Serializer);
 654             }
 655             //copy setting from "main" serializer to XML 1.1 serializer
 656             copySettings(serializer, xml11Serializer);
 657             ser = xml11Serializer;
 658         } else {
 659             ser = serializer;
 660         }
 661 
 662         String encoding = null;
 663         if ((encoding = destination.getEncoding()) == null) {
 664             encoding = _getInputEncoding(node);
 665             if (encoding == null) {
 666                 encoding = _getXmlEncoding(node);
 667                 if (encoding == null) {
 668                     encoding = "UTF-8";
 669                 }
 670             }
 671         }
 672         try {
 673             prepareForSerialization(ser, node);
 674             ser._format.setEncoding(encoding);
 675             OutputStream outputStream = destination.getByteStream();
 676             Writer writer = destination.getCharacterStream();
 677             String uri = destination.getSystemId();
 678             if (writer == null) {
 679                 if (outputStream == null) {
 680                     if (uri == null) {
 681                         String msg = DOMMessageFormatter.formatMessage(
 682                                 DOMMessageFormatter.SERIALIZER_DOMAIN,
 683                                 "no-output-specified", null);
 684                         if (ser.fDOMErrorHandler != null) {
 685                             DOMErrorImpl error = new DOMErrorImpl();
 686                             error.fType = "no-output-specified";
 687                             error.fMessage = msg;
 688                             error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
 689                             ser.fDOMErrorHandler.handleError(error);
 690                         }
 691                         throw new LSException(LSException.SERIALIZE_ERR, msg);
 692                     } else {
 693                         ser.setOutputByteStream(XMLEntityManager.createOutputStream(uri));
 694                     }
 695                 } else {
 696                     // byte stream was specified
 697                     ser.setOutputByteStream(outputStream);
 698                 }
 699             } else {
 700                 // character stream is specified
 701                 ser.setOutputCharStream(writer);
 702             }
 703 
 704             if (node.getNodeType() == Node.DOCUMENT_NODE) {
 705                 ser.serialize((Document) node);
 706             } else if (node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
 707                 ser.serialize((DocumentFragment) node);
 708             } else if (node.getNodeType() == Node.ELEMENT_NODE) {
 709                 ser.serialize((Element) node);
 710             } else if (node.getNodeType() == Node.TEXT_NODE
 711                     || node.getNodeType() == Node.COMMENT_NODE
 712                     || node.getNodeType() == Node.ENTITY_REFERENCE_NODE
 713                     || node.getNodeType() == Node.CDATA_SECTION_NODE
 714                     || node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
 715                 ser.serialize(node);
 716             } else {
 717                 return false;
 718             }
 719         } catch (UnsupportedEncodingException ue) {
 720             if (ser.fDOMErrorHandler != null) {
 721                 DOMErrorImpl error = new DOMErrorImpl();
 722                 error.fException = ue;
 723                 error.fType = "unsupported-encoding";
 724                 error.fMessage = ue.getMessage();
 725                 error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
 726                 ser.fDOMErrorHandler.handleError(error);
 727             }
 728             throw new LSException(LSException.SERIALIZE_ERR,
 729                     DOMMessageFormatter.formatMessage(
 730                             DOMMessageFormatter.SERIALIZER_DOMAIN,
 731                             "unsupported-encoding", null));
 732             //return false;
 733         } catch (LSException lse) {
 734             // Rethrow LSException.
 735             throw lse;
 736         } catch (RuntimeException e) {
 737             if (e == DOMNormalizer.abort) {
 738                 // stopped at user request
 739                 return false;
 740             }
 741             throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
 742         } catch (Exception e) {
 743             if (ser.fDOMErrorHandler != null) {
 744                 DOMErrorImpl error = new DOMErrorImpl();
 745                 error.fException = e;
 746                 error.fMessage = e.getMessage();
 747                 error.fSeverity = DOMError.SEVERITY_ERROR;
 748                 ser.fDOMErrorHandler.handleError(error);
 749 
 750             }
 751             throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
 752         } finally {
 753             ser.clearDocumentState();
 754         }
 755         return true;
 756 
 757     } //write
 758 
 759     /**
 760      * Serialize the specified node as described above in the general
 761      * description of the <code>LSSerializer</code> interface. The output is
 762      * written to the supplied URI.
 763      * <br> When writing to a URI, the encoding is found by looking at the
 764      * encoding information that is reachable through the item to be written (or
 765      * its owner document) in this order:
 766      * <ol>
 767      * <li>
 768      * <code>Document.inputEncoding</code>,
 769      * </li>
 770      * <li>
 771      * <code>Document.xmlEncoding</code>.
 772      * </li>
 773      * </ol>
 774      * <br> If no encoding is reachable through the above properties, a default
 775      * encoding of "UTF-8" will be used.
 776      * <br> If the specified encoding is not supported an "unsupported-encoding"
 777      * error is raised.
 778      *
 779      * @param node The node to serialize.
 780      * @param URI The URI to write to.
 781      * @return Returns <code>true</code> if <code>node</code> was successfully
 782      * serialized and <code>false</code> in case the node couldn't be
 783      * serialized.
 784      */
 785     public boolean writeToURI(Node node, String URI) throws LSException {
 786         if (node == null) {
 787             return false;
 788         }
 789 
 790         XMLSerializer ser = null;
 791         String ver = _getXmlVersion(node);
 792 
 793         if (ver != null && ver.equals("1.1")) {
 794             if (xml11Serializer == null) {
 795                 xml11Serializer = new XML11Serializer();
 796                 initSerializer(xml11Serializer);
 797             }
 798             // copy setting from "main" serializer to XML 1.1 serializer
 799             copySettings(serializer, xml11Serializer);
 800             ser = xml11Serializer;
 801         } else {
 802             ser = serializer;
 803         }
 804 
 805         String encoding = _getInputEncoding(node);
 806         if (encoding == null) {
 807             encoding = _getXmlEncoding(node);
 808             if (encoding == null) {
 809                 encoding = "UTF-8";
 810             }
 811         }
 812 
 813         try {
 814             prepareForSerialization(ser, node);
 815             ser._format.setEncoding(encoding);
 816             ser.setOutputByteStream(XMLEntityManager.createOutputStream(URI));
 817 
 818             if (node.getNodeType() == Node.DOCUMENT_NODE) {
 819                 ser.serialize((Document) node);
 820             } else if (node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
 821                 ser.serialize((DocumentFragment) node);
 822             } else if (node.getNodeType() == Node.ELEMENT_NODE) {
 823                 ser.serialize((Element) node);
 824             } else if (node.getNodeType() == Node.TEXT_NODE
 825                     || node.getNodeType() == Node.COMMENT_NODE
 826                     || node.getNodeType() == Node.ENTITY_REFERENCE_NODE
 827                     || node.getNodeType() == Node.CDATA_SECTION_NODE
 828                     || node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
 829                 ser.serialize(node);
 830             } else {
 831                 return false;
 832             }
 833         } catch (LSException lse) {
 834             // Rethrow LSException.
 835             throw lse;
 836         } catch (RuntimeException e) {
 837             if (e == DOMNormalizer.abort) {
 838                 // stopped at user request
 839                 return false;
 840             }
 841             throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
 842         } catch (Exception e) {
 843             if (ser.fDOMErrorHandler != null) {
 844                 DOMErrorImpl error = new DOMErrorImpl();
 845                 error.fException = e;
 846                 error.fMessage = e.getMessage();
 847                 error.fSeverity = DOMError.SEVERITY_ERROR;
 848                 ser.fDOMErrorHandler.handleError(error);
 849             }
 850             throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
 851         } finally {
 852             ser.clearDocumentState();
 853         }
 854         return true;
 855     } //writeURI
 856 
 857     //
 858     //  Private methods
 859     //
 860     private void prepareForSerialization(XMLSerializer ser, Node node) {
 861         ser.reset();
 862         ser.features = features;
 863         ser.fDOMErrorHandler = fErrorHandler;
 864         ser.fNamespaces = (features & NAMESPACES) != 0;
 865         ser.fNamespacePrefixes = (features & NSDECL) != 0;
 866         ser._format.setIndenting((features & PRETTY_PRINT) != 0);
 867         ser._format.setOmitComments((features & COMMENTS) == 0);
 868         ser._format.setOmitXMLDeclaration((features & XMLDECL) == 0);
 869 
 870         if ((features & WELLFORMED) != 0) {
 871             // REVISIT: this is inefficient implementation of well-formness. Instead, we should check
 872             // well-formness as we serialize the tree
 873             Node next, root;
 874             root = node;
 875             Method versionChanged;
 876             boolean verifyNames = true;
 877             Document document = (node.getNodeType() == Node.DOCUMENT_NODE)
 878                     ? (Document) node
 879                     : node.getOwnerDocument();
 880             try {
 881                 versionChanged = document.getClass().getMethod("isXMLVersionChanged()", new Class[]{});
 882                 if (versionChanged != null) {
 883                     verifyNames = ((Boolean) versionChanged.invoke(document, (Object[]) null)).booleanValue();
 884                 }
 885             } catch (Exception e) {
 886                 //no way to test the version...
 887                 //ignore the exception
 888             }
 889             if (node.getFirstChild() != null) {
 890                 while (node != null) {
 891                     verify(node, verifyNames, false);
 892                     // Move down to first child
 893                     next = node.getFirstChild();
 894                     // No child nodes, so walk tree
 895                     while (next == null) {
 896                         // Move to sibling if possible.
 897                         next = node.getNextSibling();
 898                         if (next == null) {
 899                             node = node.getParentNode();
 900                             if (root == node) {
 901                                 next = null;
 902                                 break;
 903                             }
 904                             next = node.getNextSibling();
 905                         }
 906                     }
 907                     node = next;
 908                 }
 909             } else {
 910                 verify(node, verifyNames, false);
 911             }
 912         }
 913     }
 914 
 915     private void verify(Node node, boolean verifyNames, boolean xml11Version) {
 916 
 917         int type = node.getNodeType();
 918         fLocator.fRelatedNode = node;
 919         boolean wellformed;
 920         switch (type) {
 921             case Node.DOCUMENT_NODE: {
 922                 break;
 923             }
 924             case Node.DOCUMENT_TYPE_NODE: {
 925                 break;
 926             }
 927             case Node.ELEMENT_NODE: {
 928                 if (verifyNames) {
 929                     if ((features & NAMESPACES) != 0) {
 930                         wellformed = CoreDocumentImpl.isValidQName(node.getPrefix(), node.getLocalName(), xml11Version);
 931                     } else {
 932                         wellformed = CoreDocumentImpl.isXMLName(node.getNodeName(), xml11Version);
 933                     }
 934                     if (!wellformed) {
 935                         if (fErrorHandler != null) {
 936                             String msg = DOMMessageFormatter.formatMessage(
 937                                     DOMMessageFormatter.DOM_DOMAIN,
 938                                     "wf-invalid-character-in-node-name",
 939                                     new Object[]{"Element", node.getNodeName()});
 940                             DOMNormalizer.reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR,
 941                                     "wf-invalid-character-in-node-name");
 942                         }
 943                     }
 944                 }
 945 
 946                 NamedNodeMap attributes = (node.hasAttributes()) ? node.getAttributes() : null;
 947                 if (attributes != null) {
 948                     for (int i = 0; i < attributes.getLength(); ++i) {
 949                         Attr attr = (Attr) attributes.item(i);
 950                         fLocator.fRelatedNode = attr;
 951                         DOMNormalizer.isAttrValueWF(fErrorHandler, fError, fLocator,
 952                                 attributes, attr, attr.getValue(), xml11Version);
 953                         if (verifyNames) {
 954                             wellformed = CoreDocumentImpl.isXMLName(attr.getNodeName(), xml11Version);
 955                             if (!wellformed) {
 956                                 String msg
 957                                         = DOMMessageFormatter.formatMessage(
 958                                                 DOMMessageFormatter.DOM_DOMAIN,
 959                                                 "wf-invalid-character-in-node-name",
 960                                                 new Object[]{"Attr", node.getNodeName()});
 961                                 DOMNormalizer.reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR,
 962                                         "wf-invalid-character-in-node-name");
 963                             }
 964                         }
 965                     }
 966 
 967                 }
 968 
 969                 break;
 970             }
 971 
 972             case Node.COMMENT_NODE: {
 973                 // only verify well-formness if comments included in the tree
 974                 if ((features & COMMENTS) != 0) {
 975                     DOMNormalizer.isCommentWF(fErrorHandler, fError, fLocator, ((Comment) node).getData(), xml11Version);
 976                 }
 977                 break;
 978             }
 979             case Node.ENTITY_REFERENCE_NODE: {
 980                 // only if entity is preserved in the tree
 981                 if (verifyNames && (features & ENTITIES) != 0) {
 982                     CoreDocumentImpl.isXMLName(node.getNodeName(), xml11Version);
 983                 }
 984                 break;
 985 
 986             }
 987             case Node.CDATA_SECTION_NODE: {
 988                 // verify content
 989                 DOMNormalizer.isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), xml11Version);
 990                 // the ]]> string will be checked during serialization
 991                 break;
 992             }
 993             case Node.TEXT_NODE: {
 994                 DOMNormalizer.isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), xml11Version);
 995                 break;
 996             }
 997             case Node.PROCESSING_INSTRUCTION_NODE: {
 998                 ProcessingInstruction pinode = (ProcessingInstruction) node;
 999                 String target = pinode.getTarget();
1000                 if (verifyNames) {
1001                     if (xml11Version) {
1002                         wellformed = XML11Char.isXML11ValidName(target);
1003                     } else {
1004                         wellformed = XMLChar.isValidName(target);
1005                     }
1006 
1007                     if (!wellformed) {
1008                         String msg
1009                                 = DOMMessageFormatter.formatMessage(
1010                                         DOMMessageFormatter.DOM_DOMAIN,
1011                                         "wf-invalid-character-in-node-name",
1012                                         new Object[]{"Element", node.getNodeName()});
1013                         DOMNormalizer.reportDOMError(
1014                                 fErrorHandler,
1015                                 fError,
1016                                 fLocator,
1017                                 msg,
1018                                 DOMError.SEVERITY_FATAL_ERROR,
1019                                 "wf-invalid-character-in-node-name");
1020                     }
1021                 }
1022                 DOMNormalizer.isXMLCharWF(fErrorHandler, fError, fLocator, pinode.getData(), xml11Version);
1023                 break;
1024             }
1025         }
1026         fLocator.fRelatedNode = null;
1027     }
1028 
1029     private String _getXmlVersion(Node node) {
1030         Document doc = (node.getNodeType() == Node.DOCUMENT_NODE)
1031                 ? (Document) node : node.getOwnerDocument();
1032         if (doc != null) {
1033             try {
1034                 return doc.getXmlVersion();
1035             } // The VM ran out of memory or there was some other serious problem. Re-throw.
1036              catch (VirtualMachineError | ThreadDeath vme) {
1037                 throw vme;
1038             } // Ignore all other exceptions and errors
1039             catch (Throwable t) {
1040             }
1041         }
1042         return null;
1043     }
1044 
1045     private String _getInputEncoding(Node node) {
1046         Document doc = (node.getNodeType() == Node.DOCUMENT_NODE)
1047                 ? (Document) node : node.getOwnerDocument();
1048         if (doc != null) {
1049             try {
1050                 return doc.getInputEncoding();
1051             } // The VM ran out of memory or there was some other serious problem. Re-throw.
1052             catch (VirtualMachineError | ThreadDeath vme) {
1053                 throw vme;
1054             } // Ignore all other exceptions and errors
1055             catch (Throwable t) {
1056             }
1057         }
1058         return null;
1059     }
1060 
1061     private String _getXmlEncoding(Node node) {
1062         Document doc = (node.getNodeType() == Node.DOCUMENT_NODE)
1063                 ? (Document) node : node.getOwnerDocument();
1064         if (doc != null) {
1065             try {
1066                 return doc.getXmlEncoding();
1067             } // The VM ran out of memory or there was some other serious problem. Re-throw.
1068             catch (VirtualMachineError | ThreadDeath vme) {
1069                 throw vme;
1070             } // Ignore all other exceptions and errors
1071             catch (Throwable t) {
1072             }
1073         }
1074         return null;
1075     }
1076 
1077 } //DOMSerializerImpl