package com.alethis.xml;

import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.sax.*; 
import java.io.*;

public class FilterWithCustomContentHandler {

    public static File INPUT_FILE = new File("c:\\project\\xml\\in.xml");
    public static File OUTPUT_FILE = new File("c:\\project\\xml\\out.xml");
    
    public final static void main(String[] args) {
        try {
            FileReader fr = new FileReader(INPUT_FILE);
            BufferedReader br = new BufferedReader(fr);
            InputSource is = new InputSource(br);
            
            XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
            CustomFilter filter = new CustomFilter();
            filter.setParent(parser);
            filter.setContentHandler(new ContentHandlerImpl());
            SAXSource source = new SAXSource(filter, is);

            FileWriter fw = new FileWriter(OUTPUT_FILE);
            BufferedWriter bw = new BufferedWriter(fw);
            StreamResult result = new StreamResult(bw);

            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer();      
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");            
            transformer.transform(source, result);
            
            System.out.println("DONE");
        }
        catch (TransformerConfigurationException e) {
            System.out.println("Transformer Configuration Exception: " + e.getMessage());
        }
        catch (TransformerException e) {
            System.out.println("Transformer Exception: " + e.getMessage());
        }
        catch (IOException e) {
            System.out.println("IO Exception: " + e.getMessage());
        }           
        catch (SAXException se) {
            System.out.println("SAX exception: " + se.getMessage());
        }
    }
}

class CustomFilter extends XMLFilterImpl {
    public void setContentHandler(ContentHandler handler) {
        super.setContentHandler(new CustomContentHandler(handler));
    }
}

class CustomContentHandler implements ContentHandler {
    
    private ContentHandler parent;
    
    private static int id = 0;
    
    public CustomContentHandler(ContentHandler parent) {
        this.parent = parent;
    }
    
    public void startElement(String namespaceURI, String localName, String qualifiedName, Attributes attrs) throws SAXException {
        AttributesImpl a = new AttributesImpl(attrs);
        a.addAttribute(null, "id", "id", "ID", "_" + String.valueOf(id++));
        parent.startElement(namespaceURI, localName, qualifiedName, a);
    }
    
    public void endElement(String namespaceURI, String localName, String qualifiedName) throws SAXException {
        parent.endElement(namespaceURI, localName, qualifiedName);
    }
    
    public void startDocument() throws SAXException {
        parent.startDocument();
    }
    
    public void endDocument() throws SAXException {
        parent.endDocument();
    }
    
    public void startPrefixMapping(String prefix, String uri) throws SAXException {
        parent.startPrefixMapping(prefix, uri);
    }
    
    public void endPrefixMapping(String prefix) throws SAXException {
        parent.endPrefixMapping(prefix);
    }
    
    public void characters(char[] text, int start, int length) throws SAXException {
        parent.characters(text, start, length);
    }
    
    public void ignorableWhitespace(char[] text, int start, int length) throws SAXException {
        parent.ignorableWhitespace(text, start, length);
    }
    
    public void processingInstruction(String target, String data) throws SAXException {
        parent.processingInstruction(target, data);
    }
    
    public void skippedEntity(String name) throws SAXException {
        parent.skippedEntity(name);
    }
    
    public void setDocumentLocator(Locator locator) {
        parent.setDocumentLocator(locator);
    }
}