package org.uli.xmldiff; import java.io.PrintStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Reader; import java.io.InputStreamReader; import java.util.List; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.SAXException; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import org.custommonkey.xmlunit.Diff; import org.custommonkey.xmlunit.Difference; import org.custommonkey.xmlunit.DetailedDiff; import org.custommonkey.xmlunit.XMLUnit; import org.uli.util.MyOptionBuilder; public class XmlDiff { static private final String NAME="xmldiff"; public static void main(String[] args) { int exitCode = run(args); if (exitCode != 0) { System.exit(exitCode); } } private final static void printHelp(PrintStream out, Options options, ParseException e) { if (e != null) { out.println(NAME + ": Command line error - " + e.getMessage()); } HelpFormatter helpFormatter = new HelpFormatter(); helpFormatter.printHelp(NAME, options); } private final static Reader getReader(String filename) throws FileNotFoundException { File f = new File(filename); Reader r = new InputStreamReader(new FileInputStream(f)); return r; } // http://www.programcreek.com/2013/08/ignoring-dtd-in-xmlunit/ private final static void disableXmlValidation() { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); try { dbf.setFeature("http://xml.org/sax/features/namespaces", false); dbf.setFeature("http://xml.org/sax/features/validation", false); dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false); dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); } catch (ParserConfigurationException e) { e.printStackTrace(); } XMLUnit.setTestDocumentBuilderFactory(dbf); XMLUnit.setControlDocumentBuilderFactory(dbf); XMLUnit.setIgnoreAttributeOrder(true); XMLUnit.setIgnoreComments(true); XMLUnit.setNormalizeWhitespace(true); XMLUnit.setNormalize(true); } public static int run(String[] args) { disableXmlValidation(); Options options = new Options(); Option h = MyOptionBuilder.init().withLongOpt("help").withDescription("print help").create("h"); Option v = MyOptionBuilder.init().withLongOpt("verbose").withDescription("create debug output").create("v"); options.addOption(h); options.addOption(v); int exitCode = 0; boolean fVerbose = false; boolean fHelp = false; for (;;) { CommandLineParser commandLineParser = new PosixParser(); try { CommandLine commandLine = commandLineParser.parse(options, args); fVerbose = commandLine.hasOption("v"); fHelp = commandLine.hasOption("h"); if (fHelp) { printHelp(System.out, options, null); break; } String[] remainingArgs = commandLine.getArgs(); if (remainingArgs.length != 2) { printHelp(System.err, options, null); System.err.println("Expecting 2 command line arguments - got "+remainingArgs.length); exitCode = 11; break; } Diff diff = new Diff(getReader(remainingArgs[0]), getReader(remainingArgs[1])); if (! diff.similar()) { DetailedDiff details = new DetailedDiff(diff); //for (Difference d : (List<Difference>) details.getAllDifferences()) { for (Object o : details.getAllDifferences()) { Difference d = (Difference) o; System.out.println(d.toString()); exitCode=1; } } break; } catch (ParseException e) { System.err.println(NAME + ": Command line error - " + e.getMessage()); HelpFormatter helpFormatter = new HelpFormatter(); helpFormatter.printHelp(NAME, options); exitCode = 10; break; } catch (SAXException e) { System.err.println(e); exitCode = 10; break; } catch (IOException e) { System.err.println(e); exitCode = 10; break; } } return exitCode; } }