package com.alisk.xml;

import java.io.StringWriter;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

interface XmlNode {
}

class Attribute implements XmlNode {
    String name;
    String value;

    Attribute(String name, String value) {
        this.name = name;
        this.value = value;
    }
}

class Empty implements XmlNode {

}

class Value implements XmlNode {
    String val;

    Value(String val) {
        this.val = val;
    }
}

public class Tag implements XmlNode {
    String name;
    ArrayList<XmlNode> parts = new ArrayList<>();

    Tag(String name) {
        this.name = name;
    }

    static Tag tag(String name) {
        return new Tag(name);
    }

    static Value val(String value) {
        return new Value(value);
    }

    Tag with(XmlNode... es) {
        for (XmlNode e : es) {
            parts.add(e);
        }
        return this;
    }

    static Attribute atr(String name, String value) {
        return new Attribute(name, value);
    }

    static Element createElement(Document doc, Tag tag) {
        Element el = doc.createElement(tag.name);
        for (XmlNode e : tag.parts) {
            if (e instanceof Tag) {
                el.appendChild(createElement(doc, (Tag) e));
            } else if (e instanceof Attribute) {
                Attribute a = (Attribute) e;
                el.setAttribute(a.name, a.value);
            } else if (e instanceof Value) {
                el.appendChild(doc.createTextNode(((Value) e).val));
            }
        }
        return el;
    }

    Document toDoc() {
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = null;
            docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            doc.appendChild(createElement(doc, this));
            return doc;
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public String toString() {
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer;

            transformer = tf.newTransformer();

            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            StringWriter writer = new StringWriter();

            transformer.transform(new DOMSource(toDoc()), new StreamResult(writer));
            String output = writer.getBuffer().toString().replaceAll("\n|\r", "");
            return output;
        } catch (TransformerException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        String xml =
                tag("foo").with(
                    atr("bar", "baz"),
                    tag("hello"),
                    val("world"),
                    tag("life").with(
                       atr("isgood", "yes")))
                .toString();
        System.out.println(xml);
    }

}

@@ -1,8 +1,1104 @@
+MIT License%0D%0A%0D%0ACopyright (c) 2016 Morten Bendiksen%0D%0A%0D%0APermission is hereby granted, free of charge, to any person obtaining a copy%0D%0Aof this software and associated documentation files (the %22Software%22), to deal%0D%0Ain the Software without restriction, including without limitation the rights%0D%0Ato use, copy, modify, merge, publish, distribute, sublicense, and/or sell%0D%0Acopies of the Software, and to permit persons to whom the Software is%0D%0Afurnished to do so, subject to the following conditions:%0D%0A%0D%0AThe above copyright notice and this permission notice shall be included in all%0D%0Acopies or substantial portions of the Software.%0D%0A%0D%0ATHE SOFTWARE IS PROVIDED %22AS IS%22, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR%0D%0AIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,%0D%0AFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE%0D%0AAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER%0D%0ALIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,%0D%0AOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE%0D%0ASOFTWARE.%0D%0A%0D%0A
 package 

Update Tag.java