import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;

import org.xml.sax.helpers.DefaultHandler;

import org.xml.sax.Attributes;

/* For SAX parsing, we need to create a class which implements org.xml.sax.ContendHandler interface.
   org.xml.sax.helpers.DefaultHandler is a convenience class which provides the default implementations
   for the ContentHandler's methods. We can extend that class with our implementation (this class) in which
   we override the superclass' desired methods. */

public class SAXParsingExample extends DefaultHandler {

	// the indent variable is used to keep track of the current indendation for printing the elements etc.
	private int indent;
	
    public SAXParsingExample() {
    	this.indent = 0;
    }

    public static void main(String args[]) {
    	
		// Create an instance of this class for handling the SAX events
		SAXParsingExample example = new SAXParsingExample();
		
		// Create first a SAXParserFactory object
		SAXParserFactory spf = SAXParserFactory.newInstance();
		try {
			
		    // Then you can create a SAX-parser
		    SAXParser docParser = spf.newSAXParser();
		    
		    // When parse() method is called parser starts parsing the document
		    // and calls automatically methods like startElement
		    docParser.parse("file.xml", example);
		    
		}
		catch(Exception e) { 
		    System.out.println("Error: "+e.getMessage());
		}
    }

	// The overridden methods for SAX events
	
	// This method is called when an element is found
	public void startElement(String namespaceUri, String localName, 
	                         String qName, Attributes attributes) {
		
		// Print the indentation and the element name
		for (int i=0; i<this.indent; i++)
			System.out.print(" ");
		System.out.println("Element "+qName+":");
		
		// The child contents of this element are indentated
		this.indent++;
		
		// Print the attributes of this element
		for (int j=0; j<attributes.getLength(); j++) {
			for (int i=0; i<this.indent; i++)
	    		System.out.print(" ");
	    	System.out.println("Attribute: "+attributes.getQName(j)+"="+attributes.getValue(j));
		}
	}
	
	//  This method is called when an element is ended
	public void endElement(String namespaceUri, String localName, 
	        String qName) {
		
		// Handle the correct indentation
		this.indent--;
	}
	
	// This method is called when a character sequence is found
	public void characters(char[] ch, int start, int length) {
		String text = "";
		// Get the text content
		for (int i = start; i<start+length; i++)
			text += ch[i];
		
		// If the text content doesn't contain only whitespace, let's print it
		if (!text.trim().equals("")) {
			for (int i=0; i<this.indent; i++)
	    		System.out.print(" ");
			System.out.println("Text content: "+text);
		}
	}
}