You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
412 lines
13 KiB
412 lines
13 KiB
/* |
|
* Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. |
|
* |
|
* This software is open source. |
|
* See the bottom of this file for the licence. |
|
*/ |
|
|
|
package org.dom4j; |
|
|
|
import java.io.StringReader; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.StringTokenizer; |
|
|
|
import org.dom4j.io.SAXReader; |
|
import org.dom4j.rule.Pattern; |
|
|
|
import org.jaxen.VariableContext; |
|
|
|
import org.xml.sax.InputSource; |
|
|
|
/** |
|
* <p> |
|
* <code>DocumentHelper</code> is a collection of helper methods for using |
|
* DOM4J. |
|
* </p> |
|
* |
|
* @author <a href="mailto:jstrachan@apache.org">James Strachan </a> |
|
* @version $Revision$ |
|
*/ |
|
public final class DocumentHelper { |
|
private DocumentHelper() { |
|
} |
|
|
|
private static DocumentFactory getDocumentFactory() { |
|
return DocumentFactory.getInstance(); |
|
} |
|
|
|
// Static helper methods |
|
public static Document createDocument() { |
|
return getDocumentFactory().createDocument(); |
|
} |
|
|
|
public static Document createDocument(Element rootElement) { |
|
return getDocumentFactory().createDocument(rootElement); |
|
} |
|
|
|
public static Element createElement(QName qname) { |
|
return getDocumentFactory().createElement(qname); |
|
} |
|
|
|
public static Element createElement(String name) { |
|
return getDocumentFactory().createElement(name); |
|
} |
|
|
|
public static Attribute createAttribute(Element owner, QName qname, |
|
String value) { |
|
return getDocumentFactory().createAttribute(owner, qname, value); |
|
} |
|
|
|
public static Attribute createAttribute(Element owner, String name, |
|
String value) { |
|
return getDocumentFactory().createAttribute(owner, name, value); |
|
} |
|
|
|
public static CDATA createCDATA(String text) { |
|
return DocumentFactory.getInstance().createCDATA(text); |
|
} |
|
|
|
public static Comment createComment(String text) { |
|
return DocumentFactory.getInstance().createComment(text); |
|
} |
|
|
|
public static Text createText(String text) { |
|
return DocumentFactory.getInstance().createText(text); |
|
} |
|
|
|
public static Entity createEntity(String name, String text) { |
|
return DocumentFactory.getInstance().createEntity(name, text); |
|
} |
|
|
|
public static Namespace createNamespace(String prefix, String uri) { |
|
return DocumentFactory.getInstance().createNamespace(prefix, uri); |
|
} |
|
|
|
public static ProcessingInstruction createProcessingInstruction(String pi, |
|
String d) { |
|
return getDocumentFactory().createProcessingInstruction(pi, d); |
|
} |
|
|
|
public static ProcessingInstruction createProcessingInstruction(String pi, |
|
Map data) { |
|
return getDocumentFactory().createProcessingInstruction(pi, data); |
|
} |
|
|
|
public static QName createQName(String localName, Namespace namespace) { |
|
return getDocumentFactory().createQName(localName, namespace); |
|
} |
|
|
|
public static QName createQName(String localName) { |
|
return getDocumentFactory().createQName(localName); |
|
} |
|
|
|
/** |
|
* <p> |
|
* <code>createXPath</code> parses an XPath expression and creates a new |
|
* XPath <code>XPath</code> instance using the singleton {@link |
|
* DocumentFactory}. |
|
* </p> |
|
* |
|
* @param xpathExpression |
|
* is the XPath expression to create |
|
* |
|
* @return a new <code>XPath</code> instance |
|
* |
|
* @throws InvalidXPathException |
|
* if the XPath expression is invalid |
|
*/ |
|
public static XPath createXPath(String xpathExpression) |
|
throws InvalidXPathException { |
|
return getDocumentFactory().createXPath(xpathExpression); |
|
} |
|
|
|
/** |
|
* <p> |
|
* <code>createXPath</code> parses an XPath expression and creates a new |
|
* XPath <code>XPath</code> instance using the singleton {@link |
|
* DocumentFactory}. |
|
* </p> |
|
* |
|
* @param xpathExpression |
|
* is the XPath expression to create |
|
* @param context |
|
* is the variable context to use when evaluating the XPath |
|
* |
|
* @return a new <code>XPath</code> instance |
|
* |
|
* @throws InvalidXPathException |
|
* if the XPath expression is invalid |
|
*/ |
|
public static XPath createXPath(String xpathExpression, |
|
VariableContext context) throws InvalidXPathException { |
|
return getDocumentFactory().createXPath(xpathExpression, context); |
|
} |
|
|
|
/** |
|
* <p> |
|
* <code>createXPathFilter</code> parses a NodeFilter from the given XPath |
|
* filter expression using the singleton {@link DocumentFactory}. XPath |
|
* filter expressions occur within XPath expressions such as |
|
* <code>self::node()[ filterExpression ]</code> |
|
* </p> |
|
* |
|
* @param xpathFilterExpression |
|
* is the XPath filter expression to create |
|
* |
|
* @return a new <code>NodeFilter</code> instance |
|
*/ |
|
public static NodeFilter createXPathFilter(String xpathFilterExpression) { |
|
return getDocumentFactory().createXPathFilter(xpathFilterExpression); |
|
} |
|
|
|
/** |
|
* <p> |
|
* <code>createPattern</code> parses the given XPath expression to create |
|
* an XSLT style {@link Pattern}instance which can then be used in an XSLT |
|
* processing model. |
|
* </p> |
|
* |
|
* @param xpathPattern |
|
* is the XPath pattern expression to create |
|
* |
|
* @return a new <code>Pattern</code> instance |
|
*/ |
|
public static Pattern createPattern(String xpathPattern) { |
|
return getDocumentFactory().createPattern(xpathPattern); |
|
} |
|
|
|
/** |
|
* <p> |
|
* <code>selectNodes</code> performs the given XPath expression on the |
|
* {@link List}of {@link Node}instances appending all the results together |
|
* into a single list. |
|
* </p> |
|
* |
|
* @param xpathFilterExpression |
|
* is the XPath filter expression to evaluate |
|
* @param nodes |
|
* is the list of nodes on which to evalute the XPath |
|
* |
|
* @return the results of all the XPath evaluations as a single list |
|
*/ |
|
public static List selectNodes(String xpathFilterExpression, List nodes) { |
|
XPath xpath = createXPath(xpathFilterExpression); |
|
|
|
return xpath.selectNodes(nodes); |
|
} |
|
|
|
/** |
|
* <p> |
|
* <code>selectNodes</code> performs the given XPath expression on the |
|
* {@link List}of {@link Node}instances appending all the results together |
|
* into a single list. |
|
* </p> |
|
* |
|
* @param xpathFilterExpression |
|
* is the XPath filter expression to evaluate |
|
* @param node |
|
* is the Node on which to evalute the XPath |
|
* |
|
* @return the results of all the XPath evaluations as a single list |
|
*/ |
|
public static List selectNodes(String xpathFilterExpression, Node node) { |
|
XPath xpath = createXPath(xpathFilterExpression); |
|
|
|
return xpath.selectNodes(node); |
|
} |
|
|
|
/** |
|
* <p> |
|
* <code>sort</code> sorts the given List of Nodes using an XPath |
|
* expression as a {@link java.util.Comparator}. |
|
* </p> |
|
* |
|
* @param list |
|
* is the list of Nodes to sort |
|
* @param xpathExpression |
|
* is the XPath expression used for comparison |
|
*/ |
|
public static void sort(List list, String xpathExpression) { |
|
XPath xpath = createXPath(xpathExpression); |
|
xpath.sort(list); |
|
} |
|
|
|
/** |
|
* <p> |
|
* <code>sort</code> sorts the given List of Nodes using an XPath |
|
* expression as a {@link java.util.Comparator}and optionally removing |
|
* duplicates. |
|
* </p> |
|
* |
|
* @param list |
|
* is the list of Nodes to sort |
|
* @param expression |
|
* is the XPath expression used for comparison |
|
* @param distinct |
|
* if true then duplicate values (using the sortXPath for |
|
* comparisions) will be removed from the List |
|
*/ |
|
public static void sort(List list, String expression, boolean distinct) { |
|
XPath xpath = createXPath(expression); |
|
xpath.sort(list, distinct); |
|
} |
|
|
|
/** |
|
* <p> |
|
* <code>parseText</code> parses the given text as an XML document and |
|
* returns the newly created Document. |
|
* </p> |
|
* |
|
* @param text |
|
* the XML text to be parsed |
|
* |
|
* @return a newly parsed Document |
|
* |
|
* @throws DocumentException |
|
* if the document could not be parsed |
|
*/ |
|
public static Document parseText(String text) throws DocumentException { |
|
Document result = null; |
|
|
|
SAXReader reader = new SAXReader(); |
|
String encoding = getEncoding(text); |
|
|
|
InputSource source = new InputSource(new StringReader(text)); |
|
source.setEncoding(encoding); |
|
|
|
result = reader.read(source); |
|
|
|
// if the XML parser doesn't provide a way to retrieve the encoding, |
|
// specify it manually |
|
if (result.getXMLEncoding() == null) { |
|
result.setXMLEncoding(encoding); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
private static String getEncoding(String text) { |
|
String result = null; |
|
|
|
String xml = text.trim(); |
|
|
|
if (xml.startsWith("<?xml")) { |
|
int end = xml.indexOf("?>"); |
|
String sub = xml.substring(0, end); |
|
StringTokenizer tokens = new StringTokenizer(sub, " =\"\'"); |
|
|
|
while (tokens.hasMoreTokens()) { |
|
String token = tokens.nextToken(); |
|
|
|
if ("encoding".equals(token)) { |
|
if (tokens.hasMoreTokens()) { |
|
result = tokens.nextToken(); |
|
} |
|
|
|
break; |
|
} |
|
} |
|
} |
|
|
|
return result; |
|
} |
|
|
|
/** |
|
* <p> |
|
* makeElement |
|
* </p> |
|
* a helper method which navigates from the given Document or Element node |
|
* to some Element using the path expression, creating any necessary |
|
* elements along the way. For example the path <code>a/b/c</code> would |
|
* get the first child <a> element, which would be created if it did |
|
* not exist, then the next child <b> and so on until finally a |
|
* <c> element is returned. |
|
* |
|
* @param source |
|
* is the Element or Document to start navigating from |
|
* @param path |
|
* is a simple path expression, seperated by '/' which denotes |
|
* the path from the source to the resulting element such as |
|
* a/b/c |
|
* |
|
* @return the first Element on the given path which either already existed |
|
* on the path or were created by this method. |
|
*/ |
|
public static Element makeElement(Branch source, String path) { |
|
StringTokenizer tokens = new StringTokenizer(path, "/"); |
|
Element parent; |
|
|
|
if (source instanceof Document) { |
|
Document document = (Document) source; |
|
parent = document.getRootElement(); |
|
|
|
// lets throw a NoSuchElementException |
|
// if we are given an empty path |
|
String name = tokens.nextToken(); |
|
|
|
if (parent == null) { |
|
parent = document.addElement(name); |
|
} |
|
} else { |
|
parent = (Element) source; |
|
} |
|
|
|
Element element = null; |
|
|
|
while (tokens.hasMoreTokens()) { |
|
String name = tokens.nextToken(); |
|
|
|
if (name.indexOf(':') > 0) { |
|
element = parent.element(parent.getQName(name)); |
|
} else { |
|
element = parent.element(name); |
|
} |
|
|
|
if (element == null) { |
|
element = parent.addElement(name); |
|
} |
|
|
|
parent = element; |
|
} |
|
|
|
return element; |
|
} |
|
} |
|
|
|
/* |
|
* Redistribution and use of this software and associated documentation |
|
* ("Software"), with or without modification, are permitted provided that the |
|
* following conditions are met: |
|
* |
|
* 1. Redistributions of source code must retain copyright statements and |
|
* notices. Redistributions must also contain a copy of this document. |
|
* |
|
* 2. Redistributions in binary form must reproduce the above copyright notice, |
|
* this list of conditions and the following disclaimer in the documentation |
|
* and/or other materials provided with the distribution. |
|
* |
|
* 3. The name "DOM4J" must not be used to endorse or promote products derived |
|
* from this Software without prior written permission of MetaStuff, Ltd. For |
|
* written permission, please contact dom4j-info@metastuff.com. |
|
* |
|
* 4. Products derived from this Software may not be called "DOM4J" nor may |
|
* "DOM4J" appear in their names without prior written permission of MetaStuff, |
|
* Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. |
|
* |
|
* 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org |
|
* |
|
* THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND |
|
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
* ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE |
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
* POSSIBILITY OF SUCH DAMAGE. |
|
* |
|
* Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. |
|
*/
|
|
|