// XML parser (uses SAX)
// usage java XMLEcho file.xml >outputfile.xml
// Sends report to console

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;  
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;

public class XMLEcho extends DefaultHandler {
    static private Writer out;
    public static void main(String args[]) throws Exception {
        // Use an instance of ourselves as the SAX event handler
        DefaultHandler handler = new XMLEcho();
        
        // Use the default (non-validating) parser
        SAXParserFactory factory = SAXParserFactory.newInstance();

        // Set up output stream
        out = new OutputStreamWriter(System.out, "UTF8");

        // Parse the input 
        SAXParser saxParser = factory.newSAXParser();
        File ifile = new File(args[0]);
        saxParser.parse( ifile, handler );

    }

    private void emit(String s)  // write output
        throws SAXException    {
        try {
            out.write(s);
            out.flush();
        } catch (IOException e) {
            throw new SAXException("I/O error", e);
        }
    }


    private void nl()
    throws SAXException     {
        String lineEnd =  System.getProperty("line.separator");
        try {
            out.write(lineEnd);
       
        } catch (IOException e) {
            throw new SAXException("I/O error", e);
        }
    }

    public void startDocument()
    throws SAXException    {
        emit("<?xml version='1.0' encoding='UTF-8'?>");
        System.err.println("Start document");
        nl();
    }

    public void endDocument()
    throws SAXException     {
        try {
            System.err.println("End document");
            nl();
            out.flush();
        } catch (IOException e) {
            throw new SAXException("I/O error", e);
        }
    }



    public void startElement(String namespaceURI,
                             String sName, // simple name (localName)
                             String qName, // qualified name
                             Attributes attrs)
    throws SAXException     {
        String eName = sName; // element name
        if ("".equals(eName)) eName = qName; // namespaceAware = false
        emit("<"+eName);
        System.err.println("TAG: " + eName);
        if (attrs != null) {
            for (int i = 0; i < attrs.getLength(); i++) {
                String aName = attrs.getLocalName(i); // Attr name 
                if ("".equals(aName)) aName = attrs.getQName(i);
                emit(" ");
                emit(aName+"=\""+attrs.getValue(i)+"\"");
            }
        }
        emit(">");
    }

    public void endElement(String namespaceURI,
                           String sName, // simple name
                           String qName  // qualified name
                          )
    throws SAXException     {
        String eName = sName; // element name
        if ("".equals(eName)) eName = qName; // namespaceAware = false
        emit("</"+eName+">");
        System.err.println("End tag: " + eName);
    }


    public void characters(char buf[], int offset, int len)
    throws SAXException     {
        String s = new String(buf, offset, len);
        if (len!=0&&(len!=1||buf[offset]!='\n')) 
           System.err.println("Content: [" + s + "]");
        emit(s);
    }

}
