| /* ==================================================================== |
| 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.openxml4j.util.ZipSecureFile; |
| 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 { |
| // allow files with much lower inflation rate here as there is no risk of Zip Bomb attacks in this developer tool |
| ZipSecureFile.setMinInflateRatio(0.00001); |
| |
| 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); |
| 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); |
| } |
| } |