Friday, November 12, 2010

Java XML DOM Document creation

/**
 * Since if found some crap on the Internet, here a better example for creating an XML document in Java. 
 * 
 * Copyright: Harald Schilly
 * License: Apache 2.0
 */


package at.schilly.aldap2.ue12131415xml;


import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Map;


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.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;
import org.w3c.dom.Node;


/** @author harald schilly */
public class MapToXml {
  
  final private SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
  
  /** this method takes a Map of Strings to Strings and builds an xml document.
   * 
   * @param xmlfn
   *          xml output filename
   * @param map
   *          just a plain Map
   * @throws ParserConfigurationException
   * @throws FileNotFoundException
   * @throws TransformerException */
  public void write(final File xmlfn, final Map map)
      throws ParserConfigurationException, FileNotFoundException,
      TransformerException {
    // Docbuilder to create the xmldoc
    DocumentBuilderFactory docbuilderfactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docbuilder = docbuilderfactory.newDocumentBuilder();
    Document xmldoc = docbuilder.newDocument();
    
    // That's the root element
    Element root = xmldoc.createElement("map");
    
    // last saved element
    Element lastsaved = xmldoc.createElement("lastSavedBy");
    lastsaved.setAttribute("name", "Harald Schilly");
    lastsaved.setAttribute("date",
        dateformat.format(Calendar.getInstance().getTime()));
    root.appendChild(lastsaved);
    
    // iterate over map and add the entry/value elements
    for (Map.Entry mapentry : map.entrySet()) {
      Element entry = xmldoc.createElement("entry");
      entry.setAttribute("key", mapentry.getKey());
      
      Element value = xmldoc.createElement("value");
      Node node = xmldoc.createTextNode(mapentry.getValue());
      
      value.appendChild(node);
      entry.appendChild(value);
      root.appendChild(entry);
    }
    xmldoc.appendChild(root);
    
    // get a transformer with the given .dtd
    TransformerFactory transormerfactory = TransformerFactory.newInstance();
    Transformer transformer = transormerfactory.newTransformer();
    transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "map.dtd");
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    
    // transform and write to a file
    // use a StringWriter() object to write to a string.
    FileOutputStream fos = new FileOutputStream(xmlfn);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    StreamResult result = new StreamResult(bos);
    DOMSource source = new DOMSource(xmldoc);
    transformer.transform(source, result);
  }
}