KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xml > serialize > DOMSerializerImpl


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xml.serialize;
18
19 import java.io.FileOutputStream JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.OutputStream JavaDoc;
22 import java.io.StringWriter JavaDoc;
23 import java.io.UnsupportedEncodingException JavaDoc;
24 import java.io.Writer JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.net.HttpURLConnection JavaDoc;
27 import java.net.URL JavaDoc;
28 import java.net.URLConnection JavaDoc;
29 import java.util.StringTokenizer JavaDoc;
30 import java.util.Vector JavaDoc;
31
32 import org.apache.xerces.dom.CoreDocumentImpl;
33 import org.apache.xerces.dom.DOMErrorImpl;
34 import org.apache.xerces.dom.DOMLocatorImpl;
35 import org.apache.xerces.dom.DOMMessageFormatter;
36 import org.apache.xerces.dom.DOMNormalizer;
37 import org.apache.xerces.dom.DOMStringListImpl;
38 import org.w3c.dom.DOMConfiguration JavaDoc;
39 import org.w3c.dom.DOMError JavaDoc;
40 import org.w3c.dom.DOMErrorHandler JavaDoc;
41 import org.w3c.dom.DOMStringList JavaDoc;
42 import org.apache.xerces.impl.Constants;
43 import org.apache.xerces.impl.XMLEntityManager;
44 import org.apache.xerces.util.NamespaceSupport;
45 import org.apache.xerces.util.SymbolTable;
46 import org.apache.xerces.util.XML11Char;
47 import org.apache.xerces.util.XMLChar;
48 import org.w3c.dom.Attr JavaDoc;
49 import org.w3c.dom.Comment JavaDoc;
50 import org.w3c.dom.DOMException JavaDoc;
51 import org.w3c.dom.Document JavaDoc;
52 import org.w3c.dom.DocumentFragment JavaDoc;
53 import org.w3c.dom.Element JavaDoc;
54 import org.w3c.dom.NamedNodeMap JavaDoc;
55 import org.w3c.dom.Node JavaDoc;
56 import org.w3c.dom.ProcessingInstruction JavaDoc;
57 import org.w3c.dom.ls.LSException JavaDoc;
58 import org.w3c.dom.ls.LSOutput JavaDoc;
59 import org.w3c.dom.ls.LSSerializer JavaDoc;
60 import org.w3c.dom.ls.LSSerializerFilter JavaDoc;
61
62
63 /**
64  * EXPERIMENTAL: Implemenatation of DOM Level 3 org.w3c.ls.LSSerializer by delegating serialization
65  * calls to <CODE>XMLSerializer</CODE>.
66  * LSSerializer provides an API for serializing (writing) a DOM document out in an
67  * XML document. The XML data is written to an output stream.
68  * During serialization of XML data, namespace fixup is done when possible as
69  * defined in DOM Level 3 Core, Appendix B.
70  *
71  * @author Elena Litani, IBM
72  * @author Gopal Sharma, Sun Microsystems
73  * @author Arun Yadav, Sun Microsystems
74  * @version $Id: DOMSerializerImpl.java,v 1.36 2005/06/13 22:26:42 nddelima Exp $
75  */

76 public class DOMSerializerImpl implements LSSerializer JavaDoc, DOMConfiguration JavaDoc {
77
78     // TODO: When DOM Level 3 goes to REC replace method calls using
79
// reflection for: getXmlEncoding, getInputEncoding and getXmlEncoding
80
// with regular static calls on the Document object.
81

82     // data
83
// serializer
84
private XMLSerializer serializer;
85
86     // XML 1.1 serializer
87
private XML11Serializer xml11Serializer;
88     
89     //Recognized parameters
90
private DOMStringList JavaDoc fRecognizedParameters;
91     
92     /** REVISIT: Currently we handle 3 different configurations, would be nice just have one configuration
93      * that has different recognized parameters depending if it is used in Core/LS.
94      */

95     protected short features = 0;
96
97     protected final static short NAMESPACES = 0x1<<0;
98     protected final static short WELLFORMED = 0x1<<1;
99     protected final static short ENTITIES = 0x1<<2;
100     protected final static short CDATA = 0x1<<3;
101     protected final static short SPLITCDATA = 0x1<<4;
102     protected final static short COMMENTS = 0x1<<5;
103     protected final static short DISCARDDEFAULT = 0x1<<6;
104     protected final static short INFOSET = 0x1<<7;
105     protected final static short XMLDECL = 0x1<<8;
106     protected final static short NSDECL = 0x1<<9;
107     protected final static short DOM_ELEMENT_CONTENT_WHITESPACE = 0x1<<10;
108     
109     // well-formness checking
110
private DOMErrorHandler JavaDoc fErrorHandler = null;
111     private final DOMErrorImpl fError = new DOMErrorImpl();
112     private final DOMLocatorImpl fLocator = new DOMLocatorImpl();
113     private static final RuntimeException JavaDoc abort = new RuntimeException JavaDoc();
114
115     /**
116      * Constructs a new LSSerializer.
117      * The constructor turns on the namespace support in <code>XMLSerializer</code> and
118      * initializes the following fields: fNSBinder, fLocalNSBinder, fSymbolTable,
119      * fEmptySymbol, fXmlSymbol, fXmlnsSymbol, fNamespaceCounter, fFeatures.
120      */

121     public DOMSerializerImpl() {
122         // set default features
123
features |= NAMESPACES;
124         features |= ENTITIES;
125         features |= COMMENTS;
126         features |= CDATA;
127         features |= SPLITCDATA;
128         features |= WELLFORMED;
129         features |= NSDECL;
130         features |= DOM_ELEMENT_CONTENT_WHITESPACE;
131         features |= DISCARDDEFAULT;
132         features |= XMLDECL;
133              
134         serializer = new XMLSerializer();
135         initSerializer(serializer);
136     }
137
138
139
140     //
141
// LSSerializer methods
142
//
143

144     public DOMConfiguration JavaDoc getDomConfig(){
145         return this;
146     }
147
148     /** DOM L3-EXPERIMENTAL:
149      * Setter for boolean and object parameters
150      */

151     public void setParameter(String JavaDoc name, Object JavaDoc value) throws DOMException JavaDoc {
152         if (value instanceof Boolean JavaDoc) {
153             boolean state = ((Boolean JavaDoc) 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             }
194             else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)){
195                 features =
196                     (short) (state
197                         ? features | CDATA
198                         : features & ~CDATA);
199                         }
200             else if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)){
201                 features =
202                      (short) (state
203                          ? features | COMMENTS
204                          : features & ~COMMENTS);
205             }
206                 else if (name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
207                     || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
208                     || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
209                     || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
210                     || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)
211                     || name.equalsIgnoreCase(Constants.DOM_FORMAT_PRETTY_PRINT)
212                     || name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)) {
213                 // true is not supported
214
if (state) {
215                     String JavaDoc msg =
216                         DOMMessageFormatter.formatMessage(
217                             DOMMessageFormatter.DOM_DOMAIN,
218                             "FEATURE_NOT_SUPPORTED",
219                             new Object JavaDoc[] { name });
220                     throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
221                 }
222             }else if (
223             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 JavaDoc msg =
235                         DOMMessageFormatter.formatMessage(
236                             DOMMessageFormatter.DOM_DOMAIN,
237                             "FEATURE_NOT_SUPPORTED",
238                             new Object JavaDoc[] { name });
239                     throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
240                 }
241             } else {
242                 String JavaDoc msg =
243                     DOMMessageFormatter.formatMessage(
244                         DOMMessageFormatter.DOM_DOMAIN,
245                         "FEATURE_NOT_FOUND",
246                         new Object JavaDoc[] { name });
247                 throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
248             }
249         } else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
250             if (value == null || value instanceof DOMErrorHandler JavaDoc) {
251                 fErrorHandler = (DOMErrorHandler JavaDoc)value;
252             } else {
253                 String JavaDoc msg =
254                     DOMMessageFormatter.formatMessage(
255                         DOMMessageFormatter.DOM_DOMAIN,
256                         "TYPE_MISMATCH_ERR",
257                         new Object JavaDoc[] { name });
258                 throw new DOMException JavaDoc(DOMException.TYPE_MISMATCH_ERR, msg);
259             }
260         } else if (
261             name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)
262                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)
263                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)
264                 && value != null) {
265             String JavaDoc msg =
266                 DOMMessageFormatter.formatMessage(
267                     DOMMessageFormatter.DOM_DOMAIN,
268                     "FEATURE_NOT_SUPPORTED",
269                     new Object JavaDoc[] { name });
270             throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
271         } else {
272             String JavaDoc msg =
273                 DOMMessageFormatter.formatMessage(
274                     DOMMessageFormatter.DOM_DOMAIN,
275                     "FEATURE_NOT_FOUND",
276                     new Object JavaDoc[] { name });
277             throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR, msg);
278         }
279     }
280
281     /** DOM L3-EXPERIMENTAL:
282      * Check if parameter can be set
283      */

284     public boolean canSetParameter(String JavaDoc name, Object JavaDoc state) {
285         if (state == null){
286             return true;
287         }
288         
289         if (state instanceof Boolean JavaDoc){
290             boolean value = ((Boolean JavaDoc)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_NAMESPACE_DECLARATIONS)){
301                 // both values supported
302
return true;
303             }
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_FORMAT_PRETTY_PRINT)
310                 || name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)) {
311                 // true is not supported
312
return !value;
313             }
314             else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
315                     || name.equalsIgnoreCase(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
316                 // false is not supported
317
return value;
318                     }
319         }
320         else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER) &&
321                 state == null || state instanceof DOMErrorHandler JavaDoc){
322             return true;
323         }
324         return false;
325     }
326
327     /**
328      * DOM Level 3 Core CR - Experimental.
329      *
330      * The list of the parameters supported by this
331      * <code>DOMConfiguration</code> object and for which at least one value
332      * can be set by the application. Note that this list can also contain
333      * parameter names defined outside this specification.
334      */

335     public DOMStringList JavaDoc getParameterNames() {
336         
337         if (fRecognizedParameters == null){
338             Vector JavaDoc parameters = new Vector JavaDoc();
339
340             //Add DOM recognized parameters
341
//REVISIT: Would have been nice to have a list of
342
//recognized parameters.
343
parameters.add(Constants.DOM_NAMESPACES);
344             parameters.add(Constants.DOM_SPLIT_CDATA);
345             parameters.add(Constants.DOM_DISCARD_DEFAULT_CONTENT);
346             parameters.add(Constants.DOM_XMLDECL);
347             parameters.add(Constants.DOM_CANONICAL_FORM);
348             parameters.add(Constants.DOM_VALIDATE_IF_SCHEMA);
349             parameters.add(Constants.DOM_VALIDATE);
350             parameters.add(Constants.DOM_CHECK_CHAR_NORMALIZATION);
351             parameters.add(Constants.DOM_DATATYPE_NORMALIZATION);
352             parameters.add(Constants.DOM_FORMAT_PRETTY_PRINT);
353             parameters.add(Constants.DOM_NORMALIZE_CHARACTERS);
354             parameters.add(Constants.DOM_WELLFORMED);
355             parameters.add(Constants.DOM_INFOSET);
356             parameters.add(Constants.DOM_NAMESPACE_DECLARATIONS);
357             parameters.add(Constants.DOM_ELEMENT_CONTENT_WHITESPACE);
358             parameters.add(Constants.DOM_ENTITIES);
359             parameters.add(Constants.DOM_CDATA_SECTIONS);
360             parameters.add(Constants.DOM_COMMENTS);
361             parameters.add(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS);
362             parameters.add(Constants.DOM_ERROR_HANDLER);
363             //parameters.add(Constants.DOM_SCHEMA_LOCATION);
364
//parameters.add(Constants.DOM_SCHEMA_TYPE);
365

366             //Add recognized xerces features and properties
367

368             fRecognizedParameters = new DOMStringListImpl(parameters);
369             
370         }
371
372         return fRecognizedParameters;
373     }
374     
375     /** DOM L3-EXPERIMENTAL:
376      * Getter for boolean and object parameters
377      */

378     public Object JavaDoc getParameter(String JavaDoc name) throws DOMException JavaDoc {
379         if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
380             return ((features & COMMENTS) != 0) ? Boolean.TRUE : Boolean.FALSE;
381         } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
382             return (features & NAMESPACES) != 0 ? Boolean.TRUE : Boolean.FALSE;
383         } else if (name.equalsIgnoreCase(Constants.DOM_XMLDECL)) {
384             return (features & XMLDECL) != 0 ? Boolean.TRUE : Boolean.FALSE;
385         } else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
386             return (features & CDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
387         } else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
388             return (features & ENTITIES) != 0 ? Boolean.TRUE : Boolean.FALSE;
389         } else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
390             return (features & SPLITCDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
391         } else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
392             return (features & WELLFORMED) != 0 ? Boolean.TRUE : Boolean.FALSE;
393         } else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
394             return (features & NSDECL) != 0 ? Boolean.TRUE : Boolean.FALSE;
395         } else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE) ||
396                    name.equalsIgnoreCase(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
397             return Boolean.TRUE;
398         }else if (name.equalsIgnoreCase(Constants.DOM_DISCARD_DEFAULT_CONTENT)){
399             return ((features & DISCARDDEFAULT)!=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_FORMAT_PRETTY_PRINT)
411                 || name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
412                 || name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
413                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
414                 || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
415                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
416                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
417                 || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
418             return Boolean.FALSE;
419         } else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
420             return fErrorHandler;
421         } else if (
422             name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)
423                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)
424                 || name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
425             String JavaDoc msg =
426                 DOMMessageFormatter.formatMessage(
427                     DOMMessageFormatter.DOM_DOMAIN,
428                     "FEATURE_NOT_SUPPORTED",
429                     new Object JavaDoc[] { name });
430             throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
431         } else {
432             String JavaDoc msg =
433                 DOMMessageFormatter.formatMessage(
434                     DOMMessageFormatter.DOM_DOMAIN,
435                     "FEATURE_NOT_FOUND",
436                     new Object JavaDoc[] { name });
437             throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR, msg);
438         }
439     }
440
441
442     /**
443      * DOM L3 EXPERIMENTAL:
444      * Serialize the specified node as described above in the description of
445      * <code>LSSerializer</code>. The result of serializing the node is
446      * returned as a string. Writing a Document or Entity node produces a
447      * serialized form that is well formed XML. Writing other node types
448      * produces a fragment of text in a form that is not fully defined by
449      * this document, but that should be useful to a human for debugging or
450      * diagnostic purposes.
451      * @param wnode The node to be written.
452      * @return Returns the serialized data
453      * @exception DOMException
454      * DOMSTRING_SIZE_ERR: The resulting string is too long to fit in a
455      * <code>DOMString</code>.
456      * @exception LSException
457      * SERIALIZE_ERR: Unable to serialize the node. DOM applications should
458      * attach a <code>DOMErrorHandler</code> using the parameter
459      * &quot;<i>error-handler</i>&quot; to get details on error.
460      */

461     public String JavaDoc writeToString(Node JavaDoc wnode) throws DOMException JavaDoc, LSException JavaDoc {
462         // determine which serializer to use:
463
Document JavaDoc doc = (wnode.getNodeType() == Node.DOCUMENT_NODE)?(Document JavaDoc)wnode:wnode.getOwnerDocument();
464         Method getVersion = null;
465         XMLSerializer ser = null;
466         String JavaDoc ver = null;
467         // this should run under JDK 1.1.8...
468
try {
469             getVersion = doc.getClass().getMethod("getXmlVersion", new Class JavaDoc[]{});
470             if(getVersion != null ) {
471                 ver = (String JavaDoc)getVersion.invoke(doc, (Object JavaDoc[]) null);
472             }
473         } catch (Exception JavaDoc e) {
474             // no way to test the version...
475
// ignore the exception
476
}
477         if(ver != null && ver.equals("1.1")) {
478             if(xml11Serializer == null) {
479                 xml11Serializer = new XML11Serializer();
480                 initSerializer(xml11Serializer);
481             }
482             // copy setting from "main" serializer to XML 1.1 serializer
483
copySettings(serializer, xml11Serializer);
484             ser = xml11Serializer;
485         } else {
486             ser = serializer;
487         }
488
489         StringWriter JavaDoc destination = new StringWriter JavaDoc();
490         try {
491             prepareForSerialization(ser, wnode);
492             ser._format.setEncoding("UTF-16");
493             ser.setOutputCharStream(destination);
494             if (wnode.getNodeType() == Node.DOCUMENT_NODE) {
495                 ser.serialize((Document JavaDoc)wnode);
496             }
497             else if (wnode.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
498                 ser.serialize((DocumentFragment JavaDoc)wnode);
499             }
500             else if (wnode.getNodeType() == Node.ELEMENT_NODE) {
501                 ser.serialize((Element JavaDoc)wnode);
502             }
503             else {
504                 String JavaDoc msg = DOMMessageFormatter.formatMessage(
505                     DOMMessageFormatter.SERIALIZER_DOMAIN,
506                     "unable-to-serialize-node", null);
507                 if (ser.fDOMErrorHandler != null) {
508                     DOMErrorImpl error = new DOMErrorImpl();
509                     error.fType = "unable-to-serialize-node";
510                     error.fMessage = msg;
511                     error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
512                     ser.fDOMErrorHandler.handleError(error);
513                 }
514                 throw new LSException JavaDoc(LSException.SERIALIZE_ERR, msg);
515             }
516         } catch (LSException JavaDoc lse) {
517             // Rethrow LSException.
518
throw lse;
519         } catch (RuntimeException JavaDoc e) {
520             if (e == DOMNormalizer.abort){
521                 // stopped at user request
522
return null;
523             }
524             throw new LSException JavaDoc(LSException.SERIALIZE_ERR, e.toString());
525         } catch (IOException JavaDoc ioe) {
526             // REVISIT: A generic IOException doesn't provide enough information
527
// to determine that the serialized document is too large to fit
528
// into a string. This could have thrown for some other reason. -- mrglavas
529
String JavaDoc msg = DOMMessageFormatter.formatMessage(
530                 DOMMessageFormatter.DOM_DOMAIN,
531                 "STRING_TOO_LONG",
532                 new Object JavaDoc[] { ioe.getMessage()});
533             throw new DOMException JavaDoc(DOMException.DOMSTRING_SIZE_ERR,msg);
534         }
535         return destination.toString();
536     }
537
538     /**
539      * DOM L3 EXPERIMENTAL:
540      * The end-of-line sequence of characters to be used in the XML being
541      * written out. The only permitted values are these:
542      * <dl>
543      * <dt><code>null</code></dt>
544      * <dd>
545      * Use a default end-of-line sequence. DOM implementations should choose
546      * the default to match the usual convention for text files in the
547      * environment being used. Implementations must choose a default
548      * sequence that matches one of those allowed by 2.11 "End-of-Line
549      * Handling". </dd>
550      * <dt>CR</dt>
551      * <dd>The carriage-return character (#xD).</dd>
552      * <dt>CR-LF</dt>
553      * <dd> The
554      * carriage-return and line-feed characters (#xD #xA). </dd>
555      * <dt>LF</dt>
556      * <dd> The line-feed
557      * character (#xA). </dd>
558      * </dl>
559      * <br>The default value for this attribute is <code>null</code>.
560      */

561     public void setNewLine(String JavaDoc newLine) {
562         serializer._format.setLineSeparator(newLine);
563     }
564
565
566     /**
567      * DOM L3 EXPERIMENTAL:
568      * The end-of-line sequence of characters to be used in the XML being
569      * written out. The only permitted values are these:
570      * <dl>
571      * <dt><code>null</code></dt>
572      * <dd>
573      * Use a default end-of-line sequence. DOM implementations should choose
574      * the default to match the usual convention for text files in the
575      * environment being used. Implementations must choose a default
576      * sequence that matches one of those allowed by 2.11 "End-of-Line
577      * Handling". </dd>
578      * <dt>CR</dt>
579      * <dd>The carriage-return character (#xD).</dd>
580      * <dt>CR-LF</dt>
581      * <dd> The
582      * carriage-return and line-feed characters (#xD #xA). </dd>
583      * <dt>LF</dt>
584      * <dd> The line-feed
585      * character (#xA). </dd>
586      * </dl>
587      * <br>The default value for this attribute is <code>null</code>.
588      */

589     public String JavaDoc getNewLine() {
590         return serializer._format.getLineSeparator();
591     }
592
593
594     /**
595      * When the application provides a filter, the serializer will call out
596      * to the filter before serializing each Node. Attribute nodes are never
597      * passed to the filter. The filter implementation can choose to remove
598      * the node from the stream or to terminate the serialization early.
599      */

600     public LSSerializerFilter JavaDoc getFilter(){
601         return serializer.fDOMFilter;
602     }
603     /**
604      * When the application provides a filter, the serializer will call out
605      * to the filter before serializing each Node. Attribute nodes are never
606      * passed to the filter. The filter implementation can choose to remove
607      * the node from the stream or to terminate the serialization early.
608      */

609     public void setFilter(LSSerializerFilter JavaDoc filter){
610         serializer.fDOMFilter = filter;
611     }
612
613     // this initializes a newly-created serializer
614
private void initSerializer(XMLSerializer ser) {
615         ser.fNSBinder = new NamespaceSupport();
616         ser.fLocalNSBinder = new NamespaceSupport();
617         ser.fSymbolTable = new SymbolTable();
618     }
619
620     // copies all settings that could have been modified
621
// by calls to LSSerializer methods from one serializer to another.
622
// IMPORTANT: if new methods are implemented or more settings of
623
// the serializer are made alterable, this must be
624
// reflected in this method!
625
private void copySettings(XMLSerializer src, XMLSerializer dest) {
626         dest.fDOMErrorHandler = fErrorHandler;
627         dest._format.setEncoding(src._format.getEncoding());
628         dest._format.setLineSeparator(src._format.getLineSeparator());
629         dest.fDOMFilter = src.fDOMFilter;
630     }//copysettings
631

632     /**
633       * Serialize the specified node as described above in the general
634       * description of the <code>LSSerializer</code> interface. The output
635       * is written to the supplied <code>LSOutput</code>.
636       * <br> When writing to a <code>LSOutput</code>, the encoding is found by
637       * looking at the encoding information that is reachable through the
638       * <code>LSOutput</code> and the item to be written (or its owner
639       * document) in this order:
640       * <ol>
641       * <li> <code>LSOutput.encoding</code>,
642       * </li>
643       * <li>
644       * <code>Document.actualEncoding</code>,
645       * </li>
646       * <li>
647       * <code>Document.xmlEncoding</code>.
648       * </li>
649       * </ol>
650       * <br> If no encoding is reachable through the above properties, a
651       * default encoding of "UTF-8" will be used.
652       * <br> If the specified encoding is not supported an
653       * "unsupported-encoding" error is raised.
654       * <br> If no output is specified in the <code>LSOutput</code>, a
655       * "no-output-specified" error is raised.
656       * @param node The node to serialize.
657       * @param destination The destination for the serialized DOM.
658       * @return Returns <code>true</code> if <code>node</code> was
659       * successfully serialized and <code>false</code> in case the node
660       * couldn't be serialized.
661       */

662     public boolean write(Node JavaDoc node, LSOutput JavaDoc destination) throws LSException JavaDoc{
663
664         if (node == null)
665             return false;
666             
667         Method getVersion = null;
668         XMLSerializer ser = null;
669         String JavaDoc ver = null;
670         Document JavaDoc fDocument =(node.getNodeType() == Node.DOCUMENT_NODE)
671                 ? (Document JavaDoc) node
672                 : node.getOwnerDocument();
673         // this should run under JDK 1.1.8...
674
try {
675             getVersion = fDocument.getClass().getMethod("getXmlVersion", new Class JavaDoc[] {});
676             if (getVersion != null) {
677                 ver = (String JavaDoc) getVersion.invoke(fDocument, (Object JavaDoc[]) null);
678             }
679         } catch (Exception JavaDoc e) {
680             //no way to test the version...
681
//ignore the exception
682
}
683         //determine which serializer to use:
684
if (ver != null && ver.equals("1.1")) {
685             if (xml11Serializer == null) {
686                 xml11Serializer = new XML11Serializer();
687                 initSerializer(xml11Serializer);
688             }
689             //copy setting from "main" serializer to XML 1.1 serializer
690
copySettings(serializer, xml11Serializer);
691             ser = xml11Serializer;
692         } else {
693             ser = serializer;
694         }
695
696         String JavaDoc encoding = null;
697         if ((encoding = destination.getEncoding()) == null) {
698             try {
699   &n