Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB annotations for nested element lists

Tags:

java

xml

jaxb

I have the following XML:

<mappings>
    <mapping>
        <parameter attr = "value">asdas</parameter>
        <parameter attr = "value2">d123asdsad</parameter>
        <parameter attr = "value3">0</parameter>
    </mapping>
    <mapping>
        <parameter attr = "value">23123s</parameter>
        <parameter attr = "value2">qwerty</parameter>
        <!-- more parameter elements -->
    </mapping>
    <!-- more mapping elements -->
</mappings>

I have the following java classes to map it to:

@XmlRootElement(name = "mappings")
public class Mappings { 
    @XmlElement(name = "mapping")
    private List<Mapping> mMappings;

    public List<Mapping> getMappings() {
        return mMappings;
    }

    public void setMappings(List<Mapping> aMappings) {
        this.mMappings = aMappings;
    }
}

public class Mapping {
    @XmlElement(name = "parameter")
    private List<Parameter> mParameters;

    public List<Parameter> getParameters() {
        return mParameters;
    }

    public void setParameters(List<Parameter> aParameters) {
        this.mParameters = aParameters;
    }
}

public class Parameter {
    @XmlAttribute(name = "attr")
    private String mName;

    @XmlValue
    private String mValue;

    public String getName() {
        return mName;
    }

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

    public String getValue() {
        return mValue;
    }

    public void setValue(String aValue) {
        this.mValue = aValue;
    }
}

When I try to unmarshall it with

JAXBContext context = JAXBContext.newInstance(BundleMappings.class);
Unmarshaller um = context.createUnmarshaller();
mappings = (BundleMappings)um.unmarshal(new File(myFile));

I get this error

If a class has @XmlElement property, it cannot have @XmlValue property.

I need parameter to have both the 'attr' attribute and content, so what am I doing wrong?

like image 666
Sotirios Delimanolis Avatar asked Jan 07 '13 19:01

Sotirios Delimanolis


People also ask

What is XmlAccessorType?

Annotation Type XmlAccessorTypeControls whether fields or Javabean properties are serialized by default. Usage. @XmlAccessorType annotation can be used with the following program elements: package. a top level class.

What is the use of @XmlElement?

A JavaBean property, when annotated with @XmlElement annotation is mapped to a local element in the XML Schema complex type to which the containing class is mapped.

What is JAXB in Java?

Bind the Schema. JAXB simplifies access to an XML document from a Java program by presenting the XML document to the program in a Java format. The first step in this process is to bind the schema for the XML document into a set of Java classes that represents the schema.


1 Answers

By default JAXB (JSR-222) implementations consider public properties (get/set methods) and annotated fields as mapped (and separate). The default mapping is @XmlElement so your properties will be considered as mapped this way.

Solution #1

Since you are annotating the fields you need to add @XmlAccessorType(XmlAccessType.FIELD) on your classes.

@XmlAccessorType(XmlAccessType.FIELD)
public class Parameter {
    @XmlAttribute(name = "attr")
    private String mName;

    @XmlValue
    private String mValue;

    public String getName() {
        return mName;
    }

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

    public String getValue() {
        return mValue;
    }

    public void setValue(String aValue) {
        this.mValue = aValue;
    }
}

Solution #2

Annotate the get (or set) methods.

public class Parameter {
    private String mName;

     private String mValue;

    @XmlAttribute(name = "attr")
    public String getName() {
        return mName;
    }

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

    @XmlValue
    public String getValue() {
        return mValue;
    }

    public void setValue(String aValue) {
        this.mValue = aValue;
    }
}

For More Information

  • http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
  • http://blog.bdoughan.com/2011/06/jaxb-and-complex-types-with-simple.html

UPDATE

You will also need to use the @XmlElement annotation on the mappings property to specify the element name should be mapping.

@XmlRootElement(name = "mappings")
public class Mappings { 
    private List<Mapping> mMappings;

    @XmlElement(name="mapping")
    public List<Mapping> getMappings() {
        return mMappings;
    }

    public void setMappings(List<Mapping> aMappings) {
        this.mMappings = aMappings;
    }
}
like image 65
bdoughan Avatar answered Oct 21 '22 04:10

bdoughan