1
2
3
4
5
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 public DOMReader() {
38 this.factory = DocumentFactory.getInstance();
39 this.namespaceStack = new NamespaceStack(factory);
40 }
41
42 public DOMReader(DocumentFactory factory) {
43 this.factory = factory;
44 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 public DocumentFactory getDocumentFactory() {
54 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 public void setDocumentFactory(DocumentFactory docFactory) {
69 this.factory = docFactory;
70 this.namespaceStack.setDocumentFactory(factory);
71 }
72
73 public Document read(org.w3c.dom.Document domDocument) {
74 if (domDocument instanceof Document) {
75 return (Document) domDocument;
76 }
77
78 Document document = createDocument();
79
80 clearNamespaceStack();
81
82 org.w3c.dom.NodeList nodeList = domDocument.getChildNodes();
83
84 for (int i = 0, size = nodeList.getLength(); i < size; i++) {
85 readTree(nodeList.item(i), document);
86 }
87
88 return document;
89 }
90
91
92 protected void readTree(org.w3c.dom.Node node, Branch current) {
93 Element element = null;
94 Document document = null;
95
96 if (current instanceof Element) {
97 element = (Element) current;
98 } else {
99 document = (Document) current;
100 }
101
102 switch (node.getNodeType()) {
103 case org.w3c.dom.Node.ELEMENT_NODE:
104 readElement(node, current);
105
106 break;
107
108 case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE:
109
110 if (current instanceof Element) {
111 Element currentEl = (Element) current;
112 currentEl.addProcessingInstruction(node.getNodeName(), node
113 .getNodeValue());
114 } else {
115 Document currentDoc = (Document) current;
116 currentDoc.addProcessingInstruction(node.getNodeName(),
117 node.getNodeValue());
118 }
119
120 break;
121
122 case org.w3c.dom.Node.COMMENT_NODE:
123
124 if (current instanceof Element) {
125 ((Element) current).addComment(node.getNodeValue());
126 } else {
127 ((Document) current).addComment(node.getNodeValue());
128 }
129
130 break;
131
132 case org.w3c.dom.Node.DOCUMENT_TYPE_NODE:
133
134 org.w3c.dom.DocumentType domDocType
135 = (org.w3c.dom.DocumentType) node;
136 document.addDocType(domDocType.getName(), domDocType
137 .getPublicId(), domDocType.getSystemId());
138
139 break;
140
141 case org.w3c.dom.Node.TEXT_NODE:
142 element.addText(node.getNodeValue());
143
144 break;
145
146 case org.w3c.dom.Node.CDATA_SECTION_NODE:
147 element.addCDATA(node.getNodeValue());
148
149 break;
150
151 case org.w3c.dom.Node.ENTITY_REFERENCE_NODE:
152
153
154 org.w3c.dom.Node firstChild = node.getFirstChild();
155
156 if (firstChild != null) {
157 element.addEntity(node.getNodeName(), firstChild
158 .getNodeValue());
159 } else {
160 element.addEntity(node.getNodeName(), "");
161 }
162
163 break;
164
165 case org.w3c.dom.Node.ENTITY_NODE:
166 element.addEntity(node.getNodeName(), node.getNodeValue());
167
168 break;
169
170 default:
171 System.out.println("WARNING: Unknown DOM node type: "
172 + node.getNodeType());
173 }
174 }
175
176 protected void readElement(org.w3c.dom.Node node, Branch current) {
177 int previouslyDeclaredNamespaces = namespaceStack.size();
178
179 String namespaceUri = node.getNamespaceURI();
180 String elementPrefix = node.getPrefix();
181
182 if (elementPrefix == null) {
183 elementPrefix = "";
184 }
185
186 org.w3c.dom.NamedNodeMap attributeList = node.getAttributes();
187
188 if ((attributeList != null) && (namespaceUri == null)) {
189
190 org.w3c.dom.Node attribute = attributeList.getNamedItem("xmlns");
191
192 if (attribute != null) {
193 namespaceUri = attribute.getNodeValue();
194 elementPrefix = "";
195 }
196 }
197
198 QName qName = namespaceStack.getQName(namespaceUri,
199 node.getLocalName(), node.getNodeName());
200 Element element = current.addElement(qName);
201
202 if (attributeList != null) {
203 int size = attributeList.getLength();
204 List attributes = new ArrayList(size);
205
206 for (int i = 0; i < size; i++) {
207 org.w3c.dom.Node attribute = attributeList.item(i);
208
209
210 String name = attribute.getNodeName();
211
212 if (name.startsWith("xmlns")) {
213 String prefix = getPrefix(name);
214 String uri = attribute.getNodeValue();
215
216 Namespace namespace = namespaceStack.addNamespace(prefix,
217 uri);
218 element.add(namespace);
219 } else {
220 attributes.add(attribute);
221 }
222 }
223
224
225 size = attributes.size();
226
227 for (int i = 0; i < size; i++) {
228 org.w3c.dom.Node attribute = (org.w3c.dom.Node) attributes
229 .get(i);
230 QName attributeQName = namespaceStack.getQName(attribute
231 .getNamespaceURI(), attribute.getLocalName(), attribute
232 .getNodeName());
233 element.addAttribute(attributeQName, attribute.getNodeValue());
234 }
235 }
236
237
238 org.w3c.dom.NodeList children = node.getChildNodes();
239
240 for (int i = 0, size = children.getLength(); i < size; i++) {
241 org.w3c.dom.Node child = children.item(i);
242 readTree(child, element);
243 }
244
245
246 while (namespaceStack.size() > previouslyDeclaredNamespaces) {
247 namespaceStack.pop();
248 }
249 }
250
251 protected Namespace getNamespace(String prefix, String uri) {
252 return getDocumentFactory().createNamespace(prefix, uri);
253 }
254
255 protected Document createDocument() {
256 return getDocumentFactory().createDocument();
257 }
258
259 protected void clearNamespaceStack() {
260 namespaceStack.clear();
261
262 if (!namespaceStack.contains(Namespace.XML_NAMESPACE)) {
263 namespaceStack.push(Namespace.XML_NAMESPACE);
264 }
265 }
266
267 private String getPrefix(String xmlnsDecl) {
268 int index = xmlnsDecl.indexOf(':', 5);
269
270 if (index != -1) {
271 return xmlnsDecl.substring(index + 1);
272 } else {
273 return "";
274 }
275 }
276 }
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313