All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.peterphi.std.util.DOMUtils Maven / Gradle / Ivy

There is a newer version: 10.1.5
Show newest version
package com.peterphi.std.util;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.ref.SoftReference;

public class DOMUtils
{
	private static SoftReference DOCUMENT_BUILDER_FACTORY = new SoftReference<>(null);
	private static final int DEFAULT_INDENT = 2;

	private DOMUtils()
	{
	}


	private static DocumentBuilderFactory createDocumentBuilderFactory()
	{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

		factory.setNamespaceAware(true);

		return factory;
	}


	/**
	 * Create a new (namespace-aware) DocumentBuilder
	 *
	 * @return
	 */
	public static DocumentBuilder createDocumentBuilder()
	{
		try
		{
			DocumentBuilderFactory factory = DOCUMENT_BUILDER_FACTORY.get();

			if (factory == null)
			{
				factory = createDocumentBuilderFactory();

				DOCUMENT_BUILDER_FACTORY = new SoftReference<>(factory);
			}

			return factory.newDocumentBuilder();
		}
		catch (ParserConfigurationException e)
		{
			throw new RuntimeException("Error creating DocumentBuilder: " + e.getMessage(), e);
		}
	}


	public static Document parse(File file)
	{
		if (file == null)
			throw new IllegalArgumentException("Must provide non-null XML input to parse!");

		try (FileInputStream fis = new FileInputStream(file))
		{
			return parse(fis);
		}
		catch (IOException e)
		{
			throw new RuntimeException("Error parsing xml: " + e.getMessage(), e);
		}
	}


	public static Document parse(String xml)
	{
		if (xml == null)
			throw new IllegalArgumentException("Must provide non-null XML input to parse!");

		return parse(new StringReader(xml));
	}


	public static Document parse(InputStream xml)
	{
		if (xml == null)
			throw new IllegalArgumentException("Must provide non-null XML input to parse!");

		return parse(new InputSource(xml));
	}


	public static Document parse(Reader xml)
	{
		if (xml == null)
			throw new IllegalArgumentException("Must provide non-null XML input to parse!");

		return parse(new InputSource(xml));
	}


	public static Document parse(InputSource src)
	{
		if (src == null)
			throw new IllegalArgumentException("Must provide non-null XML input to parse!");

		DocumentBuilder documentBuilder = createDocumentBuilder();
		try
		{
			return documentBuilder.parse(src);
		}
		catch (SAXException e)
		{
			throw new RuntimeException("Error parsing xml: " + e.getMessage(), e);
		}
		catch (IOException e)
		{
			throw new RuntimeException("Error parsing xml: " + e.getMessage(), e);
		}
	}


	public static String serialise(Node n)
	{
		StringWriter writer = new StringWriter(1024);

		serialise(n, writer);

		return writer.toString();
	}


	public static byte[] serialiseBytes(Node n)
	{
		ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);

		serialise(n, bos);

		return bos.toByteArray();
	}


	public static void serialise(Node n, StreamResult result)
	{
		if (n == null)
			throw new IllegalArgumentException("Must provide non-null XML node to serialise!");
		if (result == null)
			throw new IllegalArgumentException("Must provide non-null output to serialise to!");

		try
		{
			Transformer transform = TransformerFactory.newInstance().newTransformer();
			transform.transform(new DOMSource(n), result);
		}
		catch (TransformerConfigurationException e)
		{
			throw new RuntimeException("Error serialising node: " + e.getMessage(), e);
		}
		catch (TransformerException e)
		{
			throw new RuntimeException("Error serialising node: " + e.getMessage(), e);
		}
	}


	public static void serialise(Node n, OutputStream os)
	{
		if (n == null)
			throw new IllegalArgumentException("Must provide non-null XML node to serialise!");
		if (os == null)
			throw new IllegalArgumentException("Must provide non-null output to serialise to!");

		serialise(n, new StreamResult(os));
	}


	public static void serialise(Node n, Writer writer)
	{
		if (n == null)
			throw new IllegalArgumentException("Must provide non-null XML node to serialise!");
		if (writer == null)
			throw new IllegalArgumentException("Must provide non-null output to serialise to!");

		serialise(n, new StreamResult(writer));
	}


	public static void serialise(Node n, File file)
	{
		if (n == null)
			throw new IllegalArgumentException("Must provide non-null XML node to serialise!");
		if (file == null)
			throw new IllegalArgumentException("Must provide non-null File to serialise to!");

		serialise(n, new StreamResult(file));
	}


	/**
	 * Serialise the provided Node to a pretty-printed String with the default indent settings
	 *
	 * @param source the input Node
	 *
	 * @return
	 */
	public static String pretty(final Node source)
	{
		return pretty(new DOMSource(source));
	}


	/**
	 * Serialise the provided source to a pretty-printed String with the default indent settings
	 *
	 * @param source the input Source
	 */
	public static String pretty(final Source source)
	{
		StreamResult result = new StreamResult(new StringWriter());

		pretty(source, result);

		return result.getWriter().toString();
	}


	/**
	 * Serialise the provided source to the provided destination, pretty-printing with the default indent settings
	 *
	 * @param input the source
	 * @param output the destination
	 */
	public static void pretty(final Source input, final StreamResult output)
	{
		try
		{
			// Configure transformer
			Transformer transformer = TransformerFactory.newInstance().newTransformer();

			transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
			transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", Integer.toString(DEFAULT_INDENT));

			transformer.transform(input, output);
		}
		catch (Throwable t)
		{
			throw new RuntimeException("Error during pretty-print operation", t);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy