import org.xml.sax.*;

public class XMLCounter implements ContentHandler {

  private int numberOfElements;
  private int numberOfAttributes;
  private int numberOfProcessingInstructions;
  private int numberOfCharacters;

  public void startDocument() throws SAXException {
    numberOfElements = 0;
    numberOfAttributes = 0;
    numberOfProcessingInstructions = 0;
    numberOfCharacters = 0;
  }
  
  // We should count either the start-tag of the element or the end-tag, 
  // but not both. Empty elements will still be reported by each of these 
  // methods.
  public void startElement(String namespaceURI, String localName, 
   String qualifiedName, Attributes atts) throws SAXException {
    numberOfElements++;
    numberOfAttributes += atts.getLength();
  } 

  public void endElement(String namespaceURI, String localName, 
   String qualifiedName) throws SAXException {}
  
  public void characters(char[] text, int start, int length) 
   throws SAXException {
    numberOfCharacters += length; 
  }
  
  public void ignorableWhitespace(char[] text, int start, int length)
   throws SAXException {
    numberOfCharacters += length;
  }
  
  public void processingInstruction(String target, String data)
   throws SAXException {
    numberOfProcessingInstructions++; 
  }

  // Now that the document is done, we can print out the final results
  public void endDocument() throws SAXException {
    System.out.println("Number of elements: " + numberOfElements);
    System.out.println("Number of attributes: " + numberOfAttributes);
    System.out.println("Number of processing instructions: " 
     + numberOfProcessingInstructions);
    System.out.println("Number of characters of plain text: " 
     + numberOfCharacters);
  }

  // Do-nothing methods we have to implement only to fulfill
  // the interface requirements:
  public void setDocumentLocator(Locator locator) {}
  public void startPrefixMapping(String prefix, String uri) 
   throws SAXException {}  
  public void endPrefixMapping(String prefix) throws SAXException {}
  public void skippedEntity(String name) throws SAXException {}

}    

