Tuesday, December 14, 2010

SaxParser example

Today I've had to analyse pretty big XML file, that I couldn't open in any editor without a hassle. Finally I've used comprehensive vim editor, which can handle anything without any problems to view it, but it was useless anyway, because the XML was completely not in human readable format. Then I've been looking for some solution to format it or just to display its structure and I've found this class from Oracle.

This is nice SaxParser example, but it has one drawback. It's completely useless for analysis, because it just prints the XML human unreadable as well. But after a little change we can have a better tool to display formatted data, writing the tree structure with values to the output:

import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Stack;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class Echo01 extends DefaultHandler {
 static private Writer out;
 
 public Stack stack = new Stack();

 public static void main(String[] argv) {
  if (argv.length != 1) {
   System.err.println("Usage: cmd filename");
   System.exit(1);
  }

  // Use an instance of ourselves as the SAX event handler
  DefaultHandler handler = new Echo01();

  // Use the default (non-validating) parser
  SAXParserFactory factory = SAXParserFactory.newInstance();

  try {
   // Set up output stream
   out = new OutputStreamWriter(System.out, "UTF8");

   // Parse the input
   SAXParser saxParser = factory.newSAXParser();
   saxParser.parse(new File(argv[0]), handler);
  } catch (Throwable t) {
   t.printStackTrace();
  }

  System.exit(0);
 }

 public void startDocument() throws SAXException {
 }

 public void endDocument() throws SAXException {
  try {
   nl();
   out.flush();
  } catch (IOException e) {
   throw new SAXException("I/O error", e);
  }
 }

 public void startElement(String namespaceURI, String sName, String qName, 
    Attributes attrs) throws SAXException {
  stack.push(sName);

  nl();
  for (int i = 0; i < stack.size(); i++)
   emit("  ");

  StringBuilder sb = new StringBuilder();
        for (int i = 0; i < attrs.getLength(); i++) {
            String aName = attrs.getLocalName(i); // Attr name 

            if ("".equals(aName)) {
                aName = attrs.getQName(i);
            }

            sb.append(aName + "=\"" + attrs.getValue(i) + "\"");
        }
        
  emit(qName+" ["+sb.toString()+"]: ");
 }

 public void endElement(String namespaceURI, String sName, String qName) 
 throws SAXException {
  stack.pop();
 }

 public void characters(char[] buf, int offset, int len) throws SAXException {
  String s = new String(buf, offset, len);
  emit(s);
 }

 private void emit(String s) throws SAXException {
  try {
   out.write(s);
   out.flush();
  } catch (IOException e) {
   throw new SAXException("I/O error", e);
  }
 }

 private void nl() throws SAXException {
  String lineEnd = System.getProperty("line.separator");

  try {
   out.write(lineEnd);
  } catch (IOException e) {
   throw new SAXException("I/O error", e);
  }
 }
}

No comments:

Post a Comment