Clover coverage report - dom4j - 1.6.1 Coverage timestamp: ma mei 16 2005 14:23:01 GMT+01:00 FRAMES NO FRAMES |
file stats: | LOC: | 412 |  | Methods: | 28
| NCLOC: | 154 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
DocumentHelper.java | 95% | 75,4% | 50% | 72,6% |

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;
9 |  |
10 |  | import java.io.StringReader;
11 |  | import java.util.List;
12 |  | import java.util.Map;
13 |  | import java.util.StringTokenizer;
14 |  |
15 |  | import org.dom4j.io.SAXReader;
16 |  | import org.dom4j.rule.Pattern;
17 |  |
18 |  | import org.jaxen.VariableContext;
19 |  |
20 |  | import org.xml.sax.InputSource;
21 |  |
22 |  | /**
23 |  | * <p>
24 |  | * <code>DocumentHelper</code> is a collection of helper methods for using
25 |  | * DOM4J.
26 |  | * </p>
27 |  | *
28 |  | * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
29 |  | * @version $Revision: 1.26 $
30 |  | */
31 |  | public final class DocumentHelper {
32 | 0 | private DocumentHelper() {
33 |  | }
34 |  |
35 | 12496 | private static DocumentFactory getDocumentFactory() {
36 | 12496 | return DocumentFactory.getInstance();
37 |  | }
38 |  |
39 |  | // Static helper methods
40 | 412 | public static Document createDocument() {
41 | 412 | return getDocumentFactory().createDocument();
42 |  | }
43 |  |
44 | 2 | public static Document createDocument(Element rootElement) {
45 | 2 | return getDocumentFactory().createDocument(rootElement);
46 |  | }
47 |  |
48 | 2000 | public static Element createElement(QName qname) {
49 | 2000 | return getDocumentFactory().createElement(qname);
50 |  | }
51 |  |
52 | 4 | public static Element createElement(String name) {
53 | 4 | return getDocumentFactory().createElement(name);
54 |  | }
55 |  |
56 | 0 | public static Attribute createAttribute(Element owner, QName qname,
57 |  | String value) {
58 | 0 | return getDocumentFactory().createAttribute(owner, qname, value);
59 |  | }
60 |  |
61 | 0 | public static Attribute createAttribute(Element owner, String name,
62 |  | String value) {
63 | 0 | return getDocumentFactory().createAttribute(owner, name, value);
64 |  | }
65 |  |
66 | 0 | public static CDATA createCDATA(String text) {
67 | 0 | return DocumentFactory.getInstance().createCDATA(text);
68 |  | }
69 |  |
70 | 0 | public static Comment createComment(String text) {
71 | 0 | return DocumentFactory.getInstance().createComment(text);
72 |  | }
73 |  |
74 | 0 | public static Text createText(String text) {
75 | 0 | return DocumentFactory.getInstance().createText(text);
76 |  | }
77 |  |
78 | 0 | public static Entity createEntity(String name, String text) {
79 | 0 | return DocumentFactory.getInstance().createEntity(name, text);
80 |  | }
81 |  |
82 | 0 | public static Namespace createNamespace(String prefix, String uri) {
83 | 0 | return DocumentFactory.getInstance().createNamespace(prefix, uri);
84 |  | }
85 |  |
86 | 2 | public static ProcessingInstruction createProcessingInstruction(String pi,
87 |  | String d) {
88 | 2 | return getDocumentFactory().createProcessingInstruction(pi, d);
89 |  | }
90 |  |
91 | 0 | public static ProcessingInstruction createProcessingInstruction(String pi,
92 |  | Map data) {
93 | 0 | return getDocumentFactory().createProcessingInstruction(pi, data);
94 |  | }
95 |  |
96 | 0 | public static QName createQName(String localName, Namespace namespace) {
97 | 0 | return getDocumentFactory().createQName(localName, namespace);
98 |  | }
99 |  |
100 | 10000 | public static QName createQName(String localName) {
101 | 10000 | return getDocumentFactory().createQName(localName);
102 |  | }
103 |  |
104 |  | /**
105 |  | * <p>
106 |  | * <code>createXPath</code> parses an XPath expression and creates a new
107 |  | * XPath <code>XPath</code> instance using the singleton {@link
108 |  | * DocumentFactory}.
109 |  | * </p>
110 |  | *
111 |  | * @param xpathExpression
112 |  | * is the XPath expression to create
113 |  | *
114 |  | * @return a new <code>XPath</code> instance
115 |  | *
116 |  | * @throws InvalidXPathException
117 |  | * if the XPath expression is invalid
118 |  | */
119 | 57 | public static XPath createXPath(String xpathExpression)
120 |  | throws InvalidXPathException {
121 | 57 | return getDocumentFactory().createXPath(xpathExpression);
122 |  | }
123 |  |
124 |  | /**
125 |  | * <p>
126 |  | * <code>createXPath</code> parses an XPath expression and creates a new
127 |  | * XPath <code>XPath</code> instance using the singleton {@link
128 |  | * DocumentFactory}.
129 |  | * </p>
130 |  | *
131 |  | * @param xpathExpression
132 |  | * is the XPath expression to create
133 |  | * @param context
134 |  | * is the variable context to use when evaluating the XPath
135 |  | *
136 |  | * @return a new <code>XPath</code> instance
137 |  | *
138 |  | * @throws InvalidXPathException
139 |  | * if the XPath expression is invalid
140 |  | */
141 | 1 | public static XPath createXPath(String xpathExpression,
142 |  | VariableContext context) throws InvalidXPathException {
143 | 1 | return getDocumentFactory().createXPath(xpathExpression, context);
144 |  | }
145 |  |
146 |  | /**
147 |  | * <p>
148 |  | * <code>createXPathFilter</code> parses a NodeFilter from the given XPath
149 |  | * filter expression using the singleton {@link DocumentFactory}. XPath
150 |  | * filter expressions occur within XPath expressions such as
151 |  | * <code>self::node()[ filterExpression ]</code>
152 |  | * </p>
153 |  | *
154 |  | * @param xpathFilterExpression
155 |  | * is the XPath filter expression to create
156 |  | *
157 |  | * @return a new <code>NodeFilter</code> instance
158 |  | */
159 | 4 | public static NodeFilter createXPathFilter(String xpathFilterExpression) {
160 | 4 | return getDocumentFactory().createXPathFilter(xpathFilterExpression);
161 |  | }
162 |  |
163 |  | /**
164 |  | * <p>
165 |  | * <code>createPattern</code> parses the given XPath expression to create
166 |  | * an XSLT style {@link Pattern}instance which can then be used in an XSLT
167 |  | * processing model.
168 |  | * </p>
169 |  | *
170 |  | * @param xpathPattern
171 |  | * is the XPath pattern expression to create
172 |  | *
173 |  | * @return a new <code>Pattern</code> instance
174 |  | */
175 | 14 | public static Pattern createPattern(String xpathPattern) {
176 | 14 | return getDocumentFactory().createPattern(xpathPattern);
177 |  | }
178 |  |
179 |  | /**
180 |  | * <p>
181 |  | * <code>selectNodes</code> performs the given XPath expression on the
182 |  | * {@link List}of {@link Node}instances appending all the results together
183 |  | * into a single list.
184 |  | * </p>
185 |  | *
186 |  | * @param xpathFilterExpression
187 |  | * is the XPath filter expression to evaluate
188 |  | * @param nodes
189 |  | * is the list of nodes on which to evalute the XPath
190 |  | *
191 |  | * @return the results of all the XPath evaluations as a single list
192 |  | */
193 | 0 | public static List selectNodes(String xpathFilterExpression, List nodes) {
194 | 0 | XPath xpath = createXPath(xpathFilterExpression);
195 |  |
196 | 0 | return xpath.selectNodes(nodes);
197 |  | }
198 |  |
199 |  | /**
200 |  | * <p>
201 |  | * <code>selectNodes</code> performs the given XPath expression on the
202 |  | * {@link List}of {@link Node}instances appending all the results together
203 |  | * into a single list.
204 |  | * </p>
205 |  | *
206 |  | * @param xpathFilterExpression
207 |  | * is the XPath filter expression to evaluate
208 |  | * @param node
209 |  | * is the Node on which to evalute the XPath
210 |  | *
211 |  | * @return the results of all the XPath evaluations as a single list
212 |  | */
213 | 0 | public static List selectNodes(String xpathFilterExpression, Node node) {
214 | 0 | XPath xpath = createXPath(xpathFilterExpression);
215 |  |
216 | 0 | return xpath.selectNodes(node);
217 |  | }
218 |  |
219 |  | /**
220 |  | * <p>
221 |  | * <code>sort</code> sorts the given List of Nodes using an XPath
222 |  | * expression as a {@link java.util.Comparator}.
223 |  | * </p>
224 |  | *
225 |  | * @param list
226 |  | * is the list of Nodes to sort
227 |  | * @param xpathExpression
228 |  | * is the XPath expression used for comparison
229 |  | */
230 | 0 | public static void sort(List list, String xpathExpression) {
231 | 0 | XPath xpath = createXPath(xpathExpression);
232 | 0 | xpath.sort(list);
233 |  | }
234 |  |
235 |  | /**
236 |  | * <p>
237 |  | * <code>sort</code> sorts the given List of Nodes using an XPath
238 |  | * expression as a {@link java.util.Comparator}and optionally removing
239 |  | * duplicates.
240 |  | * </p>
241 |  | *
242 |  | * @param list
243 |  | * is the list of Nodes to sort
244 |  | * @param expression
245 |  | * is the XPath expression used for comparison
246 |  | * @param distinct
247 |  | * if true then duplicate values (using the sortXPath for
248 |  | * comparisions) will be removed from the List
249 |  | */
250 | 0 | public static void sort(List list, String expression, boolean distinct) {
251 | 0 | XPath xpath = createXPath(expression);
252 | 0 | xpath.sort(list, distinct);
253 |  | }
254 |  |
255 |  | /**
256 |  | * <p>
257 |  | * <code>parseText</code> parses the given text as an XML document and
258 |  | * returns the newly created Document.
259 |  | * </p>
260 |  | *
261 |  | * @param text
262 |  | * the XML text to be parsed
263 |  | *
264 |  | * @return a newly parsed Document
265 |  | *
266 |  | * @throws DocumentException
267 |  | * if the document could not be parsed
268 |  | */
269 | 5552 | public static Document parseText(String text) throws DocumentException {
270 | 5552 | Document result = null;
271 |  |
272 | 5552 | SAXReader reader = new SAXReader();
273 | 5552 | String encoding = getEncoding(text);
274 |  |
275 | 5552 | InputSource source = new InputSource(new StringReader(text));
276 | 5552 | source.setEncoding(encoding);
277 |  |
278 | 5552 | result = reader.read(source);
279 |  |
280 |  | // if the XML parser doesn't provide a way to retrieve the encoding,
281 |  | // specify it manually
282 | 5552 | if (result.getXMLEncoding() == null) {
283 | 5528 | result.setXMLEncoding(encoding);
284 |  | }
285 |  |
286 | 5552 | return result;
287 |  | }
288 |  |
289 | 5552 | private static String getEncoding(String text) {
290 | 5552 | String result = null;
291 |  |
292 | 5552 | String xml = text.trim();
293 |  |
294 | 5552 | if (xml.startsWith("<?xml")) {
295 | 25 | int end = xml.indexOf("?>");
296 | 25 | String sub = xml.substring(0, end);
297 | 25 | StringTokenizer tokens = new StringTokenizer(sub, " =\"\'");
298 |  |
299 | 25 | while (tokens.hasMoreTokens()) {
300 | 99 | String token = tokens.nextToken();
301 |  |
302 | 99 | if ("encoding".equals(token)) {
303 | 24 | if (tokens.hasMoreTokens()) {
304 | 24 | result = tokens.nextToken();
305 |  | }
306 |  |
307 | 24 | break;
308 |  | }
309 |  | }
310 |  | }
311 |  |
312 | 5552 | return result;
313 |  | }
314 |  |
315 |  | /**
316 |  | * <p>
317 |  | * makeElement
318 |  | * </p>
319 |  | * a helper method which navigates from the given Document or Element node
320 |  | * to some Element using the path expression, creating any necessary
321 |  | * elements along the way. For example the path <code>a/b/c</code> would
322 |  | * get the first child &lt;a&gt; element, which would be created if it did
323 |  | * not exist, then the next child &lt;b&gt; and so on until finally a
324 |  | * &lt;c&gt; element is returned.
325 |  | *
326 |  | * @param source
327 |  | * is the Element or Document to start navigating from
328 |  | * @param path
329 |  | * is a simple path expression, seperated by '/' which denotes
330 |  | * the path from the source to the resulting element such as
331 |  | * a/b/c
332 |  | *
333 |  | * @return the first Element on the given path which either already existed
334 |  | * on the path or were created by this method.
335 |  | */
336 | 6 | public static Element makeElement(Branch source, String path) {
337 | 6 | StringTokenizer tokens = new StringTokenizer(path, "/");
338 | 6 | Element parent;
339 |  |
340 | 6 | if (source instanceof Document) {
341 | 4 | Document document = (Document) source;
342 | 4 | parent = document.getRootElement();
343 |  |
344 |  | // lets throw a NoSuchElementException
345 |  | // if we are given an empty path
346 | 4 | String name = tokens.nextToken();
347 |  |
348 | 4 | if (parent == null) {
349 | 1 | parent = document.addElement(name);
350 |  | }
351 |  | } else {
352 | 2 | parent = (Element) source;
353 |  | }
354 |  |
355 | 6 | Element element = null;
356 |  |
357 | 6 | while (tokens.hasMoreTokens()) {
358 | 14 | String name = tokens.nextToken();
359 |  |
360 | 14 | if (name.indexOf(':') > 0) {
361 | 4 | element = parent.element(parent.getQName(name));
362 |  | } else {
363 | 10 | element = parent.element(name);
364 |  | }
365 |  |
366 | 14 | if (element == null) {
367 | 6 | element = parent.addElement(name);
368 |  | }
369 |  |
370 | 14 | parent = element;
371 |  | }
372 |  |
373 | 6 | return element;
374 |  | }
375 |  | }
376 |  |
377 |  | /*
378 |  | * Redistribution and use of this software and associated documentation
379 |  | * ("Software"), with or without modification, are permitted provided that the
380 |  | * following conditions are met:
381 |  | *
382 |  | * 1. Redistributions of source code must retain copyright statements and
383 |  | * notices. Redistributions must also contain a copy of this document.
384 |  | *
385 |  | * 2. Redistributions in binary form must reproduce the above copyright notice,
386 |  | * this list of conditions and the following disclaimer in the documentation
387 |  | * and/or other materials provided with the distribution.
388 |  | *
389 |  | * 3. The name "DOM4J" must not be used to endorse or promote products derived
390 |  | * from this Software without prior written permission of MetaStuff, Ltd. For
391 |  | * written permission, please contact dom4j-info@metastuff.com.
392 |  | *
393 |  | * 4. Products derived from this Software may not be called "DOM4J" nor may
394 |  | * "DOM4J" appear in their names without prior written permission of MetaStuff,
395 |  | * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
396 |  | *
397 |  | * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
398 |  | *
399 |  | * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
400 |  | * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
401 |  | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
402 |  | * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
403 |  | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
404 |  | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
405 |  | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
406 |  | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
407 |  | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
408 |  | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
409 |  | * POSSIBILITY OF SUCH DAMAGE.
410 |  | *
411 |  | * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
412 |  | */