/*******************************************************************************
* Copyright (c) 2010 Robert "Unlogic" Olofsson (unlogic@unlogic.se).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v3
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-3.0-standalone.html
******************************************************************************/
package se.unlogic.standardutils.xml;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class XMLUtils {
private static DocumentBuilder documentBuilder;
private static DocumentBuilder namespaceAwareDocumentBuilder;
static {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilder = documentBuilderFactory.newDocumentBuilder();
documentBuilderFactory.setNamespaceAware(true);
namespaceAwareDocumentBuilder = documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
public static Document createDomDocument() {
return documentBuilder.newDocument();
}
public static Document createNamespaceAwareDomDocument() {
return namespaceAwareDocumentBuilder.newDocument();
}
public static String toString(Document doc, String encoding, boolean indent) throws TransformerFactoryConfigurationError, TransformerException {
Source source = new DOMSource(doc);
StringWriter sw = new StringWriter();
Result result = new StreamResult(sw);
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.setOutputProperty(OutputKeys.ENCODING, encoding);
if (indent) {
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
}
xformer.transform(source, result);
return sw.getBuffer().toString();
}
public static void toString(Document doc, String encoding, Writer w, boolean indent) throws TransformerFactoryConfigurationError, TransformerException {
Source source = new DOMSource(doc);
Result result = new StreamResult(w);
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.setOutputProperty(OutputKeys.ENCODING, encoding);
if (indent) {
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
}
xformer.transform(source, result);
}
public static Document parseXmlFile(String filename, boolean validating, boolean namespaceAware) throws SAXException, IOException, ParserConfigurationException {
return parseXmlFile(new File(filename), validating, namespaceAware);
}
public static Document parseXmlFile(File file, boolean validating, boolean namespaceAware) throws SAXException, IOException, ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(namespaceAware);
factory.setValidating(validating);
Document doc = factory.newDocumentBuilder().parse(file);
return doc;
}
public static Document parseXmlFile(URI uri, boolean validating) throws SAXException, IOException, ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(validating);
Document doc = factory.newDocumentBuilder().parse(uri.toString());
return doc;
}
public static Document parseXmlFile(File f, boolean validating) throws SAXException, IOException, ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(validating);
Document doc = factory.newDocumentBuilder().parse(f);
return doc;
}
public static Document parseXmlFile(InputStream stream, boolean validating) throws SAXException, IOException, ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(validating);
Document doc = factory.newDocumentBuilder().parse(stream);
return doc;
}
public static Element createElement(String name, Object value, Document doc) {
Element element = doc.createElement(name);
element.appendChild(doc.createTextNode(value.toString()));
return element;
}
public static Element createCDATAElement(String name, Object value, Document doc) {
Element element = doc.createElement(name);
element.appendChild(doc.createCDATASection(value.toString()));
return element;
}
public static void writeXmlFile(Document doc, File file, boolean indent, String encoding) throws TransformerFactoryConfigurationError, TransformerException {
// Prepare the DOM document for writing
Source source = new DOMSource(doc);
// Prepare the output file
Result result = new StreamResult(file);
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.setOutputProperty(OutputKeys.ENCODING, encoding);
if (indent) {
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
}
xformer.transform(source, result);
}
public static void writeXmlFile(Document doc, File file, Entry<String,String>... outputKeys) throws TransformerFactoryConfigurationError, TransformerException {
// Prepare the DOM document for writing
Source source = new DOMSource(doc);
// Prepare the output file
Result result = new StreamResult(file);
// Write the DOM document to the file
Transformer xformer = TransformerFactory.newInstance().newTransformer();
if(outputKeys != null){
for(Entry<String,String> entry : outputKeys){
xformer.setOutputProperty(entry.getKey(), entry.getValue());
}
}
xformer.transform(source, result);
}
public static void writeXmlFile(Document doc, String filename, boolean indent, String encoding) throws TransformerFactoryConfigurationError, TransformerException {
// Prepare the output file
File file = new File(filename);
writeXmlFile(doc, file, indent, encoding);
}
public static void append(Document doc, Element targetElement, Collection<? extends XMLable> beans) {
if (beans != null && !beans.isEmpty()) {
for (XMLable xmlable : beans) {
targetElement.appendChild(xmlable.toXML(doc));
}
}
}
public static void append(Document doc, Element targetElement, String elementName, String subElementsName, Object[] values) {
if(values != null){
Element subElement = doc.createElement(elementName);
targetElement.appendChild(subElement);
for (Object value : values) {
appendNewCDATAElement(doc, subElement, subElementsName, value);
}
}
}
public static void append(Document doc, Element targetElement, String elementName, String subElementsName, List<? extends Object> values) {
if(values != null){
Element subElement = doc.createElement(elementName);
targetElement.appendChild(subElement);
for (Object value : values) {
appendNewCDATAElement(doc, subElement, subElementsName, value);
}
}
}
public static void append(Document doc, Element targetElement, String elementName, Collection<? extends XMLable> beans) {
if (beans != null && !beans.isEmpty()) {
Element subElement = doc.createElement(elementName);
targetElement.appendChild(subElement);
for (XMLable xmlable : beans) {
subElement.appendChild(xmlable.toXML(doc));
}
}
}
public static void appendNewCDATAElement(Document doc, Element targetElement, String elementName, String value) {
if(value != null){
targetElement.appendChild(createCDATAElement(elementName, value, doc));
}
}
public static void appendNewElement(Document doc, Element targetElement, String elementName, String value) {
if(value != null){
targetElement.appendChild(createElement(elementName, value, doc));
}
}
public static void appendNewCDATAElement(Document doc, Element targetElement, String elementName, Object value) {
if(value != null){
appendNewCDATAElement(doc,targetElement,elementName,value.toString());
}
}
public static void appendNewElement(Document doc, Element targetElement, String elementName, Object value) {
if(value != null){
appendNewElement(doc,targetElement,elementName,value.toString());
}
}
/**
* Adds or replaces node in parent.
* @param parent
* @param node
* @throws Exception - Node cannot exist more than once,
* i.e. multiple nodes with the same name cannot exist in parent.
*/
public static void replaceSingleNode(Element parent, final Node node) throws RuntimeException {
NodeList nodes = parent.getElementsByTagName(node.getNodeName());
if(nodes.getLength() > 1) {
throw new RuntimeException("Parent element contains multiple nodes with the name " + node.getNodeName());
}
if(nodes.getLength() == 0) {
parent.appendChild(node);
} else {
parent.replaceChild(node, nodes.item(0));
}
}
public enum TimeUnit {
HOUR,
MINUTE,
SECOND;
}
public static Element getTimeUnits(Document doc, TimeUnit timeUnit) {
switch(timeUnit) {
case HOUR:
Element hoursElement = doc.createElement("hours");
Element hourElement;
for(int i=0;i<10;++i) {
hourElement = doc.createElement("hour");
XMLUtils.appendNewElement(doc, hourElement, "value", "0"+i);
hoursElement.appendChild(hourElement);
}
for(int i=10;i<24;++i) {
hourElement = doc.createElement("hour");
XMLUtils.appendNewElement(doc, hourElement, "value", i);
hoursElement.appendChild(hourElement);
}
return hoursElement;
case MINUTE:
Element minutesElement = doc.createElement("minutes");
Element minuteElement;
for(int i=0;i<10;++i) {
minuteElement = doc.createElement("minute");
XMLUtils.appendNewElement(doc, minuteElement, "value", "0"+i);
minutesElement.appendChild(minuteElement);
}
for(int i=10;i<60;++i) {
minuteElement = doc.createElement("minute");
XMLUtils.appendNewElement(doc, minuteElement, "value", i);
minutesElement.appendChild(minuteElement);
}
return minutesElement;
case SECOND:
Element secondsElement = doc.createElement("seconds");
Element secondElement;
for(int i=0;i<10;++i) {
secondElement = doc.createElement("second");
XMLUtils.appendNewElement(doc, secondElement, "value", "0"+i);
secondsElement.appendChild(secondElement);
}
for(int i=10;i<60;++i) {
secondElement = doc.createElement("second");
XMLUtils.appendNewElement(doc, secondElement, "value", i);
secondsElement.appendChild(secondElement);
}
return secondsElement;
}
return null;
}
}