Clover coverage report - dom4j - 1.6.1 Coverage timestamp: ma mei 16 2005 14:23:01 GMT+01:00 FRAMES NO FRAMES |
file stats: | LOC: | 402 |  | Methods: | 21
| NCLOC: | 254 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
DOMWriter.java | 69,2% | 65,6% | 71,4% | 67,2% |

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;
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;
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[] 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 domDocumentClass;
50 |  |
51 |  | /** stack of <code>Namespace</code> objects */
52 |  | private NamespaceStack namespaceStack = new NamespaceStack();
53 |  |
54 | 14 | public DOMWriter() {
55 |  | }
56 |  |
57 | 2 | public DOMWriter(Class domDocumentClass) {
58 | 2 | this.domDocumentClass = domDocumentClass;
59 |  | }
60 |  |
61 | 0 | public Class getDomDocumentClass() throws DocumentException {
62 | 0 | Class result = domDocumentClass;
63 |  |
64 | 0 | if (result == null) {
65 |  | // lets try and find one in the classpath
66 | 0 | int size = DEFAULT_DOM_DOCUMENT_CLASSES.length;
67 |  |
68 | 0 | for (int i = 0; i < size; i++) {
69 | 0 | try {
70 | 0 | String name = DEFAULT_DOM_DOCUMENT_CLASSES[i];
71 | 0 | result = Class.forName(name, true, DOMWriter.class
72 |  | .getClassLoader());
73 |  |
74 | 0 | if (result != null) {
75 | 0 | break;
76 |  | }
77 |  | } catch (Exception e) {
78 |  | // could not load class correctly
79 |  | // lets carry on to the next one
80 |  | }
81 |  | }
82 |  | }
83 |  |
84 | 0 | 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 | 0 | public void setDomDocumentClass(Class domDocumentClass) {
96 | 0 | 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 | 0 | public void setDomDocumentClassName(String name) throws DocumentException {
111 | 0 | try {
112 | 0 | this.domDocumentClass = Class.forName(name, true, DOMWriter.class
113 |  | .getClassLoader());
114 |  | } catch (Exception e) {
115 | 0 | throw new DocumentException("Could not load the DOM Document "
116 |  | + "class: " + name, e);
117 |  | }
118 |  | }
119 |  |
120 | 16 | public org.w3c.dom.Document write(Document document)
121 |  | throws DocumentException {
122 | 16 | if (document instanceof org.w3c.dom.Document) {
123 | 1 | return (org.w3c.dom.Document) document;
124 |  | }
125 |  |
126 | 15 | resetNamespaceStack();
127 |  |
128 | 15 | org.w3c.dom.Document domDocument = createDomDocument(document);
129 | 15 | appendDOMTree(domDocument, domDocument, document.content());
130 | 15 | namespaceStack.clear();
131 |  |
132 | 15 | return domDocument;
133 |  | }
134 |  |
135 | 0 | public org.w3c.dom.Document write(Document document,
136 |  | org.w3c.dom.DOMImplementation domImpl) throws DocumentException {
137 | 0 | if (document instanceof org.w3c.dom.Document) {
138 | 0 | return (org.w3c.dom.Document) document;
139 |  | }
140 |  |
141 | 0 | resetNamespaceStack();
142 |  |
143 | 0 | org.w3c.dom.Document domDocument = createDomDocument(document, domImpl);
144 | 0 | appendDOMTree(domDocument, domDocument, document.content());
145 | 0 | namespaceStack.clear();
146 |  |
147 | 0 | return domDocument;
148 |  | }
149 |  |
150 | 4838 | protected void appendDOMTree(org.w3c.dom.Document domDocument,
151 |  | org.w3c.dom.Node domCurrent, List content) {
152 | 4838 | int size = content.size();
153 |  |
154 | 4838 | for (int i = 0; i < size; i++) {
155 | 13249 | Object object = content.get(i);
156 |  |
157 | 13249 | if (object instanceof Element) {
158 | 4823 | appendDOMTree(domDocument, domCurrent, (Element) object);
159 | 8426 | } else if (object instanceof String) {
160 | 0 | appendDOMTree(domDocument, domCurrent, (String) object);
161 | 8426 | } else if (object instanceof Text) {
162 | 8293 | Text text = (Text) object;
163 | 8293 | appendDOMTree(domDocument, domCurrent, text.getText());
164 | 133 | } else if (object instanceof CDATA) {
165 | 30 | appendDOMTree(domDocument, domCurrent, (CDATA) object);
166 | 103 | } else if (object instanceof Comment) {
167 | 68 | appendDOMTree(domDocument, domCurrent, (Comment) object);
168 | 35 | } else if (object instanceof Entity) {
169 | 0 | appendDOMTree(domDocument, domCurrent, (Entity) object);
170 | 35 | } else if (object instanceof ProcessingInstruction) {
171 | 2 | appendDOMTree(domDocument, domCurrent,
172 |  | (ProcessingInstruction) object);
173 |  | }
174 |  | }
175 |  | }
176 |  |
177 | 4823 | protected void appendDOMTree(org.w3c.dom.Document domDocument,
178 |  | org.w3c.dom.Node domCurrent, Element element) {
179 | 4823 | String elUri = element.getNamespaceURI();
180 | 4823 | String elName = element.getQualifiedName();
181 | 4823 | org.w3c.dom.Element domElement = domDocument.createElementNS(elUri,
182 |  | elName);
183 |  |
184 | 4823 | int stackSize = namespaceStack.size();
185 |  |
186 |  | // add the namespace of the element first
187 | 4823 | Namespace elementNamespace = element.getNamespace();
188 |  |
189 | 4823 | if (isNamespaceDeclaration(elementNamespace)) {
190 | 27 | namespaceStack.push(elementNamespace);
191 | 27 | writeNamespace(domElement, elementNamespace);
192 |  | }
193 |  |
194 |  | // add the additional declared namespaces
195 | 4823 | List declaredNamespaces = element.declaredNamespaces();
196 |  |
197 | 4823 | for (int i = 0, size = declaredNamespaces.size(); i < size; i++) {
198 | 33 | Namespace namespace = (Namespace) declaredNamespaces.get(i);
199 |  |
200 | 33 | if (isNamespaceDeclaration(namespace)) {
201 | 6 | namespaceStack.push(namespace);
202 | 6 | writeNamespace(domElement, namespace);
203 |  | }
204 |  | }
205 |  |
206 |  | // add the attributes
207 | 4823 | for (int i = 0, size = element.attributeCount(); i < size; i++) {
208 | 2492 | Attribute attribute = (Attribute) element.attribute(i);
209 | 2492 | String attUri = attribute.getNamespaceURI();
210 | 2492 | String attName = attribute.getQualifiedName();
211 | 2492 | String value = attribute.getValue();
212 | 2492 | domElement.setAttributeNS(attUri, attName, value);
213 |  | }
214 |  |
215 |  | // add content
216 | 4823 | appendDOMTree(domDocument, domElement, element.content());
217 |  |
218 | 4823 | domCurrent.appendChild(domElement);
219 |  |
220 | 4823 | while (namespaceStack.size() > stackSize) {
221 | 33 | namespaceStack.pop();
222 |  | }
223 |  | }
224 |  |
225 | 30 | protected void appendDOMTree(org.w3c.dom.Document domDocument,
226 |  | org.w3c.dom.Node domCurrent, CDATA cdata) {
227 | 30 | org.w3c.dom.CDATASection domCDATA = domDocument
228 |  | .createCDATASection(cdata.getText());
229 | 30 | domCurrent.appendChild(domCDATA);
230 |  | }
231 |  |
232 | 68 | protected void appendDOMTree(org.w3c.dom.Document domDocument,
233 |  | org.w3c.dom.Node domCurrent, Comment comment) {
234 | 68 | org.w3c.dom.Comment domComment = domDocument.createComment(comment
235 |  | .getText());
236 | 68 | domCurrent.appendChild(domComment);
237 |  | }
238 |  |
239 | 8293 | protected void appendDOMTree(org.w3c.dom.Document domDocument,
240 |  | org.w3c.dom.Node domCurrent, String text) {
241 | 8293 | org.w3c.dom.Text domText = domDocument.createTextNode(text);
242 | 8293 | domCurrent.appendChild(domText);
243 |  | }
244 |  |
245 | 0 | protected void appendDOMTree(org.w3c.dom.Document domDocument,
246 |  | org.w3c.dom.Node domCurrent, Entity entity) {
247 | 0 | org.w3c.dom.EntityReference domEntity = domDocument
248 |  | .createEntityReference(entity.getName());
249 | 0 | domCurrent.appendChild(domEntity);
250 |  | }
251 |  |
252 | 2 | protected void appendDOMTree(org.w3c.dom.Document domDoc,
253 |  | org.w3c.dom.Node domCurrent, ProcessingInstruction pi) {
254 | 2 | org.w3c.dom.ProcessingInstruction domPI = domDoc
255 |  | .createProcessingInstruction(pi.getTarget(), pi.getText());
256 | 2 | domCurrent.appendChild(domPI);
257 |  | }
258 |  |
259 | 33 | protected void writeNamespace(org.w3c.dom.Element domElement,
260 |  | Namespace namespace) {
261 | 33 | String attributeName = attributeNameForNamespace(namespace);
262 |  |
263 |  | // domElement.setAttributeNS("", attributeName, namespace.getURI());
264 | 33 | domElement.setAttribute(attributeName, namespace.getURI());
265 |  | }
266 |  |
267 | 33 | protected String attributeNameForNamespace(Namespace namespace) {
268 | 33 | String xmlns = "xmlns";
269 | 33 | String prefix = namespace.getPrefix();
270 |  |
271 | 33 | if (prefix.length() > 0) {
272 | 22 | return xmlns + ":" + prefix;
273 |  | }
274 |  |
275 | 11 | return xmlns;
276 |  | }
277 |  |
278 | 15 | protected org.w3c.dom.Document createDomDocument(Document document)
279 |  | throws DocumentException {
280 | 15 | org.w3c.dom.Document result = null;
281 |  |
282 |  | // use the given domDocumentClass (if not null)
283 | 15 | if (domDocumentClass != null) {
284 | 2 | try {
285 | 2 | result = (org.w3c.dom.Document) domDocumentClass.newInstance();
286 |  | } catch (Exception e) {
287 | 0 | 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 | 13 | result = createDomDocumentViaJAXP();
295 |  |
296 | 13 | if (result == null) {
297 | 0 | Class theClass = getDomDocumentClass();
298 |  |
299 | 0 | try {
300 | 0 | result = (org.w3c.dom.Document) theClass.newInstance();
301 |  | } catch (Exception e) {
302 | 0 | throw new DocumentException("Could not instantiate an "
303 |  | + "instance of DOM Document " + "with class: "
304 |  | + theClass.getName(), e);
305 |  | }
306 |  | }
307 |  | }
308 |  |
309 | 15 | return result;
310 |  | }
311 |  |
312 | 13 | protected org.w3c.dom.Document createDomDocumentViaJAXP()
313 |  | throws DocumentException {
314 | 13 | try {
315 | 13 | return JAXPHelper.createDocument(false, true);
316 |  | } catch (Throwable e) {
317 | 0 | if (!loggedWarning) {
318 | 0 | loggedWarning = true;
319 |  |
320 | 0 | if (SAXHelper.isVerboseErrorReporting()) {
321 |  | // log all exceptions as warnings and carry
322 |  | // on as we have a default SAX parser we can use
323 | 0 | System.out.println("Warning: Caught exception attempting "
324 |  | + "to use JAXP to create a W3C DOM " + "document");
325 | 0 | System.out.println("Warning: Exception was: " + e);
326 | 0 | e.printStackTrace();
327 |  | } else {
328 | 0 | System.out.println("Warning: Error occurred using JAXP to "
329 |  | + "create a DOM document.");
330 |  | }
331 |  | }
332 |  | }
333 |  |
334 | 0 | return null;
335 |  | }
336 |  |
337 | 0 | protected org.w3c.dom.Document createDomDocument(Document document,
338 |  | DOMImplementation domImpl) throws DocumentException {
339 | 0 | String namespaceURI = null;
340 | 0 | String qualifiedName = null;
341 | 0 | org.w3c.dom.DocumentType docType = null;
342 |  |
343 | 0 | return domImpl.createDocument(namespaceURI, qualifiedName, docType);
344 |  | }
345 |  |
346 | 4856 | protected boolean isNamespaceDeclaration(Namespace ns) {
347 | 4856 | if ((ns != null) && (ns != Namespace.NO_NAMESPACE)
348 |  | && (ns != Namespace.XML_NAMESPACE)) {
349 | 172 | String uri = ns.getURI();
350 |  |
351 | 172 | if ((uri != null) && (uri.length() > 0)) {
352 | 172 | if (!namespaceStack.contains(ns)) {
353 | 33 | return true;
354 |  | }
355 |  | }
356 |  | }
357 |  |
358 | 4823 | return false;
359 |  | }
360 |  |
361 | 15 | protected void resetNamespaceStack() {
362 | 15 | namespaceStack.clear();
363 | 15 | 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 |  | */