ingo@100: /* ingo@100: * Copyright (c) 2010 by Intevation GmbH ingo@100: * ingo@100: * This program is free software under the LGPL (>=v2.1) ingo@100: * Read the file LGPL.txt coming with the software for details ingo@100: * or visit http://www.gnu.org/licenses/ if it does not exist. ingo@100: */ ingo@100: sascha@20: package de.intevation.artifactdatabase; sascha@20: sascha@67: import java.io.File; sascha@67: import java.io.IOException; sascha@67: import java.io.OutputStream; sascha@23: sascha@23: import javax.xml.namespace.NamespaceContext; sascha@25: import javax.xml.namespace.QName; sascha@23: sascha@67: import javax.xml.parsers.DocumentBuilderFactory; sascha@67: import javax.xml.parsers.ParserConfigurationException; sascha@67: sascha@67: import javax.xml.transform.Transformer; sascha@67: import javax.xml.transform.TransformerConfigurationException; sascha@67: import javax.xml.transform.TransformerException; sascha@67: import javax.xml.transform.TransformerFactory; sascha@67: import javax.xml.transform.TransformerFactoryConfigurationError; sascha@67: sascha@67: import javax.xml.transform.dom.DOMSource; sascha@67: sascha@67: import javax.xml.transform.stream.StreamResult; sascha@67: sascha@67: import javax.xml.xpath.XPath; sascha@67: import javax.xml.xpath.XPathConstants; sascha@67: import javax.xml.xpath.XPathExpressionException; sascha@67: import javax.xml.xpath.XPathFactory; sascha@67: sascha@67: import org.apache.log4j.Logger; sascha@67: sascha@67: import org.w3c.dom.Attr; sascha@67: import org.w3c.dom.Document; sascha@67: import org.w3c.dom.Element; sascha@67: sascha@67: import org.xml.sax.SAXException; sascha@62: sascha@20: /** sascha@91: * Some helper functions to ease work with XML concering namespaces, XPATH sascha@91: * and so on. sascha@77: * @author Sascha L. Teichmann sascha@20: */ sascha@20: public final class XMLUtils sascha@20: { sascha@91: /** sascha@91: * W3C URL of XForms sascha@91: */ ingo@64: public static final String XFORM_URL = "http://www.w3.org/2002/xforms"; sascha@91: /** sascha@91: * W3C prefix of XForms sascha@91: */ ingo@64: public static final String XFORM_PREFIX = "xform"; ingo@64: sascha@20: private static Logger logger = Logger.getLogger(XMLUtils.class); sascha@20: sascha@20: private XMLUtils() { sascha@20: } sascha@20: sascha@91: /** sascha@91: * Helper class to generate elements and attributes with sascha@91: * namespaces. sascha@91: */ sascha@20: public static class ElementCreator sascha@20: { sascha@91: /** sascha@91: * owner document of the elements to be created sascha@91: */ sascha@20: protected Document document; sascha@91: /** sascha@91: * namespace to be used sascha@91: */ sascha@20: protected String ns; sascha@91: /** sascha@91: * prefix to be used sascha@91: */ sascha@20: protected String prefix; sascha@20: sascha@91: /** sascha@91: * Constructor to create an element/attribute creator sascha@91: * with a given namespace and namespace prefix using a sascha@91: * given owner document. sascha@91: * @param document The owning document sascha@91: * @param ns The namespace sascha@91: * @param prefix The namespace prefix sascha@91: */ sascha@20: public ElementCreator(Document document, String ns, String prefix) { sascha@20: this.document = document; sascha@20: this.ns = ns; sascha@20: this.prefix = prefix; sascha@20: } sascha@20: sascha@91: /** sascha@91: * Creates a new element using the owning document with sascha@91: * the this creators namespace and namespace prefix. sascha@91: * @param name The name of the element sascha@91: * @return The new element sascha@91: */ sascha@20: public Element create(String name) { sascha@20: Element element = document.createElementNS(ns, name); sascha@20: element.setPrefix(prefix); sascha@20: return element; sascha@20: } sascha@20: sascha@91: /** sascha@91: * Adds a new attribute and its value to a given element. sascha@91: * It does not set the namespace prefix. sascha@91: * @param element The element to add the attribute to sascha@91: * @param name The name of the attribute sascha@91: * @param value The value of the attribute sascha@91: */ sascha@20: public void addAttr(Element element, String name, String value) { ingo@64: addAttr(element, name, value, false); ingo@64: } ingo@64: sascha@91: /** sascha@91: * Adds a new attribute and its value to a given element. sascha@91: * If the namespace prefix is used is decided by the 'addPrefix' flag. sascha@91: * @param element The element to add the attribute to sascha@91: * @param name The name of the attribute sascha@91: * @param value The value of the attribute sascha@91: * @param addPrefix If true the creators namespace prefix is sascha@91: * set on the attribute. sascha@91: */ ingo@64: public void addAttr( ingo@64: Element element, ingo@64: String name, ingo@64: String value, ingo@64: boolean addPrefix ingo@64: ) { sascha@20: Attr attr = document.createAttributeNS(ns, name); sascha@20: attr.setValue(value); ingo@64: ingo@64: if (addPrefix) ingo@64: attr.setPrefix(prefix); ingo@64: sascha@20: element.setAttributeNode(attr); sascha@20: } sascha@20: } // class ElementCreator sascha@20: sascha@91: /** sascha@91: * Creates a new XML document sascha@91: * @return the new XML document ot null if something went wrong during sascha@91: * creation. sascha@91: */ sascha@20: public static final Document newDocument() { ingo@64: DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); ingo@64: factory.setNamespaceAware(true); ingo@64: sascha@20: try { ingo@64: return factory.newDocumentBuilder().newDocument(); sascha@20: } sascha@20: catch (ParserConfigurationException pce) { sascha@20: logger.error(pce.getLocalizedMessage(), pce); sascha@20: } sascha@20: return null; sascha@20: } sascha@23: sascha@91: /** sascha@91: * Loads a XML document namespace aware from a file sascha@91: * @param file The file to load. sascha@91: * @return the XML document or null if something went wrong sascha@91: * during loading. sascha@91: */ sascha@62: public static final Document parseDocument(File file) { ingo@64: DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); ingo@64: factory.setNamespaceAware(true); ingo@64: sascha@62: try { ingo@64: return factory.newDocumentBuilder().parse(file); sascha@62: } sascha@62: catch (ParserConfigurationException pce) { sascha@62: logger.error(pce.getLocalizedMessage(), pce); sascha@62: } sascha@62: catch (SAXException se) { sascha@62: logger.error(se.getLocalizedMessage(), se); sascha@62: } sascha@62: catch (IOException ioe) { sascha@62: logger.error(ioe.getLocalizedMessage(), ioe); sascha@62: } sascha@62: return null; sascha@62: } sascha@62: sascha@91: /** sascha@91: * Creates a new XPath without a namespace context. sascha@91: * @return the new XPath. sascha@91: */ sascha@23: public static final XPath newXPath() { sascha@23: return newXPath(null); sascha@23: } sascha@23: sascha@91: /** sascha@91: * Creates a new XPath with a given namespace context. sascha@91: * @param namespaceContext The namespace context to be used or null sascha@91: * if none should be used. sascha@91: * @return The new XPath sascha@91: */ sascha@23: public static final XPath newXPath(NamespaceContext namespaceContext) { sascha@23: XPathFactory factory = XPathFactory.newInstance(); sascha@23: XPath xpath = factory.newXPath(); sascha@23: if (namespaceContext != null) { sascha@23: xpath.setNamespaceContext(namespaceContext); sascha@23: } sascha@23: return xpath; sascha@23: } sascha@25: sascha@91: /** sascha@91: * Evaluates an XPath query on a given object and returns the result sascha@91: * as a given type. No namespace context is used. sascha@91: * @param root The object which is used as the root of the tree to sascha@91: * be searched in. sascha@91: * @param query The XPath query sascha@91: * @param returnTyp The type of the result. sascha@91: * @return The result of type 'returnTyp' or null if something sascha@91: * went wrong during XPath evaluation. sascha@91: */ sascha@94: public static final Object xpath( sascha@94: Object root, sascha@94: String query, sascha@94: QName returnTyp sascha@94: ) { sascha@25: return xpath(root, query, returnTyp, null); sascha@25: } sascha@25: sascha@91: /** sascha@92: * Evaluates an XPath query on a given object and returns the result sascha@91: * as a string. A given namespace context is used. sascha@91: * @param root The object which is used as the root of the tree to sascha@91: * be searched in. sascha@91: * @param query The XPath query sascha@91: * @param namespaceContext The namespace context to be used or null sascha@91: * if none should be used. sascha@91: * @return The result of the query or null if something went wrong sascha@91: * during XPath evaluation. sascha@91: */ sascha@26: public static final String xpathString( sascha@26: Object root, String query, NamespaceContext namespaceContext sascha@26: ) { sascha@67: return (String)xpath( sascha@67: root, query, XPathConstants.STRING, namespaceContext); sascha@26: } sascha@26: sascha@91: /** sascha@91: * Evaluates an XPath query on a given object and returns the result sascha@91: * as a given type. Optionally a namespace context is used. sascha@91: * @param root The object which is used as the root of the tree to sascha@91: * be searched in. sascha@91: * @param query The XPath query sascha@91: * @param returnType The type of the result. sascha@91: * @param namespaceContext The namespace context to be used or null sascha@91: * if none should be used. sascha@91: * @return The result of type 'returnTyp' or null if something sascha@91: * went wrong during XPath evaluation. sascha@91: */ sascha@25: public static final Object xpath( sascha@25: Object root, sascha@25: String query, sascha@25: QName returnType, sascha@25: NamespaceContext namespaceContext sascha@25: ) { sascha@25: if (root == null) { sascha@25: return null; sascha@25: } sascha@25: sascha@25: try { sascha@25: XPath xpath = newXPath(namespaceContext); sascha@25: if (xpath != null) { sascha@25: return xpath.evaluate(query, root, returnType); sascha@25: } sascha@25: } sascha@25: catch (XPathExpressionException xpee) { sascha@25: logger.error(xpee.getLocalizedMessage(), xpee); sascha@47: } sascha@25: sascha@25: return null; sascha@25: } sascha@67: sascha@91: /** sascha@91: * Streams out an XML document to a given output stream. sascha@91: * @param document The document to be streamed out. sascha@91: * @param out The output stream to be used. sascha@91: * @return true if operation succeeded else false. sascha@91: */ sascha@67: public static boolean toStream(Document document, OutputStream out) { sascha@67: try { sascha@67: Transformer transformer = sascha@67: TransformerFactory.newInstance().newTransformer(); sascha@67: DOMSource source = new DOMSource(document); sascha@67: StreamResult result = new StreamResult(out); sascha@67: transformer.transform(source, result); sascha@67: return true; sascha@67: } sascha@67: catch (TransformerConfigurationException tce) { sascha@67: logger.error(tce.getLocalizedMessage(), tce); sascha@67: } sascha@67: catch (TransformerFactoryConfigurationError tfce) { sascha@67: logger.error(tfce.getLocalizedMessage(), tfce); sascha@67: } sascha@67: catch (TransformerException te) { sascha@67: logger.error(te.getLocalizedMessage(), te); sascha@67: } sascha@67: sascha@67: return false; sascha@67: } sascha@20: } sascha@91: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :