javaxml-parsingmarshallingxstreamdocument-root

Equivalent DROP_ROOT_MODE on XStream for XML conversion


I have a doubt whether it is possible to ignore the xml root element on a conversion form Object to XML with XStream, or if is there any way to replace the root element with other one, I mean:

I have a function to parse custom runtime-created objects to XML, something like:

public static String entityToXML(GenericResponseObject entity) {
    XStream xstream = new XStream(new StaxDriver());

    xstream.autodetectAnnotations(true);
    xstream.registerConverter(new GenericResponseAttributeConverter());
    String xml = xstream.toXML(entity);

    return xml;
}

For this, I have made a mess:

I have the GenericResponseObject and the GenericResponseAttribute clases, the idea is to have an object with as many custom attributes as needed on runtime:

@XStreamAlias("objectResult")
public class GenericResponseObject {

    @XStreamAlias("attributes")
    @XStreamImplicit
    private ArrayList<GenericResponseAttribute> attributes;

    public GenericResponseObject() {
        this.attributes = new ArrayList();
    }

    public void addAttribute(String name, Object value) {
        this.attributes.add(new GenericResponseAttribute(name, value));
    }
}

And the class GenericResponseAttribute:

@XStreamAlias("attribute")
public class GenericResponseAttribute {

    private String name;
    private Object value;

    public GenericResponseAttribute(String name, Object value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Object getValue() {
        return this.value;
    }

    public void setValue(Object value) {
        this.value = value;
    }
}

And as you can read, every class has their XStream annotations for aliasing and implicit lists, so, let me show you the custom converter I have made for the GenericResponseAttribute class:

public class GenericResponseAttributeConverter implements Converter {

    @Override
    public boolean canConvert(Class type) {
        return type.equals(GenericResponseAttribute.class);
    }

    @Override
    public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext mc) {
        GenericResponseAttribute value = (GenericResponseAttribute)o;
        writer.startNode(value.getName());
        mc.convertAnother(value.getValue());
        writer.endNode();
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext uc) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

So, if I build a GenericResponseObject on runtime, and parse it to XML with my static method, K get something like:

response = new GenericResponseObject();
response.addAttribute("user", "alex");
response.addAttribute("otherAtt", "TEST");
System.out.println(XMLUtil.entityToXML(response));

The result of the println() function is:

<objectResult>
    <attribute>
        <user>hugo</user>
    </attribute>
    <attribute>
        <otherAtt>TEST</otherAtt>
    </attribute>
</objectResult>

Which is almost what I want, but I really need to omit the root element on the GenericResponseAttribute class, its important to say that for the root node that I have shown above, there is always to exist only one node, the attribute name with the content of the attribute value. So, it is going to be a root element always if I delete the current one, for example, the result I need for the previos XML is:

<objectResult>
    <user>hugo</user>
    <otherAtt>TEST</otherAtt>
</objectResult>

My need is pretty basic, but I don't know how to get it right, I have searched and it seems there's not a method like deletRootNode() or replaceRootNode() in the HierarchicalStreamWriter class, and there's no @XStreamNoRoot or @XStreamMakeRoot annotations that I could use in the GenericResponseAttribute, so, thats why I'm asking here, please help me if you know how to do this.

Thanks.


Solution

  • By the moment I ended up using a String replacement after parsing the object to XML, I mean:

    public static String entityToXML(Object entity) {
        XStream xstream = new XStream(new StaxDriver());
    
        xstream.autodetectAnnotations(true);
        xstream.registerConverter(new GenericResponseAttributeConverter());
        String xml = xstream.toXML(entity);
    
        xml = xml.replace("<attribute>", "");
        xml = xml.replace("</attribute>", "");
    
        return xml;
    }
    

    But, that's not a pretty cool solution, if you have another one please tell me.

    Thanks.