package parsers;

import java.util.*;
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

/*	SAXParser uses a SAX parser from the Apache Software Foundation.  It parses the
 *	document and stores the tags and text in a vector.  When the end tag is read, 
 *	it displays all the tags stored in the vector on the screen.
*/
public class SAXParser
{
	public static void main (String [] args)
	{
		try
		{
			BufferedReader stdin = new BufferedReader (new InputStreamReader (System.in));
			System.out.println ("Enter XML document to parse: ");
			String xmlDoc = stdin.readLine ();
			ParseDocument parseDoc = new ParseDocument ();
			parseDoc.doParse (xmlDoc);
		} catch (IOException e) {System.out.println ("IO Exception");}
	} // main
} // SAXParser

/* ParseDocument parses the document and stores elements and text in a vector.
 * When the end tag is read, it displays the contents of the vector on the screen.
*/
class ParseDocument
{
	private Vector tokens = new Vector (50);
	
	// doParse gets a parser, adds a content handler, and parses the document.
	public void doParse (String document)
	{	
		final String VALIDATION_FEATURE_ID = "http://xml.org/sax/features/validation";
		
		try 
    	{
    		XMLReader parser = XMLReaderFactory.createXMLReader(
        		"org.apache.xerces.parsers.SAXParser");
			parser.setFeature(VALIDATION_FEATURE_ID, true);
		
			ContentHandler handler = new ElementExtractor();
			parser.setContentHandler(handler);	
			parser.parse(document);		
		} catch (SAXException e) 
		{	System.err.println("Warning: Parser does not support validation feature .");}
		catch (Exception e) {System.err.println(e);}	
	} // doParse

	// ElementExtractor receives call backs from the parser for text and elements.
	class ElementExtractor extends DefaultHandler
	{
		// characters receives all the text in the xml document.
		public void characters(char[] text, int start, int length) throws SAXException 
		{
		
			String word = "";
			word = word.copyValueOf (text, start, length);
			Node textNode = new Node ("text", word);
			tokens.add (textNode);
		} // characters
		
		// startElement picks out each start element and stores it in the vector.
		public void startElement(String namespaceURI, String localName, String qName, 
									Attributes atts) throws SAXException
		{	
			Node startNode, attrNode;
			startNode = new Node ("startTag", localName);
			tokens.add (startNode);
			for (int count = 0; count < atts.getLength (); count ++)
			{
				String value = atts.getLocalName (count) + " = " + atts.getValue (count);
				attrNode = new Node ("attr", value);
				tokens.add (attrNode);
			}
		} // startElement
	
		// endElement picks out each end element and stores it in the vector.
		public void endElement(String namespaceURI, String localName, String qName)
                throws SAXException
		{
			Node endNode = new Node ("endTag", localName);
			tokens.add (endNode);
		} // endElement
	
		/*	endDocument reads the last tag in the document and then displays all the 
			tokens in the vector on the screen. 
		*/
		public void endDocument() throws SAXException
		{
			for (int count = 0; count < tokens.size (); count ++)
			{
				Node token = (Node)tokens.elementAt (count);
      			token.displayToken ();
			}
		} // endDocument
	} // ElementExtractor
} // ParseDocument

// The Node class is used to store each token returned by the parser.
class Node
{
	private String tagType, tagValue;
	
	Node (String type, String value)
	{
		tagType = type;
		tagValue = value;
	} // constructor
	
	protected String getType () {return tagType;}
	
	protected String getValue () {return tagValue;}
	
	protected void displayToken () {System.out.println (tagType + "  " + tagValue);}
} // Node


