KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > woody > util > DomHelper


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.woody.util;
17
18 import java.io.IOException JavaDoc;
19 import java.util.ArrayList JavaDoc;
20
21 import org.apache.cocoon.xml.SaxBuffer;
22 import org.apache.cocoon.xml.dom.DOMStreamer;
23 import org.apache.commons.lang.BooleanUtils;
24 import org.apache.excalibur.xml.sax.XMLizable;
25 import org.apache.xerces.dom.NodeImpl;
26 import org.apache.xerces.parsers.DOMParser;
27 import org.apache.xerces.xni.Augmentations;
28 import org.apache.xerces.xni.NamespaceContext;
29 import org.apache.xerces.xni.QName;
30 import org.apache.xerces.xni.XMLAttributes;
31 import org.apache.xerces.xni.XMLLocator;
32 import org.apache.xerces.xni.XNIException;
33 import org.w3c.dom.CDATASection JavaDoc;
34 import org.w3c.dom.Document JavaDoc;
35 import org.w3c.dom.Element JavaDoc;
36 import org.w3c.dom.Node JavaDoc;
37 import org.w3c.dom.NodeList JavaDoc;
38 import org.w3c.dom.Text JavaDoc;
39 import org.w3c.dom.UserDataHandler JavaDoc;
40 import org.xml.sax.InputSource JavaDoc;
41 import org.xml.sax.SAXException JavaDoc;
42 import org.xml.sax.SAXNotSupportedException JavaDoc;
43
44 /**
45  * Helper class to create and retrieve information from DOM-trees. It provides
46  * some functionality comparable to what's found in Avalon's Configuration
47  * objects. These lasts one could however not be used by Woody because they
48  * don't provide an accurate model of an XML file (no mixed content,
49  * no namespaced attributes, no namespace declarations, ...).
50  *
51  * <p>This class depends specifically on the Xerces DOM implementation to be
52  * able to provide information about the location of elements in their source
53  * XML file. See the {@link #getLocation(Element)} method.
54  *
55  * @version CVS $Id: DomHelper.java 201870 2005-06-26 15:34:51Z antonio $
56  */

57 public class DomHelper {
58
59     /**
60      * Retrieves the location of an element node in the source file from which
61      * the Document was created. This will only work for Document's created
62      * with the method {@link #parse(InputSource)} of this class.
63      */

64     public static String JavaDoc getLocation(Element JavaDoc element) {
65         String JavaDoc location = null;
66         if (element instanceof NodeImpl) {
67             location = (String JavaDoc)((NodeImpl)element).getUserData("location");
68         }
69
70         if (location != null) {
71             return location;
72         }
73         return "(location unknown)";
74     }
75     
76     public static String JavaDoc getSystemIdLocation(Element JavaDoc element) {
77         String JavaDoc loc = getLocation(element);
78         if (loc.charAt(0) != '(') {
79             int end = loc.lastIndexOf(':');
80             if (end > 0) {
81                 int start = loc.lastIndexOf(':', end - 1);
82                 if (start >= 0) {
83                     return loc.substring(0, start);
84                 }
85             }
86         }
87         return null;
88     }
89     
90     public static int getLineLocation(Element JavaDoc element) {
91         String JavaDoc loc = getLocation(element);
92         if (loc.charAt(0) != '(') {
93             int end = loc.lastIndexOf(':');
94             if (end > 0) {
95                 int start = loc.lastIndexOf(':', end - 1);
96                 if (start >= 0) {
97                     return Integer.parseInt(loc.substring(start + 1, end));
98                 }
99             }
100         }
101         return -1;
102     }
103
104     public static int getColumnLocation(Element JavaDoc element) {
105         String JavaDoc loc = getLocation(element);
106         if (loc.charAt(0) != '(') {
107             int end = loc.lastIndexOf(':');
108             if (end > 0) {
109                 return Integer.parseInt(loc.substring(end));
110             }
111         }
112         return -1;
113     }
114
115     /**
116      * Returns all Element children of an Element that belong to the given
117      * namespace.
118      */

119     public static Element JavaDoc[] getChildElements(Element JavaDoc element,
120             String JavaDoc namespace) {
121         ArrayList JavaDoc elements = new ArrayList JavaDoc();
122         NodeList JavaDoc nodeList = element.getChildNodes();
123         for (int i = 0; i < nodeList.getLength(); i++) {
124             Node JavaDoc node = nodeList.item(i);
125             if (node instanceof Element JavaDoc
126                     && namespace.equals(node.getNamespaceURI()))
127                 elements.add(node);
128         }
129         return (Element JavaDoc[])elements.toArray(new Element JavaDoc[0]);
130     }
131
132     /**
133      * Returns all Element children of an Element that belong to the given
134      * namespace and have the given local name.
135      */

136     public static Element JavaDoc[] getChildElements(Element JavaDoc element,
137             String JavaDoc namespace, String JavaDoc localName) {
138         ArrayList JavaDoc elements = new ArrayList JavaDoc();
139         NodeList JavaDoc nodeList = element.getChildNodes();
140         for (int i = 0; i < nodeList.getLength(); i++) {
141             Node JavaDoc node = nodeList.item(i);
142             if (node instanceof Element JavaDoc
143                     && namespace.equals(node.getNamespaceURI())
144                     && localName.equals(node.getLocalName())) {
145                 elements.add(node);
146             }
147         }
148         return (Element JavaDoc[])elements.toArray(new Element JavaDoc[0]);
149     }
150
151     /**
152      * Returns the first child element with the given namespace and localName,
153      * or null if there is no such element.
154      */

155     public static Element JavaDoc getChildElement(Element JavaDoc element, String JavaDoc namespace,
156             String JavaDoc localName) {
157         Element JavaDoc node = null;
158         try {
159             node = getChildElement(element, namespace, localName, false);
160         } catch (Exception JavaDoc e) {
161             node = null;
162         }
163         return node;
164     }
165
166     /**
167      * Returns the first child element with the given namespace and localName,
168      * or null if there is no such element and required flag is unset or
169      * throws an Exception if the "required" flag is set.
170      */

171     public static Element JavaDoc getChildElement(Element JavaDoc element, String JavaDoc namespace,
172             String JavaDoc localName, boolean required) throws Exception JavaDoc {
173         NodeList JavaDoc nodeList = element.getChildNodes();
174         for (int i = 0; i < nodeList.getLength(); i++) {
175             Node JavaDoc node = nodeList.item(i);
176             if (node instanceof Element JavaDoc
177                     && namespace.equals(node.getNamespaceURI())
178                     && localName.equals(node.getLocalName())) {
179                 return (Element JavaDoc)node;
180             }
181         }
182         if (required) {
183             throw new Exception JavaDoc("Missing element \"" + localName +
184                     "\" as child of element \"" + element.getTagName() +
185                     "\" at " + DomHelper.getLocation(element));
186         } else {
187             return null;
188         }
189     }
190
191     /**
192      * Returns the value of an element's attribute, but throws an exception
193      * if the element has no such attribute.
194      */

195     public static String JavaDoc getAttribute(Element JavaDoc element, String JavaDoc attributeName)
196             throws Exception JavaDoc {
197         String JavaDoc attrValue = element.getAttribute(attributeName);
198         if (attrValue.equals("")) {
199             throw new Exception JavaDoc("Missing attribute \"" + attributeName +
200                     "\" on element \"" + element.getTagName() +
201                     "\" at " + getLocation(element));
202         }
203         return attrValue;
204     }
205
206     /**
207      * Returns the value of an element's attribute, or a default value if the
208      * element has no such attribute.
209      */

210     public static String JavaDoc getAttribute(Element JavaDoc element, String JavaDoc attributeName,
211             String JavaDoc defaultValue) throws Exception JavaDoc {
212         String JavaDoc attrValue = element.getAttribute(attributeName);
213         if (attrValue.equals("")) {
214             return defaultValue;
215         }
216         return attrValue;
217     }
218
219     public static int getAttributeAsInteger(Element JavaDoc element,
220             String JavaDoc attributeName) throws Exception JavaDoc {
221         String JavaDoc attrValue = getAttribute(element, attributeName);
222         try {
223             return Integer.parseInt(attrValue);
224         } catch (NumberFormatException JavaDoc e) {
225             throw new Exception JavaDoc("Cannot parse the value \"" + attrValue +
226                     "\" as an integer in the attribute \"" + attributeName +
227                     "\" on the element \"" + element.getTagName() +
228                     "\" at " + getLocation(element));
229         }
230     }
231
232     public static int getAttributeAsInteger(Element JavaDoc element,
233             String JavaDoc attributeName, int defaultValue) throws Exception JavaDoc {
234         String JavaDoc attrValue = element.getAttribute(attributeName);
235         if (attrValue.equals("")) {
236             return defaultValue;
237         } else {
238             try {
239                 return Integer.parseInt(attrValue);
240             } catch (NumberFormatException JavaDoc e) {
241                 throw new Exception JavaDoc("Cannot parse the value \"" + attrValue +
242                         "\" as an integer in the attribute \"" +
243                         attributeName + "\" on the element \"" +
244                         element.getTagName() + "\" at " +
245                         getLocation(element));
246             }
247         }
248     }
249
250     public static boolean getAttributeAsBoolean(Element JavaDoc element,
251                 String JavaDoc attributeName, boolean defaultValue) {
252         String JavaDoc attrValue = element.getAttribute(attributeName);
253         Boolean JavaDoc result;
254         try {
255             result = BooleanUtils.toBooleanObject(attrValue, "true", "false", null);
256         } catch (IllegalArgumentException JavaDoc iae) {
257             result = null;
258         }
259         if (result != null) {
260             return result.booleanValue();
261         }
262         try {
263             result = BooleanUtils.toBooleanObject(attrValue, "yes", "no", null);
264         } catch (IllegalArgumentException JavaDoc iae) {
265             result = null;
266         }
267         if (result != null) {
268             return result.booleanValue();
269         }
270         return defaultValue;
271     }
272
273     public static String JavaDoc getElementText(Element JavaDoc element) {
274         StringBuffer JavaDoc value = new StringBuffer JavaDoc();
275         NodeList JavaDoc nodeList = element.getChildNodes();
276         for (int i = 0; i < nodeList.getLength(); i++) {
277             Node JavaDoc node = nodeList.item(i);
278             if (node instanceof Text JavaDoc || node instanceof CDATASection JavaDoc) {
279                 value.append(node.getNodeValue());
280             }
281         }
282         return value.toString();
283     }
284
285     /**
286      * Returns the content of the given Element as an object implementing the
287      * XMLizable interface. Practically speaking, the implementation uses the
288      * {@link SaxBuffer} class. The XMLizable object will be a standalone blurb
289      * of SAX events, not producing start/endDocument calls and containing all
290      * necessary namespace declarations.
291      */

292     public static XMLizable compileElementContent(Element JavaDoc element) {
293         SaxBuffer saxBuffer = new SaxBuffer();
294         DOMStreamer domStreamer = new DOMStreamer();
295         domStreamer.setContentHandler(saxBuffer);
296
297         NodeList JavaDoc childNodes = element.getChildNodes();
298         for (int i = 0; i < childNodes.getLength(); i++) {
299             try {
300                 domStreamer.stream(childNodes.item(i));
301             } catch (SAXException JavaDoc e) {
302                 // It's unlikely that an exception will occur here,
303
// so use a runtime exception
304
throw new RuntimeException JavaDoc(
305                         "Error in DomHelper.compileElementContent: " +
306                         e.toString());
307             }
308         }
309         return saxBuffer;
310     }
311
312     /**
313      * Creates a W3C Document that remembers the location of each element in
314      * the source file. The location of element nodes can then be retrieved
315      * using the {@link #getLocation(Element)} method.
316      */

317     public static Document JavaDoc parse(InputSource JavaDoc inputSource)
318             throws SAXException JavaDoc, SAXNotSupportedException JavaDoc, IOException JavaDoc {
319         DOMParser domParser = new LocationTrackingDOMParser();
320         domParser.setFeature(
321                 "http://apache.org/xml/features/dom/defer-node-expansion",
322                 false);
323         domParser.setFeature(
324                 "http://apache.org/xml/features/dom/create-entity-ref-nodes",
325                 false);
326         domParser.parse(inputSource);
327         return domParser.getDocument();
328     }
329
330     /**
331      * An extension of the Xerces DOM parser that puts the location of each
332      * node in that node's UserData.
333      */

334     public static class LocationTrackingDOMParser extends DOMParser {
335         XMLLocator locator;
336
337         public void startDocument(XMLLocator xmlLocator, String JavaDoc s,
338                 NamespaceContext namespaceContext,
339                 Augmentations augmentations) throws XNIException {
340             super.startDocument(xmlLocator, s, namespaceContext,
341                     augmentations);
342             this.locator = xmlLocator;
343             setLocation();
344         }
345
346         public void startElement(QName qName, XMLAttributes xmlAttributes,
347                 Augmentations augmentations) throws XNIException {
348             super.startElement(qName, xmlAttributes, augmentations);
349             setLocation();
350         }
351
352         private final void setLocation() {
353             // Older versions of Xerces had a different signature for the
354
// startDocument method. If such a version is used, the
355
// startDocument method above will not be called and locator will
356
// hence be null.
357
// Tell the users this so that they don't get a stupid NPE.
358
if (this.locator == null) {
359                 throw new RuntimeException JavaDoc(
360                         "Error: locator is null. Check that you have the" +
361                         " correct version of Xerces (such as the one that" +
362                         " comes with Cocoon) in your endorsed library path.");
363             }
364             NodeImpl node = null;
365             try {
366                 node = (NodeImpl)this.getProperty(
367                         "http://apache.org/xml/properties/dom/current-element-node");
368             } catch (org.xml.sax.SAXException JavaDoc ex) {
369                 System.err.println("except" + ex);
370             }
371             if (node != null) {
372                 String JavaDoc location = locator.getLiteralSystemId() + ":" +
373                     locator.getLineNumber() + ":" + locator.getColumnNumber();
374                 node.setUserData("location", location, (UserDataHandler JavaDoc)null);
375             }
376         }
377     }
378 }
379
Popular Tags