/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xwiki.rendering.wikimodel.xml;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
/**
* This class contains various utility methods used to manipulate with DOM
* nodes.
*
* @version $Id: 95df085a81a79c308aa4330bbcc694a55b37ca83 $
* @since 4.0M1
*/
public class XmlUtil
{
public static void formatXML(
Document xml,
Document xsl,
URIResolver resolver,
Writer output) throws Exception
{
try {
DOMSource xslSource = new DOMSource(xsl);
DOMSource xmlSource = new DOMSource(xml);
Result result = new StreamResult(output);
formatXML(xmlSource, xslSource, resolver, result);
} finally {
output.close();
}
}
public static void formatXML(Document xml, Document xsl, Writer output)
throws Exception
{
formatXML(xml, xsl, null, output);
}
public static void formatXML(
Reader xml,
Reader xsl,
URIResolver resolver,
Writer output) throws Exception
{
try {
try {
try {
Source xmlSource = new SAXSource(new InputSource(xml));
Source xslSource = new SAXSource(new InputSource(xsl));
Result result = new StreamResult(output);
formatXML(xmlSource, xslSource, resolver, result);
} finally {
output.close();
}
} finally {
xsl.close();
}
} finally {
xml.close();
}
}
public static void formatXML(Reader xml, Reader xsl, Writer output)
throws Exception
{
formatXML(xml, xsl, null, output);
}
public static void formatXML(
Source xmlSource,
Source xslSource,
URIResolver resolver,
Result result)
throws TransformerFactoryConfigurationError,
TransformerConfigurationException,
TransformerException
{
TransformerFactory factory = TransformerFactory.newInstance();
Templates t = factory.newTemplates(xslSource);
Transformer transformer = t.newTransformer();
if (resolver != null) {
transformer.setURIResolver(resolver);
}
transformer.transform(xmlSource, result);
}
/**
* Creates and returns an new document builder factory. This method tries to
* configure the namespace support for the builder. If the underlying parser
* does not support namespaces then this method returns a simple
* DocumentBuilder object.
*
* @return a new document builder
*/
private static DocumentBuilder getDocumentBuilder()
throws ParserConfigurationException
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true); // never forget this!
try {
factory.setFeature("http://xml.org/sax/features/namespaces", true);
} catch (Throwable t) {
// Just skip it...
}
DocumentBuilder builder = factory.newDocumentBuilder();
return builder;
}
public static String lookupNamespaceURI(Node root, String specifiedPrefix)
{
if (root == null) {
return null;
}
if (root.hasAttributes()) {
NamedNodeMap nnm = root.getAttributes();
for (int i = 0; i < nnm.getLength(); i++) {
Node n = nnm.item(i);
if (("xmlns".equals(n.getPrefix()) && specifiedPrefix.equals(n
.getNodeName()))
|| ("xmlns:" + specifiedPrefix).equals(n.getNodeName()))
{
return n.getNodeValue();
}
}
}
return lookupNamespaceURI(root.getParentNode(), specifiedPrefix);
}
/**
* Returns a new copy of the given node using the specified document as a
* factory for new nodes.
*
* @param doc the document used as a factory for new nodes
* @param node the node to copy
* @return a new copy of the given node using the specified document as a
* factory for new nodes.
*/
@SuppressWarnings("unchecked")
public static <E extends Node> E newCopy(Document doc, E node)
{
E result = (E) node.cloneNode(true);
return (E) doc.adoptNode(result);
}
/**
* Creates and returns a new empty DOM document.
*
* @return a newly created DOM document
*/
public static Document newDocument() throws ParserConfigurationException
{
DocumentBuilder builder = getDocumentBuilder();
return builder.newDocument();
}
public static Element newTemplate(String xml) throws Exception
{
Document doc = readXML(xml);
return doc.getDocumentElement();
}
/**
* Parses the given input stream and returns the corresponding desirialized
* XML document.
*
* @param input the input stream containing the serialized XML document
* @return the deserialized DOM document
*/
public static Document readXML(InputStream input) throws Exception
{
return readXML(new InputStreamReader(input, "UTF-8"));
}
/**
* Parses the given input stream and returns the corresponding desirialized
* XML document.
*
* @param reader the reader containing the serialized XML document
* @return the deserialized DOM document
*/
public static Document readXML(Reader reader) throws Exception
{
try {
DocumentBuilder builder = getDocumentBuilder();
InputSource source = new InputSource(reader);
Document doc = builder.parse(source);
return doc;
} finally {
reader.close();
}
}
public static Document readXML(String str) throws Exception
{
if (str == null) {
return null;
}
Reader reader = new StringReader(str);
return readXML(reader);
}
public static String write(Document doc) throws Exception
{
return write(doc.getDocumentElement());
}
public static String write(Element e) throws Exception
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
write(e, baos);
return new String(baos.toByteArray(), "UTF-8");
}
public static void write(Element root, OutputStream os) throws Exception
{
Writer writer = new OutputStreamWriter(os);
write(root, writer);
}
public static void write(Element root, Writer writer)
throws TransformerConfigurationException,
TransformerFactoryConfigurationError,
TransformerException
{
Source input = new DOMSource(root);
write(input, writer);
}
public static void write(Reader reader, XMLReader parser, Result output)
throws TransformerConfigurationException,
TransformerFactoryConfigurationError,
TransformerException
{
SAXSource input = new SAXSource();
InputSource inputSource = new InputSource();
inputSource.setCharacterStream(reader);
input.setInputSource(inputSource);
input.setXMLReader(parser);
write(input, output);
}
public static void write(Reader reader, XMLReader parser, Writer writer)
throws TransformerConfigurationException,
TransformerFactoryConfigurationError,
TransformerException
{
Result output = new StreamResult(writer);
write(reader, parser, output);
}
public static void write(Source input, Result output)
throws TransformerConfigurationException,
TransformerFactoryConfigurationError,
TransformerException
{
write(input, output, true);
}
public static void write(Source input, Result output, boolean indent)
throws TransformerConfigurationException,
TransformerFactoryConfigurationError,
TransformerException
{
boolean omitxmldeclaration = true;
Transformer idTransform = TransformerFactory
.newInstance()
.newTransformer();
if (omitxmldeclaration) {
idTransform.setOutputProperty("omit-xml-declaration", "yes");
}
idTransform.setOutputProperty("encoding", "UTF-8");
if (indent) {
idTransform.setOutputProperty("indent", "yes");
try {
idTransform.setOutputProperty(
"{http://xml.apache.org/xslt}indent-amount",
"4");
} catch (Exception e) {
//
}
}
idTransform.transform(input, output);
}
public static void write(Source input, Writer writer)
throws TransformerConfigurationException,
TransformerFactoryConfigurationError,
TransformerException
{
Result output = new StreamResult(writer);
write(input, output);
}
}