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