// Sample Java program using SAX to validate, and output to the screen, // the contents of an XML file. // // Coded by Norman Jacobson, May 2007 // -- with much referencing to the Java SAX Tutorial, // java.sun.com/webservices/jaxp/dist/1.1/docs/tutorial/sax/index.html // Usage: via command line, issue "java XMLtoScreen " // Imports: // Use System.out() to print contents of XML file to screen import java.io.*; // Make interfaces for SAX available import org.xml.sax.*; // SAX is event-driven: when particular tokens are seen, the // appropriate event is triggered. DefaultHandler has empty // methods for all events; we'll overload the ones we need to use import org.xml.sax.helpers.DefaultHandler; // Provides class to produce a SAX parser--in Java terms, a parser factory import javax.xml.parsers.SAXParserFactory; // ParserConfigurationException is thrown if a parser of the requested type // cannot be provided import javax.xml.parsers.ParserConfigurationException; // What the facory returns to do the parsing import javax.xml.parsers.SAXParser; // XMLtoScreen provides appropriate methods to handle // SAX events generated while parsing the XML file public class XMLtoScreen extends DefaultHandler { // No indentation at start private int numberOfTabStops = 0; // Name of XML file to process private static String XMLFileName; // accept XML file name; print out contents and // an error message for each validation error encountered public static void main (String[] args) { // Process command line; if ill-formed, exit if (args.length != 1) { System.out.println("Usage: java XMLtoScreen "); System.exit(1); } // Process the file // // "When a start tag or end tag is encountered, the name of the tag is passed as a // String to the startElement or endElement method, as appropriate. When a start tag // is encountered, any attributes it defines are also passed in an Attributes list. // Characters found within the element are passed as an array of characters, along with // the number of characters (length) and an offset into the array that points to the first // character." // [Java SAX tutorial, java.sun.com/webservices/jaxp/dist/1.1/docs/tutorial/sax/2a_echo.html] // Set up a parser factory that validates the XML file as it's processed SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(true); SAXParser parser = null; try { // Make a SAX parser parser = factory.newSAXParser(); } catch (ParserConfigurationException e) { System.out.println("\nUnable to make a parse with given configuration!"); System.exit(1); } catch (SAXException e) { System.out.println("\nUnable to create parser factory!"); System.exit(1); } // Tell parser the file to process -- it's the one on the command line -- // and the event handler methods to use -- they are in this class XMLFileName = args[0].trim(); try { parser.parse(new File(XMLFileName), new XMLtoScreen()); } catch (IOException e) { System.out.println("\nCould not initialize parser!"); System.exit(1); } // We'll get here unless there is a parsing error -- // and if there is, we want serious info about it catch (SAXParseException e) { System.out.println("\nParsing error!\n" + " line = " + e.getLineNumber() + "\n" + " location = " + e.getSystemId()); System.out.println(" " + e.getMessage()); } // We'll get here if there is something else wrong catch (SAXException e) { System.out.println("SAX error: " + e); } } // Event handling routines // At start of document, note we've begun public void startDocument() throws SAXException { System.out.print("\n\n** Validating and printing " + XMLFileName + " **\n\n"); } // At end of document, note we're done public void endDocument() throws SAXException { System.out.println("\n** Done! **"); } // At the start of an element, indent, print that element as a label for the line public void startElement(String namespaceURI, //namespace (we don't use) String sName, // simple name (localName) String qName, // qualified name Attributes attrs) //attribute list throws SAXException { // The name may or may not be qualified; use whichever is present String elementName = sName; if (elementName.equals("")) elementName = qName; System.out.println(); ++numberOfTabStops; indent(numberOfTabStops); System.out.print(elementName.toUpperCase().trim() + ": "); // if attributes are present, get their names and list them // indent each new list if (attrs != null) { ++numberOfTabStops; System.out.println(); for (int i = 0; i < attrs.getLength(); i++) { // get its local or qualified name, whichever is present String attributeName = attrs.getLocalName(i); if (attributeName.equals("")) attributeName = attrs.getQName(i); indent(numberOfTabStops); System.out.print("--> " + attributeName.toLowerCase().trim() + ": "); System.out.println(attrs.getValue(i).trim()); } --numberOfTabStops; } } // At the end of an element, end the line, back off indentation public void endElement(String namespaceURI, //namespace (we're not using) String sName, // simple name (localName) String qName) // qualified name throws SAXException { System.out.println(); --numberOfTabStops; } // Write out the characters, if any, between the XML tags public void characters(char buf[], int offset, int len) throws SAXException { String thisCharacterGroup = new String(buf, offset, len).trim(); if (!thisCharacterGroup.equals("")) { ++numberOfTabStops; indent(numberOfTabStops); System.out.print(">" + thisCharacterGroup + "<"); --numberOfTabStops; } } // Indent given number of 'tab' stops // (used to make output a bit prettier) private void indent(int numberOfTabStops) { for (int i = 1; i <= numberOfTabStops; i++) System.out.print(" "); // indent is 4 spaces } }