Clover coverage report - dom4j - 1.6.1
Coverage timestamp: ma mei 16 2005 14:23:01 GMT+01:00

file stats: | LOC: | 313 |  | Methods: | 11
| NCLOC: | 173 |  | Classes: | 1

Source file | Conditionals | Statements | Methods | TOTAL

DOMReader.java

82,4%

77,5%

72,7%

78,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.ArrayList;
11 |  | import java.util.List;
12 |  |
13 |  | import org.dom4j.Branch;
14 |  | import org.dom4j.Document;
15 |  | import org.dom4j.DocumentFactory;
16 |  | import org.dom4j.Element;
17 |  | import org.dom4j.Namespace;
18 |  | import org.dom4j.QName;
19 |  | import org.dom4j.tree.NamespaceStack;
20 |  |
21 |  | /**
22 |  | * <p>
23 |  | * <code>DOMReader</code> navigates a W3C DOM tree and creates a DOM4J tree
24 |  | * from it.
25 |  | * </p>
26 |  | *
27 |  | * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
28 |  | * @version $Revision: 1.17 $
29 |  | */
30 |  | public class DOMReader {
31 |  | /** <code>DocumentFactory</code> used to create new document objects */
32 |  | private DocumentFactory factory;
33 |  |
34 |  | /** stack of <code>Namespace</code> and <code>QName</code> objects */
35 |  | private NamespaceStack namespaceStack;
36 |  |
37 | 20 | public DOMReader() {
38 | 20 | this.factory = DocumentFactory.getInstance();
39 | 20 | this.namespaceStack = new NamespaceStack(factory);
40 |  | }
41 |  |
42 | 0 | public DOMReader(DocumentFactory factory) {
43 | 0 | this.factory = factory;
44 | 0 | this.namespaceStack = new NamespaceStack(factory);
45 |  | }
46 |  |
47 |  | /**
48 |  | * DOCUMENT ME!
49 |  | *
50 |  | * @return the <code>DocumentFactory</code> used to create document
51 |  | * objects
52 |  | */
53 | 20 | public DocumentFactory getDocumentFactory() {
54 | 20 | return factory;
55 |  | }
56 |  |
57 |  | /**
58 |  | * <p>
59 |  | * This sets the <code>DocumentFactory</code> used to create new
60 |  | * documents. This method allows the building of custom DOM4J tree objects
61 |  | * to be implemented easily using a custom derivation of
62 |  | * {@link DocumentFactory}
63 |  | * </p>
64 |  | *
65 |  | * @param docFactory
66 |  | * <code>DocumentFactory</code> used to create DOM4J objects
67 |  | */
68 | 0 | public void setDocumentFactory(DocumentFactory docFactory) {
69 | 0 | this.factory = docFactory;
70 | 0 | this.namespaceStack.setDocumentFactory(factory);
71 |  | }
72 |  |
73 | 20 | public Document read(org.w3c.dom.Document domDocument) {
74 | 20 | if (domDocument instanceof Document) {
75 | 0 | return (Document) domDocument;
76 |  | }
77 |  |
78 | 20 | Document document = createDocument();
79 |  |
80 | 20 | clearNamespaceStack();
81 |  |
82 | 20 | org.w3c.dom.NodeList nodeList = domDocument.getChildNodes();
83 |  |
84 | 20 | for (int i = 0, size = nodeList.getLength(); i < size; i++) {
85 | 26 | readTree(nodeList.item(i), document);
86 |  | }
87 |  |
88 | 20 | return document;
89 |  | }
90 |  |
91 |  | // Implementation methods
92 | 14094 | protected void readTree(org.w3c.dom.Node node, Branch current) {
93 | 14094 | Element element = null;
94 | 14094 | Document document = null;
95 |  |
96 | 14094 | if (current instanceof Element) {
97 | 14068 | element = (Element) current;
98 |  | } else {
99 | 26 | document = (Document) current;
100 |  | }
101 |  |
102 | 14094 | switch (node.getNodeType()) {
103 | 5119 | case org.w3c.dom.Node.ELEMENT_NODE:
104 | 5119 | readElement(node, current);
105 |  |
106 | 5119 | break;
107 |  |
108 | 2 | case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE:
109 |  |
110 | 2 | if (current instanceof Element) {
111 | 0 | Element currentEl = (Element) current;
112 | 0 | currentEl.addProcessingInstruction(node.getNodeName(), node
113 |  | .getNodeValue());
114 |  | } else {
115 | 2 | Document currentDoc = (Document) current;
116 | 2 | currentDoc.addProcessingInstruction(node.getNodeName(),
117 |  | node.getNodeValue());
118 |  | }
119 |  |
120 | 2 | break;
121 |  |
122 | 70 | case org.w3c.dom.Node.COMMENT_NODE:
123 |  |
124 | 70 | if (current instanceof Element) {
125 | 66 | ((Element) current).addComment(node.getNodeValue());
126 |  | } else {
127 | 4 | ((Document) current).addComment(node.getNodeValue());
128 |  | }
129 |  |
130 | 70 | break;
131 |  |
132 | 0 | case org.w3c.dom.Node.DOCUMENT_TYPE_NODE:
133 |  |
134 | 0 | org.w3c.dom.DocumentType domDocType
135 |  | = (org.w3c.dom.DocumentType) node;
136 | 0 | document.addDocType(domDocType.getName(), domDocType
137 |  | .getPublicId(), domDocType.getSystemId());
138 |  |
139 | 0 | break;
140 |  |
141 | 8873 | case org.w3c.dom.Node.TEXT_NODE:
142 | 8873 | element.addText(node.getNodeValue());
143 |  |
144 | 8873 | break;
145 |  |
146 | 30 | case org.w3c.dom.Node.CDATA_SECTION_NODE:
147 | 30 | element.addCDATA(node.getNodeValue());
148 |  |
149 | 30 | break;
150 |  |
151 | 0 | case org.w3c.dom.Node.ENTITY_REFERENCE_NODE:
152 |  |
153 |  | // is there a better way to get the value of an entity?
154 | 0 | org.w3c.dom.Node firstChild = node.getFirstChild();
155 |  |
156 | 0 | if (firstChild != null) {
157 | 0 | element.addEntity(node.getNodeName(), firstChild
158 |  | .getNodeValue());
159 |  | } else {
160 | 0 | element.addEntity(node.getNodeName(), "");
161 |  | }
162 |  |
163 | 0 | break;
164 |  |
165 | 0 | case org.w3c.dom.Node.ENTITY_NODE:
166 | 0 | element.addEntity(node.getNodeName(), node.getNodeValue());
167 |  |
168 | 0 | break;
169 |  |
170 | 0 | default:
171 | 0 | System.out.println("WARNING: Unknown DOM node type: "
172 |  | + node.getNodeType());
173 |  | }
174 |  | }
175 |  |
176 | 5119 | protected void readElement(org.w3c.dom.Node node, Branch current) {
177 | 5119 | int previouslyDeclaredNamespaces = namespaceStack.size();
178 |  |
179 | 5119 | String namespaceUri = node.getNamespaceURI();
180 | 5119 | String elementPrefix = node.getPrefix();
181 |  |
182 | 5119 | if (elementPrefix == null) {
183 | 4751 | elementPrefix = "";
184 |  | }
185 |  |
186 | 5119 | org.w3c.dom.NamedNodeMap attributeList = node.getAttributes();
187 |  |
188 | 5119 | if ((attributeList != null) && (namespaceUri == null)) {
189 |  | // test if we have an "xmlns" attribute
190 | 4686 | org.w3c.dom.Node attribute = attributeList.getNamedItem("xmlns");
191 |  |
192 | 4686 | if (attribute != null) {
193 | 2 | namespaceUri = attribute.getNodeValue();
194 | 2 | elementPrefix = "";
195 |  | }
196 |  | }
197 |  |
198 | 5119 | QName qName = namespaceStack.getQName(namespaceUri,
199 |  | node.getLocalName(), node.getNodeName());
200 | 5119 | Element element = current.addElement(qName);
201 |  |
202 | 5119 | if (attributeList != null) {
203 | 5119 | int size = attributeList.getLength();
204 | 5119 | List attributes = new ArrayList(size);
205 |  |
206 | 5119 | for (int i = 0; i < size; i++) {
207 | 2829 | org.w3c.dom.Node attribute = attributeList.item(i);
208 |  |
209 |  | // Define all namespaces first then process attributes later
210 | 2829 | String name = attribute.getNodeName();
211 |  |
212 | 2829 | if (name.startsWith("xmlns")) {
213 | 52 | String prefix = getPrefix(name);
214 | 52 | String uri = attribute.getNodeValue();
215 |  |
216 | 52 | Namespace namespace = namespaceStack.addNamespace(prefix,
217 |  | uri);
218 | 52 | element.add(namespace);
219 |  | } else {
220 | 2777 | attributes.add(attribute);
221 |  | }
222 |  | }
223 |  |
224 |  | // now add the attributes, the namespaces should be available
225 | 5119 | size = attributes.size();
226 |  |
227 | 5119 | for (int i = 0; i < size; i++) {
228 | 2777 | org.w3c.dom.Node attribute = (org.w3c.dom.Node) attributes
229 |  | .get(i);
230 | 2777 | QName attributeQName = namespaceStack.getQName(attribute
231 |  | .getNamespaceURI(), attribute.getLocalName(), attribute
232 |  | .getNodeName());
233 | 2777 | element.addAttribute(attributeQName, attribute.getNodeValue());
234 |  | }
235 |  | }
236 |  |
237 |  | // Recurse on child nodes
238 | 5119 | org.w3c.dom.NodeList children = node.getChildNodes();
239 |  |
240 | 5119 | for (int i = 0, size = children.getLength(); i < size; i++) {
241 | 14068 | org.w3c.dom.Node child = children.item(i);
242 | 14068 | readTree(child, element);
243 |  | }
244 |  |
245 |  | // pop namespaces from the stack
246 | 5119 | while (namespaceStack.size() > previouslyDeclaredNamespaces) {
247 | 52 | namespaceStack.pop();
248 |  | }
249 |  | }
250 |  |
251 | 0 | protected Namespace getNamespace(String prefix, String uri) {
252 | 0 | return getDocumentFactory().createNamespace(prefix, uri);
253 |  | }
254 |  |
255 | 20 | protected Document createDocument() {
256 | 20 | return getDocumentFactory().createDocument();
257 |  | }
258 |  |
259 | 20 | protected void clearNamespaceStack() {
260 | 20 | namespaceStack.clear();
261 |  |
262 | 20 | if (!namespaceStack.contains(Namespace.XML_NAMESPACE)) {
263 | 20 | namespaceStack.push(Namespace.XML_NAMESPACE);
264 |  | }
265 |  | }
266 |  |
267 | 52 | private String getPrefix(String xmlnsDecl) {
268 | 52 | int index = xmlnsDecl.indexOf(':', 5);
269 |  |
270 | 52 | if (index != -1) {
271 | 30 | return xmlnsDecl.substring(index + 1);
272 |  | } else {
273 | 22 | return "";
274 |  | }
275 |  | }
276 |  | }
277 |  |
278 |  | /*
279 |  | * Redistribution and use of this software and associated documentation
280 |  | * ("Software"), with or without modification, are permitted provided that the
281 |  | * following conditions are met:
282 |  | *
283 |  | * 1. Redistributions of source code must retain copyright statements and
284 |  | * notices. Redistributions must also contain a copy of this document.
285 |  | *
286 |  | * 2. Redistributions in binary form must reproduce the above copyright notice,
287 |  | * this list of conditions and the following disclaimer in the documentation
288 |  | * and/or other materials provided with the distribution.
289 |  | *
290 |  | * 3. The name "DOM4J" must not be used to endorse or promote products derived
291 |  | * from this Software without prior written permission of MetaStuff, Ltd. For
292 |  | * written permission, please contact dom4j-info@metastuff.com.
293 |  | *
294 |  | * 4. Products derived from this Software may not be called "DOM4J" nor may
295 |  | * "DOM4J" appear in their names without prior written permission of MetaStuff,
296 |  | * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
297 |  | *
298 |  | * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
299 |  | *
300 |  | * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
301 |  | * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
302 |  | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
303 |  | * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
304 |  | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
305 |  | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
306 |  | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
307 |  | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
308 |  | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
309 |  | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
310 |  | * POSSIBILITY OF SUCH DAMAGE.
311 |  | *
312 |  | * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
313 |  | */