Xstream Map <-> XML (2)

황제낙엽 2011.04.29 13:54 조회 수 : 99

site_link1  
site_link2  
site_link3 http://1 
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
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.converters.collections.AbstractCollectionConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.mapper.Mapper;

public class XmlToMap {

private String xmlData = null;
private String root = null;

/**
*
*/
public XmlToMap(String xml, String root) {

this.xmlData = xml;
this.root = root;

}

@SuppressWarnings("unchecked")
public Object build() throws Exception {

XStream xStream = new XStream(new DomDriver("UTF-8"));
Mapper mapper = xStream.getMapper();
xStream.alias(root, Map.class);
xStream.registerConverter(new MapConverter(mapper));

Map<String, String> xmlMap = (Map<String, String>) xStream.fromXML(xmlData);

return xmlMap;
}

public static class MapConverter extends AbstractCollectionConverter implements Converter {

public MapConverter(Mapper mapper) {
super(mapper);
}

@SuppressWarnings("rawtypes")
public boolean canConvert(Class type) {
return type.equals(java.util.HashMap.class)
|| type.equals(java.util.Hashtable.class)
|| (type.getName().equals("java.util.LinkedHashMap") 
|| type.getName().equals("sun.font.AttributeMap"));
}

@SuppressWarnings("rawtypes")
public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {

AbstractMap map = (AbstractMap) value;
for (Object obj : map.entrySet()) {
Entry ety = (Entry) obj;
writer.startNode(ety.getKey().toString());
writer.setValue(ety.getValue().toString());
writer.endNode();
}

}

@SuppressWarnings( { "unchecked", "rawtypes" })
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext arg1) {

Map elements = new HashMap();
for (; reader.hasMoreChildren(); reader.moveUp()) {

reader.moveDown();

if (reader.hasMoreChildren() == true) {

//재귀호출
elements.put(reader.getNodeName(), unmarshal(reader, arg1));

} else {

String tempValue = reader.getValue();
String tempKey = reader.getNodeName();

if (tempValue != null) {
tempValue = tempValue.trim().replaceAll("n", "");
}

Object gettingValue = elements.get(tempKey);
if (gettingValue != null) {

//가장 하위의 요소들이 중복일경우에는 List 처리를 합니다.
//단 , 상위요소가 중복일경우에는 무시합니다. 하나만 처리됩니다.
// 예
//<abc>
// <record>
//  <ele>1</ele>
//  <ele>2</ele>
// </record>
// <record>
//  <ele>3</ele>
//  <ele>4</ele>
// </record>
//</abc>
//위와 같을경우에 <ele> 요소는 배열처리 되지만 <record>는 나머지는 무시되고 하나만 저장됩니다.

//중복된 요소의 List 처리
if (gettingValue instanceof List) {
((List) gettingValue).add(tempValue);
elements.put(tempKey, gettingValue);
} else if (gettingValue instanceof String) {
List tempList = new ArrayList();
tempList.add(gettingValue);
tempList.add(tempValue);
elements.put(tempKey, tempList);
}

} else {
elements.put(reader.getNodeName(), tempValue);
}

}
}

return elements;
}

}

public static void main(String args[]) {

StringBuilder buffer = new StringBuilder();

buffer.append("<res>      ");
buffer.append(" <param>      ");
buffer.append("  <val1>val1</val1>  ");
buffer.append("  <val2>val2</val2>  ");
buffer.append(" </param>      ");
buffer.append("</res>      ");

XmlToMap test = new XmlToMap(buffer.toString(), "res");
try {
Object oo = test.build();
System.out.println(oo);
} catch (Exception e) {
e.printStackTrace();
}
}
}