import org.w3c.dom.*;

public class Visitor {

   protected String name, value;
   protected int depthCounter = 0;

   public void visit(Document doc) {
      try {
		 Node root = (Node)doc.getDocumentElement();
         visit(root);
      } catch(VisitorException e) {
         handle(e);
      }
   }

   // visit content
   public void visit(NodeList nodes) throws VisitorException {
      depthCounter++;
      for(int i = 0; i < nodes.getLength(); i++) {
         visit(nodes.item(i));
      }
      depthCounter--;
   }

   // visit attributes
   public void visit(NamedNodeMap nodes) throws VisitorException {
	   depthCounter++;
	   for(int i = 0; i < nodes.getLength(); i++) {
		   Attr attribute = (Attr) nodes.item(i);
           visit(attribute);
	   }
	   depthCounter--;
   }

   // dispatcher:
   public void visit(Node node) throws VisitorException {
      name = node.getNodeName();
      value = node.getNodeValue();
      if (value != null) value = value.trim();
      switch (node.getNodeType()) {
         case Node.ELEMENT_NODE:
            Element elem = (Element) node;
            visit(elem);
            visit(node.getAttributes());
            visit(node.getChildNodes());
            break;
         case Node.ATTRIBUTE_NODE:
            Attr attr = (Attr) node;
            visit(attr);
            break;
         case Node.CDATA_SECTION_NODE:
         case Node.TEXT_NODE:
            Text text = (Text) node;
            visit(text);
            break;
      } // switch
   } // visit node



   // overridables:
   protected void visit(Element node) throws VisitorException { }
   protected void visit(Text node) throws VisitorException { }
   protected void visit(Attr node) throws VisitorException { }
   protected void handle(VisitorException e) {
      System.err.println("visitor exception: " + e);
   }
   // etc.
}