Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/jdom/input/DOMBuilder.java


1   /*--
2   
3    $Id: DOMBuilder.java,v 1.59 2004/09/03 06:03:41 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  package org.jdom.input;
58  
59  import org.jdom.*;
60  import org.jdom.Document;
61  import org.jdom.Element;
62  import org.w3c.dom.*;
63  
64  /**
65   * Builds a JDOM {@link org.jdom.Document org.jdom.Document} from a pre-existing
66   * DOM {@link org.w3c.dom.Document org.w3c.dom.Document}. Also handy for testing
67   * builds from files to sanity check {@link SAXBuilder}.
68   *
69   * @version $Revision: 1.59 $, $Date: 2004/09/03 06:03:41 $
70   * @author  Brett McLaughlin
71   * @author  Jason Hunter
72   * @author  Philip Nelson
73   * @author  Kevin Regan
74   * @author  Yusuf Goolamabbas
75   * @author  Dan Schaffer
76   * @author  Bradley S. Huffman
77   */
78  public class DOMBuilder {
79  
80      private static final String CVS_ID =
81        "@(#) $RCSfile: DOMBuilder.java,v $ $Revision: 1.59 $ $Date: 2004/09/03 06:03:41 $ $Name: jdom_1_0 $";
82  
83      /** Adapter class to use */
84      private String adapterClass;
85  
86      /** The factory for creating new JDOM objects */
87      private JDOMFactory factory = new DefaultJDOMFactory();
88  
89      /**
90       * This creates a new DOMBuilder which will attempt to first locate
91       * a parser via JAXP, then will try to use a set of default parsers.
92       * The underlying parser will not validate.
93       */
94      public DOMBuilder() {
95      }
96  
97      /**
98       * This creates a new DOMBuilder using the specified DOMAdapter
99       * implementation as a way to choose the underlying parser.
100      * The underlying parser will not validate.
101      *
102      * @param adapterClass <code>String</code> name of class
103      *                     to use for DOM building.
104      */
105     public DOMBuilder(String adapterClass) {
106         this.adapterClass = adapterClass;
107     }
108 
109     /*
110      * This sets a custom JDOMFactory for the builder.  Use this to build
111      * the tree with your own subclasses of the JDOM classes.
112      *
113      * @param factory <code>JDOMFactory</code> to use
114      */
115     public void setFactory(JDOMFactory factory) {
116         this.factory = factory;
117     }
118 
119     /**
120      * Returns the current {@link org.jdom.JDOMFactory} in use.
121      * @return the factory in use
122      */
123     public JDOMFactory getFactory() {
124         return factory;
125     }
126 
127     /**
128      * This will build a JDOM tree from an existing DOM tree.
129      *
130      * @param domDocument <code>org.w3c.dom.Document</code> object
131      * @return <code>Document</code> - JDOM document object.
132      */
133     public Document build(org.w3c.dom.Document domDocument) {
134         Document doc = factory.document(null);
135         buildTree(domDocument, doc, null, true);
136         return doc;
137     }
138 
139     /**
140      * This will build a JDOM Element from an existing DOM Element
141      *
142      * @param domElement <code> org.w3c.dom.Element</code> object
143      * @return <code>Element</code> - JDOM Element object
144      */
145     public org.jdom.Element build(org.w3c.dom.Element domElement) {
146         Document doc = factory.document(null);
147         buildTree(domElement, doc, null, true);
148         return doc.getRootElement();
149     }
150 
151     /**
152      * This takes a DOM <code>Node</code> and builds up
153      * a JDOM tree, recursing until the DOM tree is exhausted
154      * and the JDOM tree results.
155      *
156      * @param node <code>Code</node> to examine.
157      * @param doc JDOM <code>Document</code> being built.
158      * @param current <code>Element</code> that is current parent.
159      * @param atRoot <code>boolean</code> indicating whether at root level.
160      */
161     private void buildTree(Node node,
162                            Document doc,
163                            Element current,
164                            boolean atRoot) {
165         // Recurse through the tree
166         switch (node.getNodeType()) {
167             case Node.DOCUMENT_NODE:
168                 NodeList nodes = node.getChildNodes();
169                 for (int i=0, size=nodes.getLength(); i<size; i++) {
170                     buildTree(nodes.item(i), doc, current, true);
171                 }
172                 break;
173 
174             case Node.ELEMENT_NODE:
175                 String nodeName = node.getNodeName();
176                 String prefix = "";
177                 String localName = nodeName;
178                 int colon = nodeName.indexOf(':');
179                 if (colon >= 0) {
180                     prefix = nodeName.substring(0, colon);
181                     localName = nodeName.substring(colon + 1);
182                 }
183 
184                 // Get element's namespace
185                 Namespace ns = null;
186                 String uri = node.getNamespaceURI();
187                 if (uri == null) {
188                     ns = (current == null) ? Namespace.NO_NAMESPACE
189                                            : current.getNamespace(prefix);
190                 }
191                 else {
192                     ns = Namespace.getNamespace(prefix, uri);
193                 }
194 
195                 Element element = factory.element(localName, ns);
196 
197                 if (atRoot) {
198                     // If at root, set as document root
199                     doc.setRootElement(element);  // XXX should we use a factory call?
200                 } else {
201                     // else add to parent element
202                     factory.addContent(current, element);
203                 }
204 
205                 // Add namespaces
206                 NamedNodeMap attributeList = node.getAttributes();
207                 int attsize = attributeList.getLength();
208 
209                 for (int i = 0; i < attsize; i++) {
210                     Attr att = (Attr) attributeList.item(i);
211 
212                     String attname = att.getName();
213                     if (attname.startsWith("xmlns")) {
214                         String attPrefix = "";
215                         colon = attname.indexOf(':');
216                         if (colon >= 0) {
217                             attPrefix = attname.substring(colon + 1);
218                         }
219 
220                         String attvalue = att.getValue();
221 
222                         Namespace declaredNS =
223                             Namespace.getNamespace(attPrefix, attvalue);
224 
225                         // Add as additional namespaces if it's different
226                         // than this element's namespace (perhaps we should
227                         // also have logic not to mark them as additional if
228                         // it's been done already, but it probably doesn't
229                         // matter)
230                         if (prefix.equals(attPrefix)) {
231                             element.setNamespace(declaredNS);
232                         }
233                         else {
234                             factory.addNamespaceDeclaration(element, declaredNS);
235                         }
236                     }
237                 }
238 
239                 // Add attributes
240                 for (int i = 0; i < attsize; i++) {
241                     Attr att = (Attr) attributeList.item(i);
242 
243                     String attname = att.getName();
244 
245                     if ( !attname.startsWith("xmlns")) {
246                         String attPrefix = "";
247                         String attLocalName = attname;
248                         colon = attname.indexOf(':');
249                         if (colon >= 0) {
250                             attPrefix = attname.substring(0, colon);
251                             attLocalName = attname.substring(colon + 1);
252                         }
253 
254                         String attvalue = att.getValue();
255 
256                         // Get attribute's namespace
257                         Namespace attns = null;
258                         if ("".equals(attPrefix)) {
259                             attns = Namespace.NO_NAMESPACE;
260                         }
261                         else {
262                             attns = element.getNamespace(attPrefix);
263                         }
264 
265                         Attribute attribute =
266                             factory.attribute(attLocalName, attvalue, attns);
267                         factory.setAttribute(element, attribute);
268                     }
269                 }
270 
271                 // Recurse on child nodes
272                 // The list should never be null nor should it ever contain
273                 // null nodes, but some DOM impls are broken
274                 NodeList children = node.getChildNodes();
275                 if (children != null) {
276                     int size = children.getLength();
277                     for (int i = 0; i < size; i++) {
278                         Node item = children.item(i);
279                         if (item != null) {
280                             buildTree(item, doc, element, false);
281                         }
282                     }
283                 }
284                 break;
285 
286             case Node.TEXT_NODE:
287                 String data = node.getNodeValue();
288                 factory.addContent(current, factory.text(data));
289                 break;
290 
291             case Node.CDATA_SECTION_NODE:
292                 String cdata = node.getNodeValue();
293                 factory.addContent(current, factory.cdata(cdata));
294                 break;
295 
296 
297             case Node.PROCESSING_INSTRUCTION_NODE:
298                 if (atRoot) {
299                     factory.addContent(doc,
300                         factory.processingInstruction(node.getNodeName(),
301                                                       node.getNodeValue()));
302                 } else {
303                     factory.addContent(current,
304                         factory.processingInstruction(node.getNodeName(),
305                                                       node.getNodeValue()));
306                 }
307                 break;
308 
309             case Node.COMMENT_NODE:
310                 if (atRoot) {
311                     factory.addContent(doc, factory.comment(node.getNodeValue()));
312                 } else {
313                     factory.addContent(current, factory.comment(node.getNodeValue()));
314                 }
315                 break;
316 
317             case Node.ENTITY_REFERENCE_NODE:
318                 EntityRef entity = factory.entityRef(node.getNodeName());
319                 factory.addContent(current, entity);
320                 break;
321 
322             case Node.ENTITY_NODE:
323                 // ??
324                 break;
325 
326             case Node.DOCUMENT_TYPE_NODE:
327                 DocumentType domDocType = (DocumentType)node;
328                 String publicID = domDocType.getPublicId();
329                 String systemID = domDocType.getSystemId();
330                 String internalDTD = domDocType.getInternalSubset();
331 
332                 DocType docType = factory.docType(domDocType.getName());
333                 docType.setPublicID(publicID);
334                 docType.setSystemID(systemID);
335                 docType.setInternalSubset(internalDTD);
336 
337                 factory.addContent(doc, docType);
338                 break;
339         }
340     }
341 }