Search code examples
javaxmlxml-parsingxml-serializationxstream

Reading list values using xstream


I am working with xstream to read some xml in the following format --

<Objects>
  <Object Type="System.Management.Automation.Internal.Host.InternalHost">
    <Property Name="Name" Type="System.String">ConsoleHost</Property>
    <Property Name="Version" Type="System.Version">2.0</Property>
    <Property Name="InstanceId" Type="System.Guid">7e2156</Property>
  </Object>
</Objects>

Basically under Objects tag there can be n number of Object Type and each Object Type can have n number of Property tags. So I have modelled by Java classes and the code to read it as follows --

class ParentResponseObject {    
    List <ResponseObject>responseObjects = new ArrayList<ResponseObject>();

}

@XStreamAlias("Object")
@XStreamConverter(value = ToAttributedValueConverter.class, strings = { "Value" })
class ResponseObject {  
    String Type;   
    String Value; 

    List <Properties> properties = new ArrayList<Properties>(); 
}

@XStreamAlias("Property")
@XStreamConverter(value = ToAttributedValueConverter.class, strings = { "Value" })
class Properties {
    String Name;
    String Type;
    String Value;
}
public class MyAgainTest {
    public static void main (String[] args) throws Exception {
        String k1 = //collect the xml as string            
        XStream s = new XStream(new DomDriver());       
        s.alias("Objects", ParentResponseObject.class);
        s.alias("Object",  ResponseObject.class);
        s.alias("Property", Properties.class); 
        s.useAttributeFor(ResponseObject.class, "Type");
        s.addImplicitCollection(ParentResponseObject.class, "responseObjects");     
        s.addImplicitCollection(ResponseObject.class, "properties");
        s.useAttributeFor(Properties.class, "Name");
        s.useAttributeFor(Properties.class, "Type");
    s.processAnnotations(ParentResponseObject.class);       
        ParentResponseObject gh =(ParentResponseObject)s.fromXML(k1);
        System.out.println(gh.toString());
    }
}

Using this code, I am able to populate the responseObjects List in the ParentResponseObject class. However, the properties list in the ResponseObject is always null, even though I am using the same technique in both the cases. Can anyone please help on getting this solved. Help on this is highly appreciated.


Solution

  • Your XML format does not match your Java object model. According to the XML, <Property> is a child of <Objects>, but according to your code, the Properties list is part of the ResponseObject. You need to fix this mismatch.

    Also, it seems that you are using a mix of annotations and code. Either use only annotations (recommended) or do it all in code. Otherwise, your code becomes confusing and unreadable.


    Update:

    I see you have fixed your XML. The problem is that you have a Value field in your ResponseObject, but there is no value in the xml element, so remove it.

    The following code should work:

    @XStreamAlias("Objects")
    public class ParentResponseObject {
    
        @XStreamImplicit
        List<ResponseObject> responseObjects = new ArrayList<ResponseObject>();
    }
    
    @XStreamAlias("Object")
    public class ResponseObject {
    
        @XStreamAsAttribute
        String Type;   
    
        @XStreamImplicit
        List<Properties> properties = new ArrayList<Properties>();
    }
    
    @XStreamAlias("Property")
    @XStreamConverter(value = ToAttributedValueConverter.class, strings = { "Value" })
    public class Properties {
        String Name;
        String Type;
        String Value;
    }
    

    Main method:

    XStream s = new XStream(new DomDriver());
    s.processAnnotations(ParentResponseObject.class);
    ParentResponseObject gh = (ParentResponseObject) s.fromXML(xml);
    
    for (ResponseObject o : gh.responseObjects) {
         System.out.println(o.Type);
         for (Properties p : o.properties) {
             System.out.println(p.Name + ":" + p.Type + ":" + p.Value);
         }
    }