// $Id: Xslt.java,v 1.2 2004/05/19 14:32:52 ramsdell Exp $ // // A simple main routine for XSLT transformations and XML validation. // // Copyright (c) 2002. The MITRE Corporation (http://www.mitre.org/). // All rights reserved. // The SIMP Service comes with ABSOLUTELY NO WARRANTY. // See the SIMP Service License Agreement for details. // package org.mitre.simp.tools; import java.util.LinkedList; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParser; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.*; import javax.xml.transform.*; import javax.xml.transform.stream.*; public class Xslt implements ErrorHandler { // when true, print a stack trace when an exception is raised. private static boolean debug = false; private static boolean warnings = false; public static final String VALIDATION_FEATURE_ID = "http://xml.org/sax/features/validation"; public static final String NAMESPACE_PREFIXES_FEATURE_ID = "http://xml.org/sax/features/namespace-prefixes"; private final String input; // Instances of this class are used to report errors // during validation. private Xslt(String input) { this.input = input; } public void error(SAXParseException spe) { SAXParseError("Error", spe); } public void fatalError(SAXParseException spe) { SAXParseError("Fatal Error", spe); System.exit(1); } public void warning(SAXParseException spe) { if (warnings) SAXParseError("Warning", spe); } private void SAXParseError(String level, SAXParseException spe) { String msg = input + ":" + spe.getLineNumber() + ":" + spe.getColumnNumber() + ": SAX " + level + ": " + spe.getMessage(); System.err.println(msg); if (debug) spe.printStackTrace(); } /** * Entry point for transformations and validations. * Use the -h switch to see command line options. */ public static void main(String[] args) { LinkedList params = new LinkedList(); int offset = 0; while (offset < args.length && args[offset].length() > 1 && args[offset].charAt(0) == '-') { String flag = args[offset++]; switch (flag.charAt(1)) { case 'd': if ("-debug".startsWith(flag)) { debug = true; warnings = true; } else { badFlag(flag); return; } break; case 'w': if ("-warnings".startsWith(flag)) { warnings = true; } else { badFlag(flag); return; } break; case 'h': if ("-help".startsWith(flag)) usage(); else badFlag(flag); return; case 'P': if (flag.indexOf('=') < 3) { badFlag(flag); return; } params.add(flag); break; default: badFlag(flag); return; } } String[] param = (String[])params.toArray(new String[0]); switch (args.length - offset) { case 1: if (param.length > 0) { System.err.println("Parameters apply only to transformations"); usage(); return; } performValidation(args[offset]); return; case 2: performTransform(args[offset], args[offset + 1], null, param); return; case 3: performTransform(args[offset], args[offset + 1], args[offset + 2], param); return; default: System.err.println("Bad argument count"); usage(); } } private static void usage() { String cmd = " java " + Xslt.class.getName() + " [ options ] "; String[] msg = { "Transformer Usage:", cmd + "stylesheet input [ output ]", "Validator Usage:", cmd + "input", "", "where options include:", " -warnings print warnings", " -debug print detailed error messages", " -help print this help message", " -P= set a transformer parameter", "", "When stylesheet is \"-\", the source is searched for it.", }; for (int i = 0; i < msg.length; i++) System.err.println(msg[i]); } private static void badFlag(String flag) { System.err.println("Unrecognized flag: " + flag); usage(); } private static void fatalError(String msg, Throwable t) { System.err.print(msg + ": "); if (debug) { System.err.println(); t.printStackTrace(); } else System.err.println(t.getMessage()); System.exit(1); } /** * Validate XML in named input file. */ public static void performValidation(String inputFileName) { XMLReader reader = getXMLReader(); reader.setErrorHandler(new Xslt(inputFileName)); requestFeature(reader, VALIDATION_FEATURE_ID); requestFeature(reader, NAMESPACE_PREFIXES_FEATURE_ID); parseInput(reader, inputFileName); } private static XMLReader getXMLReader() { try { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); return parser.getXMLReader(); } catch (ParserConfigurationException pce) { fatalError("SAX parser configuration", pce); } catch (SAXException se) { fatalError("SAX parser creation", se); } return null; // Should never get here. } private static void requestFeature(XMLReader reader, String featureId) { try { reader.setFeature(featureId, true); } catch (SAXNotRecognizedException snre) { fatalError("Feature " + featureId + " not recognized", snre); } catch (SAXNotSupportedException snse) { fatalError("Feature " + featureId + " not supported", snse); } } private static void parseInput(XMLReader reader, String inputFileName) { try { reader.parse(new InputSource(inputFileName)); } catch (SAXException se) { fatalError("SAX error", se); } catch (FileNotFoundException fnfe) { fatalError("File not found: " + inputFileName, fnfe); } catch (IOException ioe) { fatalError("SAX I/O error in: " + inputFileName, ioe); } } /** * Transform input file as specified by the xslt file. * When the output file is null, the output is sent to * System.out. */ public static void performTransform(String xsltFileName, String inFileName, String outFileName, String[] param) { TransformerFactory factory = TransformerFactory.newInstance(); StreamSource in = new StreamSource(new File(inFileName)); Source xslt; if ("-".equals(xsltFileName)) { try { xslt = factory.getAssociatedStylesheet(in, null, null, null); } catch (TransformerConfigurationException tce) { String msg = "Failed getting style sheet from source"; fatalError(msg, tce); return; } } else xslt = new StreamSource(new File(xsltFileName)); if (xslt == null) { System.err.println("No style sheet was found in source"); System.exit(1); } StreamResult out; if (outFileName != null) out = new StreamResult(new File(outFileName)); else { out = new StreamResult(); out.setOutputStream(System.out); } try { Transformer tf = factory.newTransformer(xslt); for (int i = 0; i < param.length; i++) { String p = param[i]; int j = p.indexOf('='); tf.setParameter(p.substring(2, j), p.substring(j + 1)); } tf.transform(in, out); } catch (TransformerConfigurationException tce) { fatalError("Transformer configuration", tce); } catch (TransformerException te) { fatalError("Transformer", te); } } }