2

I am trying to convert a xml file as follows into java map. xml

<Person>
   <ID>123</ID>
   <Demographics>
   <LastName>ABC</LastName>
   <FirstName>XYZ</FirstName>
   </Demographics>
   <Married>YES</Married>
</Person>

The XStream code is as follows:

    final XStream xstream = new XStream();
    xstream.alias("Person", Map.class);
    xstream.alias("Demographics", Map.class);
    xstream.registerConverter(new MapEntryConverter());

    final Map<String, Object> map2 = (Map<String, Object>) xstream.fromXML(xml);//where xml is above defined string.

The custom MapEntryConverter is:

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

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

    public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context)
    {
        final Map<String, String> map = new HashMap<String, String>();
        while (reader.hasMoreChildren())
        {
            reader.moveDown();
            map.put(reader.getNodeName(), reader.getValue());
            reader.moveUp();
        }
        return map;
    }
}

So the map now only consists of ID and Married as key-value pairs. Its not converting Demographics parent into its corresponding name value pairs.

I would like to have all the tag names as keys and their values as map values.

1 Answer 1

2

Make use of the convertAnother method on the MarshallingContext to handle the hierarchical nature of the data, e.g.:

public class MapEntryConverter implements Converter {

    public boolean canConvert(final Class clazz) {
        return Map.class.isAssignableFrom(clazz);
    }

    public void marshal(final Object value, final HierarchicalStreamWriter writer, final MarshallingContext context) {
        Map<String, Object> map = (Map<String, Object>) value;
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue() instanceof Map) {
                writer.startNode(entry.getKey());
                context.convertAnother(entry.getValue());
                writer.endNode();
            } else {
                writer.startNode(entry.getKey());
                writer.setValue(entry.getValue().toString());
                writer.endNode();
            }
        }
    }

    public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
        Map<String, Object> map = new HashMap<String, Object>();
        while (reader.hasMoreChildren()) {
            reader.moveDown();
            if (reader.hasMoreChildren()) {
                Map<String, Object> childMap = (Map<String, Object>) context.convertAnother(new HashMap<String, Object>(), Map.class);
                map.put(reader.getNodeName(), childMap);
            } else {
                map.put(reader.getNodeName(), reader.getValue());
            }

            reader.moveUp();
        }
        return map;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.