KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dom4j > io > DOMWriter


1 /*
2  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
3  *
4  * This software is open source.
5  * See the bottom of this file for the licence.
6  */

7
8 package org.dom4j.io;
9
10 import java.util.List JavaDoc;
11
12 import org.dom4j.Attribute;
13 import org.dom4j.CDATA;
14 import org.dom4j.Comment;
15 import org.dom4j.Document;
16 import org.dom4j.DocumentException;
17 import org.dom4j.Element;
18 import org.dom4j.Entity;
19 import org.dom4j.Namespace;
20 import org.dom4j.ProcessingInstruction;
21 import org.dom4j.Text;
22 import org.dom4j.tree.NamespaceStack;
23
24 import org.w3c.dom.DOMImplementation JavaDoc;
25
26 /**
27  * <p>
28  * <code>DOMWriter</code> takes a DOM4J tree and outputs it as a W3C DOM
29  * object
30  * </p>
31  *
32  * @author <a HREF="mailto:james.strachan@metastuff.com">James Strachan </a>
33  * @version $Revision: 1.17 $
34  */

35 public class DOMWriter {
36     private static boolean loggedWarning = false;
37
38     private static final String JavaDoc[] DEFAULT_DOM_DOCUMENT_CLASSES = {
39             "org.apache.xerces.dom.DocumentImpl", // Xerces
40
"gnu.xml.dom.DomDocument", // GNU JAXP
41
"org.apache.crimson.tree.XmlDocument", // Crimson
42
"com.sun.xml.tree.XmlDocument", // Sun's Project X
43
"oracle.xml.parser.v2.XMLDocument", // Oracle V2
44
"oracle.xml.parser.XMLDocument", // Oracle V1
45
"org.dom4j.dom.DOMDocument" // Internal DOM implementation
46
};
47
48     // the Class used to create new DOM Document instances
49
private Class JavaDoc domDocumentClass;
50
51     /** stack of <code>Namespace</code> objects */
52     private NamespaceStack namespaceStack = new NamespaceStack();
53
54     public DOMWriter() {
55     }
56
57     public DOMWriter(Class JavaDoc domDocumentClass) {
58         this.domDocumentClass = domDocumentClass;
59     }
60
61     public Class JavaDoc getDomDocumentClass() throws DocumentException {
62         Class JavaDoc result = domDocumentClass;
63
64         if (result == null) {
65             // lets try and find one in the classpath
66
int size = DEFAULT_DOM_DOCUMENT_CLASSES.length;
67
68             for (int i = 0; i < size; i++) {
69                 try {
70                     String JavaDoc name = DEFAULT_DOM_DOCUMENT_CLASSES[i];
71                     result = Class.forName(name, true, DOMWriter.class
72                             .getClassLoader());
73
74                     if (result != null) {
75                         break;
76                     }
77                 } catch (Exception JavaDoc e) {
78                     // could not load class correctly
79
// lets carry on to the next one
80
}
81             }
82         }
83
84         return result;
85     }
86
87     /**
88      * Sets the DOM {@link org.w3c.dom.Document}implementation class used by
89      * the writer when creating DOM documents.
90      *
91      * @param domDocumentClass
92      * is the Class implementing the {@linkorg.w3c.dom.Document}
93      * interface
94      */

95     public void setDomDocumentClass(Class JavaDoc domDocumentClass) {
96         this.domDocumentClass = domDocumentClass;
97     }
98
99     /**
100      * Sets the DOM {@link org.w3c.dom.Document}implementation class name used
101      * by the writer when creating DOM documents.
102      *
103      * @param name
104      * is the name of the Class implementing the {@link
105      * org.w3c.dom.Document} interface
106      *
107      * @throws DocumentException
108      * if the class could not be loaded
109      */

110     public void setDomDocumentClassName(String JavaDoc name) throws DocumentException {
111         try {
112             this.domDocumentClass = Class.forName(name, true, DOMWriter.class
113                     .getClassLoader());
114         } catch (Exception JavaDoc e) {
115             throw new DocumentException("Could not load the DOM Document "
116                     + "class: " + name, e);
117         }
118     }
119
120     public org.w3c.dom.Document JavaDoc write(Document document)
121             throws DocumentException {
122         if (document instanceof org.w3c.dom.Document JavaDoc) {
123             return (org.w3c.dom.Document JavaDoc) document;
124         }
125
126         resetNamespaceStack();
127
128         org.w3c.dom.Document JavaDoc domDocument = createDomDocument(document);
129         appendDOMTree(domDocument, domDocument, document.content());
130         namespaceStack.clear();
131
132         return domDocument;
133     }
134
135     public org.w3c.dom.Document JavaDoc write(Document document,
136             org.w3c.dom.DOMImplementation JavaDoc domImpl) throws DocumentException {
137         if (document instanceof org.w3c.dom.Document JavaDoc) {
138             return (org.w3c.dom.Document JavaDoc) document;
139         }
140
141         resetNamespaceStack();
142
143         org.w3c.dom.Document JavaDoc domDocument = createDomDocument(document, domImpl);
144         appendDOMTree(domDocument, domDocument, document.content());
145         namespaceStack.clear();
146
147         return domDocument;
148     }
149
150     protected void appendDOMTree(org.w3c.dom.Document JavaDoc domDocument,
151             org.w3c.dom.Node JavaDoc domCurrent, List JavaDoc content) {
152         int size = content.size();
153
154         for (int i = 0; i < size; i++) {
155             Object JavaDoc object = content.get(i);
156
157             if (object instanceof Element) {
158                 appendDOMTree(domDocument, domCurrent, (Element) object);
159             } else if (object instanceof String JavaDoc) {
160                 appendDOMTree(domDocument, domCurrent, (String JavaDoc) object);
161             } else if (object instanceof Text) {
162                 Text text = (Text) object;
163                 appendDOMTree(domDocument, domCurrent, text.getText());
164             } else if (object instanceof CDATA) {
165                 appendDOMTree(domDocument, domCurrent, (CDATA) object);
166             } else if (object instanceof Comment) {
167                 appendDOMTree(domDocument, domCurrent, (Comment) object);
168             } else if (object instanceof Entity) {
169                 appendDOMTree(domDocument, domCurrent, (Entity) object);
170             } else if (object instanceof ProcessingInstruction) {
171                 appendDOMTree(domDocument, domCurrent,
172                         (ProcessingInstruction) object);
173             }
174         }
175     }
176
177     protected void appendDOMTree(org.w3c.dom.Document JavaDoc domDocument,
178             org.w3c.dom.Node JavaDoc domCurrent, Element element) {
179         String JavaDoc elUri = element.getNamespaceURI();
180         String JavaDoc elName = element.getQualifiedName();
181         org.w3c.dom.Element JavaDoc domElement = domDocument.createElementNS(elUri,
182                 elName);
183
184         int stackSize = namespaceStack.size();
185
186         // add the namespace of the element first
187
Namespace elementNamespace = element.getNamespace();
188
189         if (isNamespaceDeclaration(elementNamespace)) {
190             namespaceStack.push(elementNamespace);
191             writeNamespace(domElement, elementNamespace);
192         }
193
194         // add the additional declared namespaces
195
List JavaDoc declaredNamespaces = element.declaredNamespaces();
196
197         for (int i = 0, size = declaredNamespaces.size(); i < size; i++) {
198             Namespace namespace = (Namespace) declaredNamespaces.get(i);
199
200             if (isNamespaceDeclaration(namespace)) {
201                 namespaceStack.push(namespace);
202                 writeNamespace(domElement, namespace);
203             }
204         }
205
206         // add the attributes
207
for (int i = 0, size = element.attributeCount(); i < size; i++) {
208             Attribute attribute = (Attribute) element.attribute(i);
209             String JavaDoc attUri = attribute.getNamespaceURI();
210             String JavaDoc attName = attribute.getQualifiedName();
211             String JavaDoc value = attribute.getValue();
212             domElement.setAttributeNS(attUri, attName, value);
213         }
214
215         // add content
216
appendDOMTree(domDocument, domElement, element.content());
217
218         domCurrent.appendChild(domElement);
219
220         while (namespaceStack.size() > stackSize) {
221             namespaceStack.pop();
222         }
223     }
224
225     protected void appendDOMTree(org.w3c.dom.Document JavaDoc domDocument,
226             org.w3c.dom.Node JavaDoc domCurrent, CDATA cdata) {
227         org.w3c.dom.CDATASection JavaDoc domCDATA = domDocument
228                 .createCDATASection(cdata.getText());
229         domCurrent.appendChild(domCDATA);
230     }
231
232     protected void appendDOMTree(org.w3c.dom.Document JavaDoc domDocument,
233             org.w3c.dom.Node JavaDoc domCurrent, Comment comment) {
234         org.w3c.dom.Comment JavaDoc domComment = domDocument.createComment(comment
235                 .getText());
236         domCurrent.appendChild(domComment);
237     }
238
239     protected void appendDOMTree(org.w3c.dom.Document JavaDoc domDocument,
240             org.w3c.dom.Node JavaDoc domCurrent, String JavaDoc text) {
241         org.w3c.dom.Text JavaDoc domText = domDocument.createTextNode(text);
242         domCurrent.appendChild(domText);
243     }
244
245     protected void appendDOMTree(org.w3c.dom.Document JavaDoc domDocument,
246             org.w3c.dom.Node JavaDoc domCurrent, Entity entity) {
247         org.w3c.dom.EntityReference JavaDoc domEntity = domDocument
248                 .createEntityReference(entity.getName());
249         domCurrent.appendChild(domEntity);
250     }
251
252     protected void appendDOMTree(org.w3c.dom.Document JavaDoc domDoc,
253             org.w3c.dom.Node JavaDoc domCurrent, ProcessingInstruction pi) {
254         org.w3c.dom.ProcessingInstruction JavaDoc domPI = domDoc
255                 .createProcessingInstruction(pi.getTarget(), pi.getText());
256         domCurrent.appendChild(domPI);
257     }
258
259     protected void writeNamespace(org.w3c.dom.Element JavaDoc domElement,
260             Namespace namespace) {
261         String JavaDoc attributeName = attributeNameForNamespace(namespace);
262
263         // domElement.setAttributeNS("", attributeName, namespace.getURI());
264
domElement.setAttribute(attributeName, namespace.getURI());
265     }
266
267     protected String JavaDoc attributeNameForNamespace(Namespace namespace) {
268         String JavaDoc xmlns = "xmlns";
269         String JavaDoc prefix = namespace.getPrefix();
270
271         if (prefix.length() > 0) {
272             return xmlns + ":" + prefix;
273         }
274
275         return xmlns;
276     }
277
278     protected org.w3c.dom.Document JavaDoc createDomDocument(Document document)
279             throws DocumentException {
280         org.w3c.dom.Document JavaDoc result = null;
281
282         // use the given domDocumentClass (if not null)
283
if (domDocumentClass != null) {
284             try {
285                 result = (org.w3c.dom.Document JavaDoc) domDocumentClass.newInstance();
286             } catch (Exception JavaDoc e) {
287                 throw new DocumentException(
288                         "Could not instantiate an instance "
289                                 + "of DOM Document with class: "
290                                 + domDocumentClass.getName(), e);
291             }
292         } else {
293             // lets try JAXP first before using the hardcoded default parsers
294
result = createDomDocumentViaJAXP();
295
296             if (result == null) {
297                 Class JavaDoc theClass = getDomDocumentClass();
298
299                 try {
300                     result = (org.w3c.dom.Document JavaDoc) theClass.newInstance();
301                 } catch (Exception JavaDoc e) {
302                     throw new DocumentException("Could not instantiate an "
303                             + "instance of DOM Document " + "with class: "
304                             + theClass.getName(), e);
305                 }
306             }
307         }
308
309         return result;
310     }
311
312     protected org.w3c.dom.Document JavaDoc createDomDocumentViaJAXP()
313             throws DocumentException {
314         try {
315             return JAXPHelper.createDocument(false, true);
316         } catch (Throwable JavaDoc e) {
317             if (!loggedWarning) {
318                 loggedWarning = true;
319
320                 if (SAXHelper.isVerboseErrorReporting()) {
321                     // log all exceptions as warnings and carry
322
// on as we have a default SAX parser we can use
323
System.out.println("Warning: Caught exception attempting "
324                             + "to use JAXP to create a W3C DOM " + "document");
325                     System.out.println("Warning: Exception was: " + e);
326                     e.printStackTrace();
327                 } else {
328                     System.out.println("Warning: Error occurred using JAXP to "
329                             + "create a DOM document.");
330                 }
331             }
332         }
333
334         return null;
335     }
336
337     protected org.w3c.dom.Document JavaDoc createDomDocument(Document document,
338             DOMImplementation JavaDoc domImpl) throws DocumentException {
339         String JavaDoc namespaceURI = null;
340         String JavaDoc qualifiedName = null;
341         org.w3c.dom.DocumentType JavaDoc docType = null;
342
343         return domImpl.createDocument(namespaceURI, qualifiedName, docType);
344     }
345
346     protected boolean isNamespaceDeclaration(Namespace ns) {
347         if ((ns != null) && (ns != Namespace.NO_NAMESPACE)
348                 && (ns != Namespace.XML_NAMESPACE)) {
349             String JavaDoc uri = ns.getURI();
350
351             if ((uri != null) && (uri.length() > 0)) {
352                 if (!namespaceStack.contains(ns)) {
353                     return true;
354                 }
355             }
356         }
357
358         return false;
359     }
360
361     protected void resetNamespaceStack() {
362         namespaceStack.clear();
363         namespaceStack.push(Namespace.XML_NAMESPACE);
364     }
365 }
366
367 /*
368  * Redistribution and use of this software and associated documentation
369  * ("Software"), with or without modification, are permitted provided that the
370  * following conditions are met:
371  *
372  * 1. Redistributions of source code must retain copyright statements and
373  * notices. Redistributions must also contain a copy of this document.
374  *
375  * 2. Redistributions in binary form must reproduce the above copyright notice,
376  * this list of conditions and the following disclaimer in the documentation
377  * and/or other materials provided with the distribution.
378  *
379  * 3. The name "DOM4J" must not be used to endorse or promote products derived
380  * from this Software without prior written permission of MetaStuff, Ltd. For
381  * written permission, please contact dom4j-info@metastuff.com.
382  *
383  * 4. Products derived from this Software may not be called "DOM4J" nor may
384  * "DOM4J" appear in their names without prior written permission of MetaStuff,
385  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
386  *
387  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
388  *
389  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
390  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
391  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
392  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
393  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
394  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
395  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
396  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
397  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
398  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
399  * POSSIBILITY OF SUCH DAMAGE.
400  *
401  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
402  */

403
Popular Tags