import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory;  
import javax.xml.parsers.FactoryConfigurationError;  
import javax.xml.parsers.ParserConfigurationException;
 
import org.xml.sax.SAXException;  
import org.xml.sax.SAXParseException;  

import java.io.File;
import java.io.IOException;

import org.w3c.dom.Document;
import org.w3c.dom.DOMException;

/*
 * Show all nodes in parsed XML document
 *
 * @author Owen Astrachan
 */
public class DomShow
{
    private Document document; 
    private final String[] TAB_STR = {
        "    ",
        "        ",
        "            ",
        "                ",
        "                    "        
    };

    /**
     * Returns a string for indenting/tabbing
     * @param level is amount to indent (0 = once, 1 = twice, ...)
     * @return String used for tabbing
     */
    
    private String indent(int level)
    {
        if (level < TAB_STR.length){
            return TAB_STR[level];
        }
        return TAB_STR[0];
    }

    /**
     * Remove leading/trailing white-space, handle null gracefully
     * @param s is a string or null to unwhite
     * @return version of s that is trimmed using String.trim()
     */
    private String unwhite(String s)
    {
        if (s == null) return null;
        else           return s.trim();
    }

    /**
     * Display this node and its children and attributes.
     * @param node is the DOM node to display
     * @param level is indentation level
     */
    public void display(org.w3c.dom.Node node, int level)
    {
        System.out.println(indent(level)+"name: "+node.getNodeName());
        System.out.println(indent(level)+"value: "+unwhite(node.getNodeValue()));
        System.out.println(indent(level)+"type: "+node.getNodeType());        

        
        org.w3c.dom.NodeList list = node.getChildNodes();
        System.out.println(indent(level)+" ** children **");
        for(int k=0; k < list.getLength(); k++) {
            display(list.item(k),level+1);
        }
        org.w3c.dom.NamedNodeMap nnmap = node.getAttributes();
        if (nnmap != null && nnmap.getLength() != 0) {
            System.out.println(indent(level)+" ** attributes **");            
            for(int k=0; k < nnmap.getLength(); k++) {
                display(nnmap.item(k),level+1);
            }
        }
    }


    /**
     * Open/parse XML file and return Document for it
     * @param filename is file containing XML
     * @return Document parsed from file read
     */
    
    public Document getDocFromFile(String filename)
    {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        // factory.setValidating(true);   
        factory.setNamespaceAware(true);
        try {
           DocumentBuilder builder = factory.newDocumentBuilder();
           document = builder.parse(new File(filename));
           return document;
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public static void main(String argv[])
    {
        if (argv.length != 1) {
            System.err.println("Usage: java DomEcho filename");
            System.exit(1);
        }
        DomShow ds = new DomShow();
        Document doc = ds.getDocFromFile(argv[0]);
        ds.display(doc,0);

    } 

}
