mercredi 5 août 2015

Ran into error "If a class has @XmlElement property, it cannot have @XmlValue property."


I know this looks like a common issue and I looked through sf but it'd appear that not many of the cases fit my shoe.

In my case, it's about the two forms of data under one xsd definition.

XSD:

  <xs:element name="Person">
    <xs:complexType mixed="true">
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="name"/>
        <xs:element ref="address1"/>
        <xs:element ref="address2"/>
        <xs:element ref="address3"/>
      </xs:choice>
      <xs:attribute name="Key" type="xs:NCName"/>
    </xs:complexType>
  </xs:element>

And the xml based on it has two types of data:

1

<Person Key="Y">some name</Person>

2.

<Person>
<name>some name</name>
<address1>some where</address1>
<address2>some road</address2>
<address3>some house</address3>
</Person>

So if I use Eclipse to generate the java bean it would look like this:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "content"
})
@XmlRootElement(name = "Person")
public class Person{

    @XmlElementRefs({
        @XmlElementRef(name = "name", type = JAXBElement.class, required = false),
        @XmlElementRef(name = "address1", type = JAXBElement.class, required = false),
        @XmlElementRef(name = "address2", type = JAXBElement.class, required = false),
        @XmlElementRef(name = "address3", type = JAXBElement.class, required = false)
    })
    @XmlMixed
    protected List<Serializable> content;
    @XmlAttribute(name = "Key")
    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
    @XmlSchemaType(name = "NCName")
    protected String key;

It will work without any errors whatsoever, but in a very ugly way since all the string attributes like name and address will be wrapped up as a Serializable/JAXBElement, which is really unnecessary in my opinion.

So I tried to modify the xsd by:

  1. change <xs:choice> to <xs:sequence>;
  2. Removed mixed = "true".

    Just to get a normal java bean with attributes like this:

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "name",
        "address1",
        "address2",
        "address3"
    }) @XmlRootElement(name = "Person")
        public class Person{
    
            @XmlElement(name = "name", required = true)
            protected String name;
            @XmlElement(name = "address1", required = true)
            protected String address1;
            @XmlElement(name = "address2", required = true)
            protected String address2;
            @XmlElement(name = "address3", required = true)
            protected String address3;
            @XmlAttribute(name = "Key")
            @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
            @XmlSchemaType(name = "NCName")
            protected String key;
    
    

As expected, the 1st type of data <Person Key="Y">some name</Person> wouldn't be able to get content "some name" as the java bean does not contain attribute "content" anymore.

But When I manually added "content" with annotation @XmlValue, it threw the error "If a class has @XmlElement property, it cannot have @XmlValue property."

So finally I get to my question:), to work in a more elegant way as I proposed, what can we do here?



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire