How to convert XML to java.util.Map and vice versa?

Viewed 154389

I'm searching a lightweight API (preferable single class) to convert a

Map<String,String> map = new HashMap<String,String();

to XML and, vice versa, convert the XML back to a Map<String,String>.

example:

Map<String,String> map = new HashMap<String,String();
map.put("name","chris");
map.put("island","faranga");

MagicAPI.toXML(map,"root");

result:

<root>
  <name>chris</chris>
  <island>faranga</island>
</root>

and back:

Map<String,String> map = MagicAPI.fromXML("...");

I don't want to use JAXB or JSON conversion API. It doesn't have to take care of nested maps or attributes or anything else, just that simple case. Any suggestions?


I created a working copy & paste sample. Thanks to fvu and Michal Bernhard.

Download latest XStream framework, 'core only' is enough.

Map<String,Object> map = new HashMap<String,Object>();
map.put("name","chris");
map.put("island","faranga");

// convert to XML
XStream xStream = new XStream(new DomDriver());
xStream.alias("map", java.util.Map.class);
String xml = xStream.toXML(map);

// from XML, convert back to map
Map<String,Object> map2 = (Map<String,Object>) xStream.fromXML(xml);

No converters or anything else is required. Just the xstream-x.y.z.jar is enough.

13 Answers

If you only need to convert simple map to xml, without nested properties, then the lightweight solution would be just a private method, as follows:

private String convertMapToXML(Map<String, String> map) {
    StringBuilder xmlBuilder = new StringBuilder();
    xmlBuilder.append("<xml>");
    for (Map.Entry<String, String> entry : map.entrySet()) {
        if (entry.getValue() != null) {
            String xmlElement = entry.getKey();
            xmlBuilder.append("<");
            xmlBuilder.append(xmlElement);
            xmlBuilder.append(">");
            xmlBuilder.append(entry.getValue());
            xmlBuilder.append("<");
            xmlBuilder.append("/");
            xmlBuilder.append(xmlElement);                
            xmlBuilder.append(">");
        }             
    }

    xmlBuilder.append("</xml>");
    return xmlBuilder.toString();
}

In my case I convert DBresponse to XML in Camel ctx. JDBC executor return the ArrayList (rows) with LinkedCaseInsensitiveMap (single row). Task - create XML object based on DBResponce.

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.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.springframework.util.LinkedCaseInsensitiveMap;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

public class ConvertDBToXMLProcessor implements Processor {

    public void process(List body) {

        if (body instanceof ArrayList) {
            ArrayList<LinkedCaseInsensitiveMap> rows = (ArrayList) body;

            DocumentBuilder builder = null;
            builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document document = builder.newDocument();
            Element rootElement = document.createElement("DBResultSet");

            for (LinkedCaseInsensitiveMap row : rows) {
                Element newNode = document.createElement("Row");
                row.forEach((key, value) -> {
                    if (value != null) {
                        Element newKey = document.createElement((String) key);
                        newKey.setTextContent(value.toString());
                        newNode.appendChild(newKey);
                    }
                });
                rootElement.appendChild(newNode);
            }
            document.appendChild(rootElement);


            /* 
            * If you need return string view instead org.w3c.dom.Document
            */
            StringWriter writer = new StringWriter();
            StreamResult result = new StreamResult(writer);
            DOMSource domSource = new DOMSource(document);
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
            transformer.transform(domSource, result);

            // return document
            // return writer.toString()

        }
    }
}
Related