/* ==================================================================== | |
Licensed to the Apache Software Foundation (ASF) under one or more | |
contributor license agreements. See the NOTICE file distributed with | |
this work for additional information regarding copyright ownership. | |
The ASF licenses this file to You under the Apache License, Version 2.0 | |
(the "License"); you may not use this file except in compliance with | |
the License. You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
==================================================================== */ | |
package org.apache.poi.dev; | |
import java.io.BufferedOutputStream; | |
import java.io.File; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.OutputStream; | |
import java.util.Enumeration; | |
import java.util.zip.ZipEntry; | |
import java.util.zip.ZipException; | |
import java.util.zip.ZipFile; | |
import java.util.zip.ZipOutputStream; | |
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.dom.DOMSource; | |
import javax.xml.transform.stream.StreamResult; | |
import org.apache.poi.openxml4j.opc.internal.ZipHelper; | |
import org.apache.poi.util.IOUtils; | |
import org.w3c.dom.Document; | |
import org.xml.sax.InputSource; | |
/** | |
* Reads a zipped OOXML file and produces a copy with the included | |
* pretty-printed XML files. | |
* | |
* This is useful for comparing OOXML files produced by different tools as the often | |
* use different formatting of the XML. | |
*/ | |
public class OOXMLPrettyPrint { | |
private final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); | |
private final DocumentBuilder documentBuilder; | |
public OOXMLPrettyPrint() throws ParserConfigurationException { | |
documentBuilder = documentBuilderFactory.newDocumentBuilder(); | |
} | |
public static void main(String[] args) throws Exception { | |
if(args.length <= 1 || args.length % 2 != 0) { | |
System.err.println("Use:"); | |
System.err.println("\tjava OOXMLPrettyPrint [<filename> <outfilename>] ..."); | |
System.exit(1); | |
} | |
for(int i = 0;i < args.length;i+=2) { | |
File f = new File(args[i]); | |
if(! f.exists()) { | |
System.err.println("Error, file not found!"); | |
System.err.println("\t" + f.toString()); | |
System.exit(2); | |
} | |
handleFile(f, new File(args[i+1])); | |
} | |
System.out.println("Done."); | |
} | |
private static void handleFile(File file, File outFile) throws ZipException, | |
IOException, TransformerException, ParserConfigurationException { | |
System.out.println("Reading zip-file " + file + " and writing pretty-printed XML to " + outFile); | |
ZipFile zipFile = ZipHelper.openZipFile(file); | |
try { | |
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outFile))); | |
try { | |
new OOXMLPrettyPrint().handle(zipFile, out); | |
} finally { | |
out.close(); | |
} | |
} finally { | |
zipFile.close(); | |
System.out.println(); | |
} | |
} | |
private void handle(ZipFile file, ZipOutputStream out) throws IOException, TransformerException { | |
Enumeration<? extends ZipEntry> entries = file.entries(); | |
while(entries.hasMoreElements()) { | |
ZipEntry entry = entries.nextElement(); | |
String name = entry.getName(); | |
out.putNextEntry(new ZipEntry(name)); | |
try { | |
if(name.endsWith(".xml") || name.endsWith(".rels")) { | |
Document document = documentBuilder.parse(new InputSource(file.getInputStream(entry))); | |
document.setXmlStandalone(true); | |
pretty(document, out, 2); | |
} else { | |
System.out.println("Not pretty-printing non-XML file " + name); | |
IOUtils.copy(file.getInputStream(entry), out); | |
} | |
} catch (Exception e) { | |
throw new IOException("While handling entry " + name, e); | |
} finally { | |
out.closeEntry(); | |
} | |
System.out.print("."); | |
} | |
} | |
private static void pretty(Document document, OutputStream outputStream, int indent) throws TransformerException { | |
TransformerFactory transformerFactory = TransformerFactory.newInstance(); | |
Transformer transformer = transformerFactory.newTransformer(); | |
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); | |
if (indent > 0) { | |
// set properties to indent the resulting XML nicely | |
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); | |
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", Integer.toString(indent)); | |
} | |
Result result = new StreamResult(outputStream); | |
Source source = new DOMSource(document); | |
transformer.transform(source, result); | |
} | |
} |