如何将XML转换为java.util.Map,反之亦然

Chr*_*ris 65 java xml

我正在搜索一个轻量级API(最好是单个类)来转换

Map<String,String> map = new HashMap<String,String();
Run Code Online (Sandbox Code Playgroud)

到xml,反之亦然,将XML转换回Map.

例:

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

MagicAPI.toXML(map,"root");
Run Code Online (Sandbox Code Playgroud)

结果:

<root>
  <name>chris</chris>
  <island>faranga</island>
</root>
Run Code Online (Sandbox Code Playgroud)

然后回来:

Map<String,String> map = MagicAPI.fromXML("...");
Run Code Online (Sandbox Code Playgroud)

我不想使用JAXBJSON转换API.它不需要处理嵌套的地图或属性或其他任何东西,只是这个简单的情况.有什么建议?


编辑:我创建了一个工作复制和粘贴示例.感谢fvuMichal Bernhard.

下载最新的XStream框架,'仅核心'就足够了.

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);
Run Code Online (Sandbox Code Playgroud)

不需要转换器或任何其他东西.只需xstream-xyzjar即可.

Mic*_*ard 61

XStream的!

更新:我在评论中要求添加了解组部分..

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;

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

public class Test {

    public static void main(String[] args) {

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

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

        String xml = magicApi.toXML(map);
        System.out.println("Result of tweaked XStream toXml()");
        System.out.println(xml);

        Map<String, String> extractedMap = (Map<String, String>) magicApi.fromXML(xml);
        assert extractedMap.get("name").equals("chris");
        assert extractedMap.get("island").equals("faranga");

    }

    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()) {
                Map.Entry entry = (Map.Entry) obj;
                writer.startNode(entry.getKey().toString());
                Object val = entry.getValue();
                if ( null != val ) {
                    writer.setValue(val.toString());
                }
                writer.endNode();
            }

        }

        public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {

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

            while(reader.hasMoreChildren()) {
                reader.moveDown();

                String key = reader.getNodeName(); // nodeName aka element's name
                String value = reader.getValue();
                map.put(key, value);

                reader.moveUp();
            }

            return map;
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

  • XStream xs = new XStream(新的DomDriver("UTF-8",新的XmlFriendlyReplacer("_-","\ _"))); //用于正确的下划线处理 (2认同)

小智 44

这里的XStream转换器包括unmarshall

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

public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
    AbstractMap<String,String> map = (AbstractMap<String,String>) value;
    for (Entry<String,String> entry : map.entrySet()) {
        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;
}
Run Code Online (Sandbox Code Playgroud)


fvu*_*fvu 8

XStream怎么样?对于包括你在内的许多用例而言,不是1级而是2个罐子,使用起来非常简单但非常强大.


Mic*_*mlk 8

一种选择是自己动手.这样做很简单:

Document doc = getDocument();
Element root = doc.createElement(rootName);
doc.appendChild(root);
for (Map.Entry<String,String> element : map.entrySet() ) {
    Element e = doc.createElement(element.getKey());
    e.setTextContent(element.getValue());
    root.appendChild(e);
}
save(doc, file);
Run Code Online (Sandbox Code Playgroud)

并且负载是同样简单getChildNodes的循环.当然它有一些XML神需要的锅炉板,但它最多工作1小时.

或者,如果您对XML的格式不太融合,您可以查看属性.


Eva*_*els 6

我使用自定义转换器的方法:

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());
            context.convertAnother(entry.getValue());
            writer.endNode();
        }
    }

    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        // dunno, read manual and do it yourself ;)
    }

}
Run Code Online (Sandbox Code Playgroud)

但是我将maps值的序列化更改为委托给MarshallingContext.这应该改进解决方案以适用于复合地图值和嵌套地图.

  • 如果`unmarshal()`完成了,这将是一个更好的例子。 (3认同)