summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/util/XmlHelper.java
blob: 70c5be816478b4f7920ca637847df9bde560419c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package org.openslx.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XmlHelper
{
	private final static Logger LOGGER = Logger.getLogger( XmlHelper.class );

	// TODO check thread-safety
	public static final XPath XPath = XPathFactory.newInstance().newXPath();
	private static DocumentBuilder dBuilder;
	static {
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		dbFactory.setIgnoringComments( true );
		try {
			dBuilder = dbFactory.newDocumentBuilder();
		} catch ( ParserConfigurationException e ) {
			LOGGER.error( "Failed to initalize DOM parser with default configurations." );
		}
	}

	public static Document parseDocumentFromStream( InputStream is )
	{
		Document doc = null;
		try {
			doc = dBuilder.parse( is );
		} catch ( SAXException | IOException e ) {
			LOGGER.error( "Failed to parse input stream to document." );
		}
		if ( doc == null )
			return null;
		doc.getDocumentElement().normalize();
		return doc;
	}

	public static Document removeFormattingNodes( Document doc )
	{
		NodeList empty;
		try {
			empty = (NodeList)XPath.evaluate( "//text()[normalize-space(.) = '']",
					doc, XPathConstants.NODESET );
		} catch ( XPathExpressionException e ) {
			LOGGER.error( "Bad XPath expression to find all empty text nodes." );
			return null;
		}

		for ( int i = 0; i < empty.getLength(); i++ ) {
			Node node = empty.item( i );
			node.getParentNode().removeChild( node );
		}
		return doc;
	}

	public static String getUnformattedXml( InputStream is )
	{
		// prune empty text nodes, essentially removing all formatting
		Document doc = parseDocumentFromStream( is );
		return getXmlFromDocument( removeFormattingNodes( doc ), false );
	}

	public static String getFormattedXml( InputStream is )
	{
		Document doc = parseDocumentFromStream( is );
		return getXmlFromDocument( doc, true );
	}

	public static String getXmlFromDocument( Document doc, boolean humanReadable )
	{
		try {
			StringWriter writer = new StringWriter();
			TransformerFactory tf = TransformerFactory.newInstance();
			Transformer transformer = tf.newTransformer();
			transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "no" );
			transformer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
			transformer.setOutputProperty( OutputKeys.METHOD, "xml" );
			if ( humanReadable ) {
				transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
				transformer.setOutputProperty( "{http://xml.apache.org/xslt}indent-amount", "2" );
			}
			transformer.transform( new DOMSource( doc ), new StreamResult( writer ) );
			return writer.toString();
		} catch ( Exception ex ) {
			LOGGER.error( "Failed to transform XML to String: ", ex );
			return null;
		}
	}
}