Tuesday, June 5, 2012

Conversion of a Map into XML and Vice-versa in Java

Dear reader,
I am writing an article today on how to convert a Map to XML and Vice-versa in Java.
I have tried to put nested Map examples too, which is serialized in a String Key,Value pair. Third party libraries are from 
XStream team, which are very popular in Industry for the same.
I hope you will find it useful. Some tweaking may be required to suit your purpose but the below mentioned all
examples are tested by me and runs fine. So enjoy reading and experimenting from where I have left here...

Contents:
1) Plain Java code to convert a Map to an XML.
2) Java code using Third party libraries to convert into XML and Vice-Versa.
3) Again using same Third party libraries as point-2 above but a complex converter.
4) Nested Map contents and conversion into XML.
5) Reference link.
6) Required Jars for third party libraries.


1) Plain Java code to convert a Map to an XML
   First I am writing a very simple program to convert a Map to an XML as below:

import java.util.HashMap;
import java.util.Map;

public class MagicAPI {
    public static void main(String[] args) {
        Map<String,String> mp=new HashMap<String,String>();

        //Map contains: EmpId,Name
        mp.put("197","Deepak kumar modi");
        mp.put("198","Sweep panorama");
        mp.put("199","HD Video");
        //System.out.println(mp);

        String xml = covertToXML(mp,"root");
        System.out.println("Result of converted map to xml:");
        System.out.println(xml);
    }
    public static String covertToXML(Map<String, String> map, String root) {
        StringBuilder sb = new StringBuilder("<");
        sb.append(root);
        sb.append(">");

        for (Map.Entry<String, String> e : map.entrySet()) {
            sb.append("<");
            sb.append(e.getKey());
            sb.append(">");

            sb.append(e.getValue());
            sb.append("</");
            sb.append(e.getKey());
            sb.append(">");
        }

        sb.append("</");
        sb.append(root);
        sb.append(">");

        return sb.toString();
    }
}
//Output: 
Result of converted map to xml:
<root><198>Sweep panorama</198><199>HD Video</199><197>Deepak kumar modi</197></root>


2) Java code using Third party libraries to convert into XML and Vice-Versa
//Two POJOs are required for this example, so please find below two simple classes:

//Person.java
public class Person {
    private String firstname;
    private String lastname;
    private PhoneNumber phone;
    private PhoneNumber fax;
    public Person(String fn,String ln){
        setFirstname(fn);
        setLastname(ln);
    }
    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getLastname() {
        return lastname;
    }
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }
    public PhoneNumber getPhone() {
        return phone;
    }
    public void setPhone(PhoneNumber phone) {
        this.phone = phone;
    }
    public PhoneNumber getFax() {
        return fax;
    }
    public void setFax(PhoneNumber fax) {
        this.fax = fax;
    }
    public String toString(){
        StringBuffer sb=new StringBuffer();
        sb.append(getFirstname()).append(",");
        sb.append(getLastname()).append(",");
        //sb.append(getPhone().getCode()).append(",");
        //sb.append(getPhone().getNumber()).append(",");
        return sb.toString();
    }
}

//PhoneNumber.java
public class PhoneNumber {
    private int code;
    private String number;
    public PhoneNumber(int i, String string) {
        setCode(i);
        setNumber(string);
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getNumber() {
        return number;
    }
    public void setNumber(String number) {
        this.number = number;
    }
}

//Main program: SimpleConverter.java, please check at the end for these supportive jar files.

import java.io.File;
import java.io.FileOutputStream;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.StaxDriver;

public class SimpleConverter {
    public static void main(String[] args) throws Exception {
        Person me = new Person("Deepak", "Modi");
        me.setPhone(new PhoneNumber(91, "991647****"));
        me.setFax(new PhoneNumber(80, "23658***"));
        XStream xstream = new XStream(new DomDriver());  //This will parse like a complete xml
        //XStream xstream = new XStream(new StaxDriver());   //This will parse into a String format, however this is also xml
        
        xstream.alias("person", Person.class);
        xstream.alias("phonenumber", PhoneNumber.class);
        String xml = xstream.toXML(me);
        System.out.println("Newly generated xml..");
        System.out.println(xml);
        FileOutputStream fos=new FileOutputStream(new File("person.xml"));
        fos.write(xml.getBytes());
        System.out.println("\n...XML file generation is done too, check your directory..");
        
        System.out.println("Now we will read from XML, check below output: toString() method in Person class...");
        Person duplicateMe = (Person)xstream.fromXML(xml);
        System.out.println("Output: "+duplicateMe);
    }
}
//Output, along with below content a "person.xml" will be created too:
Newly generated xml..
<person>
  <firstname>Deepak</firstname>
  <lastname>Modi</lastname>
  <phone>
    <code>91</code>
    <number>991647****</number>
  </phone>
  <fax>
    <code>80</code>
    <number>23658***</number>
  </fax>
</person>

...XML file generation is done too, check your directory..
Now we will read from XML, check below output: toString() method in Person class...
Output: Deepak,Modi,


3) Again using same Third party libraries as point-2 above but a complex converter
//MapToXmlConverter.java

import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class MapToXmlConverter {
    public static void main(String[] args) throws Exception {
        Map<String,String> mp=new HashMap<String,String>();

        //Map contains: EmpId,Name
        mp.put("197","Deepak kumar modi");
        mp.put("198","Sweep panorama");
        mp.put("199","HD Video");
        mp.put("200","My Motorola Mobile");
        //System.out.println(mp);

        XStream magicApi = new XStream();
        magicApi.alias("root", Map.class);
        magicApi.registerConverter(new MapEntryConverter());

        String xml = magicApi.toXML(mp);
        System.out.println("Result of newly formed Xml:");
        System.out.println(xml);
    }
    
    public static class MapEntryConverter implements Converter {
        public boolean canConvert(Class clazz) {
            return AbstractMap.class.isAssignableFrom(clazz);
        }

        public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
            AbstractMap map = (AbstractMap) value;
            for (Object obj : map.entrySet()) {
                Entry entry = (Entry) obj;
                writer.startNode(entry.getKey().toString());
                writer.setValue(entry.getValue().toString());
                writer.endNode();
            }
        }

        public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
            Map<String, String> map = new HashMap<String, String>();
            while(reader.hasMoreChildren()) {
                reader.moveDown();
                map.put(reader.getNodeName(), reader.getValue());
                reader.moveUp();
            }
            return map;
        }
    }
}
//Output:
Result of newly formed Xml:
<root>
  <198>Sweep panorama</198>
  <199>HD Video</199>
  <200>My Motorola Mobile</200>
  <197>Deepak kumar modi</197>
</root>


4) Nested Map contents and conversion into XML
//NestedMapToXmlConverter.java
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class NestedMapToXmlConverter {
    public NestedMapToXmlConverter(){
        System.out.println("Constructor invoked..");
    }
    public static void main(String[] args) {
        Map mp=new HashMap();
        Map nestedMap=new HashMap();
        Map nestedNestedMap=new HashMap();

        //Map contains: EmpId,Name
        mp.put("197","Deepak kumar modi");
        mp.put("198","Sweep panorama");
        mp.put("199","HD Video");
        mp.put("200","My Motorola Mobile");
        //System.out.println(mp);

        //nestedMap contains: FirstName, LastName
        nestedMap.put("Deepak", "Modi");
        nestedMap.put("Sweep", "panorama");
        
        //NestedNestedMap contains: FN,Name
        nestedNestedMap.put("FN", "DEEPAK");
        nestedNestedMap.put("Object", new NestedMapToXmlConverter());
        
        nestedMap.put("NestedNestedMap", nestedNestedMap);
        
        mp.put("NestedMap", nestedMap);
        
        XStream magicApi = new XStream();
        magicApi.alias("root", Map.class);
        magicApi.registerConverter(new MapEntryConverter());

        String xml = magicApi.toXML(mp);
        System.out.println("Result of newly formed XML:");
        System.out.println(xml);

    }
    
    public static class MapEntryConverter implements Converter {
        public boolean canConvert(Class clazz) {
            return AbstractMap.class.isAssignableFrom(clazz);
        }

        public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
            AbstractMap map = (AbstractMap) value;
            for (Object obj : map.entrySet()) {
                Entry entry = (Entry) obj;
                //System.out.println(entry.getValue().toString());
                writer.startNode(entry.getKey().toString());
                writer.setValue(entry.getValue().toString());
                writer.endNode();
            }
        }

        public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
            Map<String, String> map = new HashMap<String, String>();
            while(reader.hasMoreChildren()) {
                reader.moveDown();
                map.put(reader.getNodeName(), reader.getValue());
                reader.moveUp();
            }
            return map;
        }
    }
}
//Output;
Constructor invoked..
Result of newly formed XML:
<root>
  <198>Sweep panorama</198>
  <199>HD Video</199>
  <200>My Motorola Mobile</200>
  <NestedMap>{Sweep=panorama, NestedNestedMap={FN=DEEPAK, Object=NestedMapToXmlConverter@182f0db}, Deepak=Modi}</NestedMap>
  <197>Deepak kumar modi</197>
</root>


5) For reference please check: http://xstream.codehaus.org/converter-tutorial.html

6) Required Jars for third party libraries: These below jars can be downloaded from Internet.
xstream-1.4.2.jar
kxml2-2.3.0.jar

----------------------------------------END-----------------------------------------

4 comments:

  1. Hi,

    Do try the Conversion Conduit component

    http://capsulesforthejavamind.blogspot.in/2014/10/conversion-conduit-v10_15.html

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. Nice example.. it helped me. Thanks Deepak

    ReplyDelete