KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jdom > output > DOMOutputter


1 /*--
2
3  $Id: DOMOutputter.java,v 1.41 2004/09/03 06:03:42 jhunter Exp $
4
5  Copyright (C) 2000-2004 Jason Hunter & Brett McLaughlin.
6  All rights reserved.
7  
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions
10  are met:
11  
12  1. Redistributions of source code must retain the above copyright
13     notice, this list of conditions, and the following disclaimer.
14  
15  2. Redistributions in binary form must reproduce the above copyright
16     notice, this list of conditions, and the disclaimer that follows
17     these conditions in the documentation and/or other materials
18     provided with the distribution.
19
20  3. The name "JDOM" must not be used to endorse or promote products
21     derived from this software without prior written permission. For
22     written permission, please contact <request_AT_jdom_DOT_org>.
23  
24  4. Products derived from this software may not be called "JDOM", nor
25     may "JDOM" appear in their name, without prior written permission
26     from the JDOM Project Management <request_AT_jdom_DOT_org>.
27  
28  In addition, we request (but do not require) that you include in the
29  end-user documentation provided with the redistribution and/or in the
30  software itself an acknowledgement equivalent to the following:
31      "This product includes software developed by the
32       JDOM Project (http://www.jdom.org/)."
33  Alternatively, the acknowledgment may be graphical using the logos
34  available at http://www.jdom.org/images/logos.
35
36  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
40  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  SUCH DAMAGE.
48
49  This software consists of voluntary contributions made by many
50  individuals on behalf of the JDOM Project and was originally
51  created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
52  Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information
53  on the JDOM Project, please see <http://www.jdom.org/>.
54  
55  */

56
57
58 package org.jdom.output;
59
60 import java.util.*;
61
62 import org.jdom.*;
63 import org.jdom.adapters.*;
64
65
66 /**
67  * Outputs a JDOM {@link org.jdom.Document org.jdom.Document} as a DOM {@link
68  * org.w3c.dom.Document org.w3c.dom.Document}.
69  *
70  * @version $Revision: 1.41 $, $Date: 2004/09/03 06:03:42 $
71  * @author Brett McLaughlin
72  * @author Jason Hunter
73  * @author Matthew Merlo
74  * @author Dan Schaffer
75  * @author Yusuf Goolamabbas
76  * @author Bradley S. Huffman
77  */

78 public class DOMOutputter {
79
80     private static final String JavaDoc CVS_ID =
81       "@(#) $RCSfile: DOMOutputter.java,v $ $Revision: 1.41 $ $Date: 2004/09/03 06:03:42 $ $Name: $";
82
83     /** Default adapter class */
84     private static final String JavaDoc DEFAULT_ADAPTER_CLASS =
85         "org.jdom.adapters.XercesDOMAdapter";
86
87     /** Adapter to use for interfacing with the DOM implementation */
88     private String JavaDoc adapterClass;
89
90     /**
91      * This creates a new DOMOutputter which will attempt to first locate
92      * a DOM implementation to use via JAXP, and if JAXP does not exist or
93      * there's a problem, will fall back to the default parser.
94      */

95     public DOMOutputter() {
96         // nothing
97
}
98
99     /**
100      * This creates a new DOMOutputter using the specified DOMAdapter
101      * implementation as a way to choose the underlying parser.
102      *
103      * @param adapterClass <code>String</code> name of class
104      * to use for DOM output
105      */

106     public DOMOutputter(String JavaDoc adapterClass) {
107         this.adapterClass = adapterClass;
108     }
109
110
111     /**
112      * This converts the JDOM <code>Document</code> parameter to a
113      * DOM Document, returning the DOM version. The DOM implementation
114      * is the one chosen in the constructor.
115      *
116      * @param document <code>Document</code> to output.
117      * @return an <code>org.w3c.dom.Document</code> version
118      */

119     public org.w3c.dom.Document JavaDoc output(Document document)
120                                        throws JDOMException {
121         NamespaceStack namespaces = new NamespaceStack();
122
123         org.w3c.dom.Document JavaDoc domDoc = null;
124         try {
125             // Assign DOCTYPE during construction
126
DocType dt = document.getDocType();
127             domDoc = createDOMDocument(dt);
128
129             // Add content
130
Iterator itr = document.getContent().iterator();
131             while (itr.hasNext()) {
132                 Object JavaDoc node = itr.next();
133
134                 if (node instanceof Element) {
135                     Element element = (Element) node;
136                     org.w3c.dom.Element JavaDoc domElement =
137                         output(element, domDoc, namespaces);
138                         // Add the root element, first check for existing root
139
org.w3c.dom.Element JavaDoc root = domDoc.getDocumentElement();
140                         if (root == null) {
141                             // Normal case
142
domDoc.appendChild(domElement); // normal case
143
}
144                         else {
145                             // Xerces 1.3 creates new docs with a <root />
146
// XXX: Need to address DOCTYPE mismatch still
147
domDoc.replaceChild(domElement, root);
148                         }
149                 }
150                 else if (node instanceof Comment) {
151                     Comment comment = (Comment) node;
152                     org.w3c.dom.Comment JavaDoc domComment =
153                         domDoc.createComment(comment.getText());
154                     domDoc.appendChild(domComment);
155                 }
156                 else if (node instanceof ProcessingInstruction) {
157                     ProcessingInstruction pi =
158                         (ProcessingInstruction) node;
159                     org.w3c.dom.ProcessingInstruction JavaDoc domPI =
160                          domDoc.createProcessingInstruction(
161                          pi.getTarget(), pi.getData());
162                     domDoc.appendChild(domPI);
163                 }
164                 else if (node instanceof DocType) {
165                     // We already dealt with the DocType above
166
}
167                 else {
168                     throw new JDOMException(
169                         "Document contained top-level content with type:" +
170                         node.getClass().getName());
171                 }
172             }
173         }
174         catch (Throwable JavaDoc e) {
175             throw new JDOMException("Exception outputting Document", e);
176         }
177
178         return domDoc;
179     }
180
181     private org.w3c.dom.Document JavaDoc createDOMDocument(DocType dt)
182                                        throws JDOMException {
183         if (adapterClass != null) {
184             // The user knows that they want to use a particular impl
185
try {
186                 DOMAdapter adapter =
187                     (DOMAdapter)Class.forName(adapterClass).newInstance();
188                 // System.out.println("using specific " + adapterClass);
189
return adapter.createDocument(dt);
190             }
191             catch (ClassNotFoundException JavaDoc e) {
192                 // e.printStackTrace();
193
}
194             catch (IllegalAccessException JavaDoc e) {
195                 // e.printStackTrace();
196
}
197             catch (InstantiationException JavaDoc e) {
198                 // e.printStackTrace();
199
}
200         }
201         else {
202             // Try using JAXP...
203
try {
204                 DOMAdapter adapter =
205                     (DOMAdapter)Class.forName(
206                     "org.jdom.adapters.JAXPDOMAdapter").newInstance();
207                 // System.out.println("using JAXP");
208
return adapter.createDocument(dt);
209             }
210             catch (ClassNotFoundException JavaDoc e) {
211                 // e.printStackTrace();
212
}
213             catch (IllegalAccessException JavaDoc e) {
214                 // e.printStackTrace();
215
}
216             catch (InstantiationException JavaDoc e) {
217                 // e.printStackTrace();
218
}
219         }
220
221         // If no DOM doc yet, try to use a hard coded default
222
try {
223             DOMAdapter adapter = (DOMAdapter)
224                 Class.forName(DEFAULT_ADAPTER_CLASS).newInstance();
225             return adapter.createDocument(dt);
226             // System.out.println("Using default " +
227
// DEFAULT_ADAPTER_CLASS);
228
}
229         catch (ClassNotFoundException JavaDoc e) {
230             // e.printStackTrace();
231
}
232         catch (IllegalAccessException JavaDoc e) {
233             // e.printStackTrace();
234
}
235         catch (InstantiationException JavaDoc e) {
236             // e.printStackTrace();
237
}
238
239         throw new JDOMException("No JAXP or default parser available");
240         
241     }
242
243     private org.w3c.dom.Element JavaDoc output(Element element,
244                                          org.w3c.dom.Document JavaDoc domDoc,
245                                          NamespaceStack namespaces)
246                                          throws JDOMException {
247         try {
248             int previouslyDeclaredNamespaces = namespaces.size();
249
250             org.w3c.dom.Element JavaDoc domElement = null;
251             if (element.getNamespace() == Namespace.NO_NAMESPACE) {
252                 // No namespace, use createElement
253
domElement = domDoc.createElement(element.getQualifiedName());
254             }
255             else {
256                 domElement = domDoc.createElementNS(
257                                           element.getNamespaceURI(),
258                                           element.getQualifiedName());
259             }
260
261             // Add namespace attributes, beginning with the element's own
262
// Do this only if it's not the XML namespace and it's
263
// not the NO_NAMESPACE with the prefix "" not yet mapped
264
// (we do output xmlns="" if the "" prefix was already used
265
// and we need to reclaim it for the NO_NAMESPACE)
266
Namespace ns = element.getNamespace();
267             if (ns != Namespace.XML_NAMESPACE &&
268                            !(ns == Namespace.NO_NAMESPACE &&
269                              namespaces.getURI("") == null)) {
270                 String JavaDoc prefix = ns.getPrefix();
271                 String JavaDoc uri = namespaces.getURI(prefix);
272                 if (!ns.getURI().equals(uri)) { // output a new namespace decl
273
namespaces.push(ns);
274                     String JavaDoc attrName = getXmlnsTagFor(ns);
275                     domElement.setAttribute(attrName, ns.getURI());
276                 }
277             }
278
279             // Add additional namespaces also
280
Iterator itr = element.getAdditionalNamespaces().iterator();
281             while (itr.hasNext()) {
282                 Namespace additional = (Namespace)itr.next();
283                 String JavaDoc prefix = additional.getPrefix();
284                 String JavaDoc uri = namespaces.getURI(prefix);
285                 if (!additional.getURI().equals(uri)) {
286                     String JavaDoc attrName = getXmlnsTagFor(additional);
287                     domElement.setAttribute(attrName, additional.getURI());
288                     namespaces.push(additional);
289                 }
290             }
291
292             // Add attributes to the DOM element
293
itr = element.getAttributes().iterator();
294             while (itr.hasNext()) {
295                 Attribute attribute = (Attribute) itr.next();
296                 domElement.setAttributeNode(output(attribute, domDoc));
297                 Namespace ns1 = attribute.getNamespace();
298                 if ((ns1 != Namespace.NO_NAMESPACE) &&
299                     (ns1 != Namespace.XML_NAMESPACE)) {
300                     String JavaDoc prefix = ns1.getPrefix();
301                     String JavaDoc uri = namespaces.getURI(prefix);
302                     if (!ns1.getURI().equals(uri)) { // output a new decl
303
String JavaDoc attrName = getXmlnsTagFor(ns1);
304                         domElement.setAttribute(attrName, ns1.getURI());
305                         namespaces.push(ns1);
306                     }
307                 }
308                 // Crimson doesn't like setAttributeNS() for non-NS attribs
309
if (attribute.getNamespace() == Namespace.NO_NAMESPACE) {
310                     // No namespace, use setAttribute
311
domElement.setAttribute(attribute.getQualifiedName(),
312                                             attribute.getValue());
313                 }
314                 else {
315                     domElement.setAttributeNS(attribute.getNamespaceURI(),
316                                               attribute.getQualifiedName(),
317                                               attribute.getValue());
318                 }
319             }
320
321             // Add content to the DOM element
322
itr = element.getContent().iterator();
323             while (itr.hasNext()) {
324                 Object JavaDoc node = itr.next();
325
326                 if (node instanceof Element) {
327                     Element e = (Element) node;
328                     org.w3c.dom.Element JavaDoc domElt = output(e, domDoc, namespaces);
329                     domElement.appendChild(domElt);
330                 }
331                 else if (node instanceof String JavaDoc) {
332                     String JavaDoc str = (String JavaDoc) node;
333                     org.w3c.dom.Text JavaDoc domText = domDoc.createTextNode(str);
334                     domElement.appendChild(domText);
335                 }
336                 else if (node instanceof CDATA) {
337                     CDATA cdata = (CDATA) node;
338                     org.w3c.dom.CDATASection JavaDoc domCdata =
339                         domDoc.createCDATASection(cdata.getText());
340                     domElement.appendChild(domCdata);
341                 }
342                 else if (node instanceof Text) {
343                     Text text = (Text) node;
344                     org.w3c.dom.Text JavaDoc domText =
345                         domDoc.createTextNode(text.getText());
346                     domElement.appendChild(domText);
347                 }
348                 else if (node instanceof Comment) {
349                     Comment comment = (Comment) node;
350                     org.w3c.dom.Comment JavaDoc domComment =
351                         domDoc.createComment(comment.getText());
352                     domElement.appendChild(domComment);
353                 }
354                 else if (node instanceof ProcessingInstruction) {
355                     ProcessingInstruction pi =
356                         (ProcessingInstruction) node;
357                     org.w3c.dom.ProcessingInstruction JavaDoc domPI =
358                          domDoc.createProcessingInstruction(
359                          pi.getTarget(), pi.getData());
360                     domElement.appendChild(domPI);
361                 }
362                 else if (node instanceof EntityRef) {
363                     EntityRef entity = (EntityRef) node;
364                     org.w3c.dom.EntityReference JavaDoc domEntity =
365                         domDoc.createEntityReference(entity.getName());
366                     domElement.appendChild(domEntity);
367                 }
368                 else {
369                     throw new JDOMException(
370                         "Element contained content with type:" +
371                         node.getClass().getName());
372                 }
373             }
374     
375             // Remove declared namespaces from stack
376
while (namespaces.size() > previouslyDeclaredNamespaces) {
377                 namespaces.pop();
378             }
379
380             return domElement;
381         }
382         catch (Exception JavaDoc e) {
383             throw new JDOMException("Exception outputting Element " +
384                                     element.getQualifiedName(), e);
385         }
386     }
387
388     private org.w3c.dom.Attr JavaDoc output(Attribute attribute,
389                                       org.w3c.dom.Document JavaDoc domDoc)
390                                       throws JDOMException {
391          org.w3c.dom.Attr JavaDoc domAttr = null;
392          try {
393              if (attribute.getNamespace() == Namespace.NO_NAMESPACE) {
394                  // No namespace, use createAttribute
395
domAttr = domDoc.createAttribute(attribute.getQualifiedName());
396              }
397              else {
398                  domAttr = domDoc.createAttributeNS(attribute.getNamespaceURI(),
399                                                   attribute.getQualifiedName());
400              }
401              domAttr.setValue(attribute.getValue());
402          } catch (Exception JavaDoc e) {
403              throw new JDOMException("Exception outputting Attribute " +
404                                      attribute.getQualifiedName(), e);
405          }
406          return domAttr;
407     }
408
409     /**
410      * This will handle adding any <code>{@link Namespace}</code>
411      * attributes to the DOM tree.
412      *
413      * @param ns <code>Namespace</code> to add definition of
414      */

415     private static String JavaDoc getXmlnsTagFor(Namespace ns) {
416         String JavaDoc attrName = "xmlns";
417         if (!ns.getPrefix().equals("")) {
418             attrName += ":";
419             attrName += ns.getPrefix();
420         }
421         return attrName;
422     }
423 }
424
Popular Tags