Re: How to convert Map to xml based on Schema.
On 11/18/2012 4:15 PM, Arne Vajh?j wrote:
On 11/17/2012 1:52 AM, Mausam wrote:
I have a Map (it can be nested map, containing of maps) and a schema.
Keys in Map represent element/attribute name of the schema and an
entry in Map will be at same depth as an element defined in schema
I need help in generating xml from the map as per the schema provided,
without generating new files (as e.g Jaxb would require) Sample
schema/map provided below
e.g Map =
[dept=[deptno="10",dname="ABC",loc="XYZ",emps=[[empno=1000,ename="Albert"],[empno 00,ename="John"]]]]
and schema will be
e.g Schema
<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:element name="depts">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="dept" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="deptno" type="xsd:string"/><!-- This
simple element e.g can be attribute in some schema-->
<xsd:element name="dname" type="xsd:string"/>
<xsd:element name="emps" maxOccurs="unbounded"
minOccurs="0">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="empno" type="xsd:string"/>
<xsd:element name="ename" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
I would probably:
- generate a Java class from the schema (xjc)
- populate from Map to an instance of that class via recursion
and reflection
- serialize instance to XML via JAXB
If you have high performance requirements, then you may need
to do some custom coding.
Demo with Map:
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
public class AutoMapper {
private static Object xctor(Object o, String propnam) throws
IntrospectionException, InstantiationException, IllegalAccessException {
PropertyDescriptor pd = new PropertyDescriptor(propnam, o.getClass());
return pd.getPropertyType().newInstance();
}
private static void xset(Object o, String propnam, Object val) throws
IntrospectionException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
PropertyDescriptor pd = new PropertyDescriptor(propnam, o.getClass());
pd.getWriteMethod().invoke(o, val);
}
@SuppressWarnings("unchecked")
private static void map(Map<String,Object> m, Object o) throws
IllegalArgumentException, IntrospectionException,
IllegalAccessException, InvocationTargetException, InstantiationException {
for(String key : m.keySet()) {
Object val = m.get(key);
if(val instanceof Map) {
Object o2 = xctor(o, key);
map((Map<String, Object>) val, o2);
xset(o, key, o2);
} else {
xset(o, key, val);
}
}
}
public static void main(String[] args) throws Exception {
Map<String,Object> m2 = new HashMap<String,Object>();
m2.put("iv", 456);
m2.put("xv", 123.456);
Map<String,Object> m = new HashMap<String,Object>();
m.put("iv", 123);
m.put("sv", "ABC");
m.put("cv", m2);
Data o = new Data();
System.out.println(m);
map(m, o);
System.out.println(o);
}
}
class Data {
private int iv;
private String sv;
private SubData cv;
public int getIv() {
return iv;
}
public void setIv(int iv) {
this.iv = iv;
}
public String getSv() {
return sv;
}
public void setSv(String sv) {
this.sv = sv;
}
public SubData getCv() {
return cv;
}
public void setCv(SubData cv) {
this.cv = cv;
}
@Override
public String toString() {
return "(iv=" + iv + ",sv=" + sv + ",cv=" + cv + ")";
}
}
class SubData {
private int iv;
private double xv;
public int getIv() {
return iv;
}
public void setIv(int iv) {
this.iv = iv;
}
public double getXv() {
return xv;
}
public void setXv(double xv) {
this.xv = xv;
}
@Override
public String toString() {
return "(iv=" + iv + ",xv=" + xv + ")";
}
}
Arne
PS: It looks like you may really need to convert List not Map.