########################################
  SAMPLE OF SAX PARSE 
  (JAVA & XML 2nd Edition, Chapter 3)
########################################

How to do?
1. create these 3 java source File
   SAXTreeViewer.java  ErrorHandler.java   ContentHandler.java
2. complie the source: 
   javac SAXTreeViewer.java
3. run the sample:  
   java SAXTreeViewer http://cvs01.yahoo.co.jp/alerts/test.xml
   (classpath=%classpath%; .\;)

========================================
SAXTreeViewer.java
========================================
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

// This is an XML book - no need for explicit Swing imports
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;

public class SAXTreeViewer extends JFrame {

    /** Default parser to use */
    private String vendorParserClass = 
        "org.apache.xerces.parsers.SAXParser";

    /** The base tree to render */
    private JTree jTree;

    /** Tree model to use */
    DefaultTreeModel defaultTreeModel;

    public SAXTreeViewer( ) {
        // Handle Swing setup
        super("SAX Tree Viewer");
        setSize(600, 450);
    }

    public void init(String xmlURI) throws IOException, SAXException {
        DefaultMutableTreeNode base = 
            new DefaultMutableTreeNode("XML Document: " + 
                xmlURI);
        
        // Build the tree model
        defaultTreeModel = new DefaultTreeModel(base);
        jTree = new JTree(defaultTreeModel);

        // Construct the tree hierarchy
        buildTree(defaultTreeModel, base, xmlURI);

        // Display the results
        getContentPane( ).add(new JScrollPane(jTree), 
            BorderLayout.CENTER);
    }

    public void buildTree(DefaultTreeModel treeModel, 
                          DefaultMutableTreeNode base, String xmlURI) 
        throws IOException, SAXException {

        // Create instances needed for parsing
        XMLReader reader = 
            XMLReaderFactory.createXMLReader(vendorParserClass);
        ContentHandler jTreeContentHandler = 
            new JTreeContentHandler(treeModel, base);
        ErrorHandler jTreeErrorHandler = new JTreeErrorHandler( );            

        // Register content handler
        reader.setContentHandler(jTreeContentHandler);

        // Register error handler
        reader.setErrorHandler(jTreeErrorHandler);

        // Parse
        InputSource inputSource = 
            new InputSource(xmlURI);
        reader.parse(inputSource);
    }

    public static void main(String[] args) {
        try {
            if (args.length != 1) {
                System.out.println(
                    "Usage: java javaxml2.SAXTreeViewer " +
                    "[XML Document URI]");
                System.exit(0);
            }
            SAXTreeViewer viewer = new SAXTreeViewer( );
            viewer.init(args[0]);
            viewer.setVisible(true);
        } catch (Exception e) {
            e.printStackTrace( );
        }
    }
}


class JTreeErrorHandler implements ErrorHandler {

     public void warning(SAXParseException exception)
        throws SAXException {
            
        System.out.println("**Parsing Warning**\n" +
                           "  Line:    " + 
                              exception.getLineNumber( ) + "\n" +
                           "  URI:     " + 
                              exception.getSystemId( ) + "\n" +
                           "  Message: " + 
                              exception.getMessage( ));        
        throw new SAXException("Warning encountered");
    }

    public void error(SAXParseException exception)
        throws SAXException {
        
        System.out.println("**Parsing Error**\n" +
                           "  Line:    " + 
                              exception.getLineNumber( ) + "\n" +
                           "  URI:     " + 
                              exception.getSystemId( ) + "\n" +
                           "  Message: " + 
                              exception.getMessage( ));
        throw new SAXException("Error encountered");
    }

    public void fatalError(SAXParseException exception)
        throws SAXException {
    
        System.out.println("**Parsing Fatal Error**\n" +
                           "  Line:    " + 
                              exception.getLineNumber( ) + "\n" +
                           "  URI:     " + 
                              exception.getSystemId( ) + "\n" +
                           "  Message: " + 
                              exception.getMessage( ));        
        throw new SAXException("Fatal Error encountered");
    }
}


class JTreeContentHandler implements ContentHandler {

    /** Hold onto the locator for location information */
    private Locator locator;

    /** Store URI to prefix mappings */
    private Map namespaceMappings;

    /** Tree Model to add nodes to */
    private DefaultTreeModel treeModel;

    /** Current node to add sub-nodes to */
    private DefaultMutableTreeNode current;

    public JTreeContentHandler(DefaultTreeModel treeModel, 
                               DefaultMutableTreeNode base) {
        this.treeModel = treeModel;
        this.current = base;
        this.namespaceMappings = new HashMap( );
    }
    
    public void setDocumentLocator(Locator locator) {
        // Save this for later use
        this.locator = locator;
    }

    public void ignorableWhitespace(char[] ch, int start, int length)
        throws SAXException {
        
        // This is ignorable, so don't display it
    }

    public void skippedEntity(String name) throws SAXException {
        DefaultMutableTreeNode skipped =
            new DefaultMutableTreeNode("Skipped Entity: '" + name + "'");
        current.add(skipped);
    }

    public void startPrefixMapping(String prefix, String uri) {
        // No visual events occur here.
        namespaceMappings.put(uri, prefix);
    }

    public void endPrefixMapping(String prefix) {
        // No visual events occur here.
        for (Iterator i = namespaceMappings.keySet().iterator( ); 
             i.hasNext( ); ) {

            String uri = (String)i.next( );
            String thisPrefix = (String)namespaceMappings.get(uri);
            if (prefix.equals(thisPrefix)) {
                namespaceMappings.remove(uri);
                break;
            }
        }
    }

    public void processingInstruction(String target, String data)
        throws SAXException {

        DefaultMutableTreeNode pi = 
            new DefaultMutableTreeNode("PI (target = '" + target +
                                       "', data = '" + data + "')");
        current.add(pi);
    }
    
    public void startDocument( ) throws SAXException {
        // No visual events occur here
    }

    public void endDocument( ) throws SAXException {
        // No visual events occur here
    }

    public void startElement(String namespaceURI, String localName,
                             String qName, Attributes atts)
        throws SAXException {

        DefaultMutableTreeNode element = 
            new DefaultMutableTreeNode("Element: " + localName);
        current.add(element);
        current = element;

        // Determine namespace
        if (namespaceURI.length( ) > 0) {
            String prefix = 
                (String)namespaceMappings.get(namespaceURI);
            if (prefix.equals("")) {
                prefix = "[None]";
            }
            DefaultMutableTreeNode namespace =
                new DefaultMutableTreeNode("Namespace: prefix = '" +
                    prefix + "', URI = '" + namespaceURI + "'");
            current.add(namespace);
        }

        // Process attributes
        for (int i=0; i 0) {
                String attPrefix = 
                    (String)namespaceMappings.get(namespaceURI);
                if (attPrefix.equals("")) {
                    attPrefix = "[None]";
                }
                DefaultMutableTreeNode attNamespace =
                    new DefaultMutableTreeNode("Namespace: prefix = '" +
                        attPrefix + "', URI = '" + attURI + "'");
                attribute.add(attNamespace);            
            }
            current.add(attribute);
        }
    }
    
    public void endElement(String namespaceURI, String localName,
                           String qName)
        throws SAXException {

        // Walk back up the tree
        current = (DefaultMutableTreeNode)current.getParent( );
    }
    
    public void characters(char[] ch, int start, int length)
        throws SAXException {

        String s = new String(ch, start, length);
        DefaultMutableTreeNode data =
            new DefaultMutableTreeNode("Character Data: '" + s + "'");
        current.add(data);
    }
    
}


========================================
ErrorHandler.java
========================================
public interface ErrorHandler {
    public abstract void warning (SAXParseException exception)
		throws SAXException;
    public abstract void error (SAXParseException exception)
		throws SAXException;
    public abstract void fatalError (SAXParseException exception)
		throws SAXException;
}


========================================
ContentHandler.java
========================================
public interface ContentHandler {
    public void setDocumentLocator(Locator locator);
    public void startDocument( ) throws SAXException;
    public void endDocument( ) throws SAXException;
    public void startPrefixMapping(String prefix, String uri)
		throws SAXException;
    public void endPrefixMapping(String prefix)
		throws SAXException;
    public void startElement(String namespaceURI, String localName,
	    		            String qName, Attributes atts)
		throws SAXException;
    public void endElement(String namespaceURI, String localName,
			          String qName)
		throws SAXException;
    public void characters(char ch[], int start, int length)
		throws SAXException;
    public void ignorableWhitespace(char ch[], int start, int length)
		throws SAXException;
    public void processingInstruction(String target, String data)
		throws SAXException;
    public void skippedEntity(String name)
		throws SAXException;
}