]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/acr/xml/XmlNormalizer.java
Introduce CMS JShell
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / acr / xml / XmlNormalizer.java
1 package org.argeo.cms.acr.xml;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.OutputStream;
7 import java.nio.file.DirectoryStream;
8 import java.nio.file.Files;
9 import java.nio.file.Path;
10 import java.nio.file.Paths;
11
12 import javax.xml.parsers.DocumentBuilder;
13 import javax.xml.parsers.DocumentBuilderFactory;
14 import javax.xml.parsers.ParserConfigurationException;
15 import javax.xml.transform.OutputKeys;
16 import javax.xml.transform.Result;
17 import javax.xml.transform.Source;
18 import javax.xml.transform.Transformer;
19 import javax.xml.transform.TransformerException;
20 import javax.xml.transform.TransformerFactory;
21 import javax.xml.transform.TransformerFactoryConfigurationError;
22 import javax.xml.transform.dom.DOMResult;
23 import javax.xml.transform.dom.DOMSource;
24 import javax.xml.transform.stream.StreamResult;
25 import javax.xml.transform.stream.StreamSource;
26
27 import org.w3c.dom.DOMException;
28 import org.w3c.dom.Document;
29 import org.xml.sax.SAXException;
30
31 /**
32 * Consistently normalises an XML in order to ease diff (typically in a
33 * versioning system).
34 */
35 public class XmlNormalizer {
36 // private final static Logger logger = System.getLogger(XmlNormalizer.class.getName());
37
38 private DocumentBuilder documentBuilder;
39 private TransformerFactory transformerFactory;
40
41 private DOMSource stripSpaceXsl;
42
43 public XmlNormalizer() {
44 this(2);
45 }
46
47 public XmlNormalizer(int indent) {
48 try {
49 documentBuilder = DocumentBuilderFactory.newNSInstance().newDocumentBuilder();
50 transformerFactory = TransformerFactory.newInstance();
51 transformerFactory.setAttribute("indent-number", indent);
52 try (InputStream in = XmlNormalizer.class.getResourceAsStream("stripSpaces.xsl")) {
53 DOMResult result = new DOMResult();
54 transformerFactory.newTransformer().transform(new StreamSource(in), result);
55 stripSpaceXsl = new DOMSource(result.getNode());
56 }
57 } catch (ParserConfigurationException | TransformerFactoryConfigurationError | TransformerException
58 | IOException e) {
59 throw new IllegalStateException("Cannot initialise document builder and transformer", e);
60 }
61 }
62
63 public void normalizeXmlFiles(DirectoryStream<Path> ds) throws IOException {
64 for (Path path : ds) {
65 normalizeXmlFile(path);
66 }
67 }
68
69 public void normalizeXmlFile(Path path) throws IOException {
70 byte[] bytes = Files.readAllBytes(path);
71 try (ByteArrayInputStream in = new ByteArrayInputStream(bytes);
72 OutputStream out = Files.newOutputStream(path)) {
73 normalizeAndIndent(in, out);
74 // logger.log(Level.DEBUG, () -> "Normalized XML " + path);
75 }
76 }
77
78 public void normalizeAndIndent(Source source, Result result) {
79 try {
80 Transformer transformer = transformerFactory.newTransformer(stripSpaceXsl);
81 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
82 // transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
83 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
84
85 transformer.transform(source, result);
86 } catch (TransformerException e) {
87 throw new RuntimeException("Cannot strip space from " + source, e);
88 }
89 }
90
91 public void normalizeAndIndent(InputStream in, OutputStream out) throws IOException {
92 try {
93 Document document = documentBuilder.parse(in);
94
95 // clear whitespaces outside tags
96 document.normalize();
97 // XPath xPath = XPathFactory.newInstance().newXPath();
98 // NodeList nodeList = (NodeList) xPath.evaluate("//text()[normalize-space()='']", document,
99 // XPathConstants.NODESET);
100 //
101 // for (int i = 0; i < nodeList.getLength(); ++i) {
102 // Node node = nodeList.item(i);
103 // node.getParentNode().removeChild(node);
104 // }
105
106 normalizeAndIndent(new DOMSource(document), new StreamResult(out));
107 } catch (DOMException | IllegalArgumentException | SAXException | TransformerFactoryConfigurationError e) {
108 throw new RuntimeException("Cannot normalise and indent XML", e);
109 }
110 }
111
112 public static void print(Source source, int indent) {
113 XmlNormalizer xmlNormalizer = new XmlNormalizer(indent);
114 xmlNormalizer.normalizeAndIndent(source, new StreamResult(System.out));
115 }
116
117 public static void print(Source source) {
118 print(source, 2);
119 }
120
121 public static void main(String[] args) throws IOException {
122 Path dir = Paths.get(args[0]);
123 XmlNormalizer xmlNormalizer = new XmlNormalizer();
124 DirectoryStream<Path> ds = Files.newDirectoryStream(dir, "*.svg");
125 xmlNormalizer.normalizeXmlFiles(ds);
126
127 }
128 }