Java – JAXB converts @ xmlelementrefs and @ xmlelements to XS: choice

I have four classes The person class, and the phone and address classes are used to extend its abstract contactinformation

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Person {
    @XmlElement(required = true,nillable = false)
    private String first;
    @XmlElement(required = true,nillable = false)
    private String last;
    @XmlElementWrapper(name = "contacts")
    @XmlElementRefs({
        @XmlElementRef(name = "phone",type = Phone.class,required = true),@XmlElementRef(name = "address",type = Address.class,required = true)
    })
    private final List<ContactInfomation> contacts = new ArrayList<>();
}

Contactinformation is used as a container only:

public abstract class ContactInfomation { /* empty class */ }

Telephone:

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Phone extends ContactInfomation {
    @XmlElement(required = true,nillable = false)
    private String number;
}

And address classes:

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Address extends ContactInfomation {
    @XmlElement(required = true,nillable = false)
    private String country;
    @XmlElement(required = true,nillable = false)
    private String city;
}

The problem is that when I change @ xmlelementrefs to @ xmlelements in the person class, there is no response JAXB maps them to XS: choice The XML output is the same as before, and schemagen generates the same schema as before This is an example output:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
    <first>majid</first>
    <last>azimi</last>
    <contacts>
        <address>
            <country>US</country>
            <city>Los Angles</city>
        </address>
        <address>
            <country>US</country>
            <city>New York</city>
        </address>
        <phone>
            <number>5551037</number>
        </phone>
    </contacts>
</person>

This is the architecture:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="address" type="address"/>

  <xs:element name="person" type="person"/>

  <xs:element name="phone" type="phone"/>

  <xs:complexType name="person">
    <xs:sequence>
      <xs:element name="first" type="xs:string"/>
      <xs:element name="last" type="xs:string"/>
      <xs:element name="contacts" minOccurs="0">
        <xs:complexType>
          <xs:sequence>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
              <xs:element ref="phone"/>
              <xs:element ref="address"/>
            </xs:choice>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="phone">
    <xs:complexContent>
      <xs:extension base="contactInfomation">
        <xs:sequence>
          <xs:element name="number" type="xs:string"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="contactInfomation" abstract="true">
    <xs:sequence/>
  </xs:complexType>

  <xs:complexType name="address">
    <xs:complexContent>
      <xs:extension base="contactInfomation">
        <xs:sequence>
          <xs:element name="country" type="xs:string"/>
          <xs:element name="city" type="xs:string"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
</xs:schema>

@The xmlelementref document uses it for substitution groups and XML selections I completely confused the difference between @ xmlelementrefs / @ xmlelementref and @ xmlelements / @ xmlelement Can I help you?

Solution

TL; DR

@The basic difference between xmlelement and @ xmlelementref

@The difference between xmlelement and @ xmlelementref is whether the corresponding generated element contains a local element definition or a reference to a global element definition

Selection and substitution groups

The choices in XML schema are actually supersets that can be completed by replacement groups Therefore, to simplify mapping, JAXB utilizes two mappings

JAXB and schema generation

JAXB can generate Java models from any XML schema. On the other hand, JAXB does not retain all metadata about XML schemas Therefore, JAXB cannot generate every XML schema

@Xmlelementrefs / @ xmlelementref and @ xmlrootelement

Here's what's in your model

people

I modified the mapping on the contact field to make the mapping to the address class clearer

@XmlElementWrapper(name = "contacts")
@XmlElementRefs({
    @XmlElementRef(name = "phone",@XmlElementRef(name = "ADDRESS",required = true)
})
private final List<ContactInfomation> contacts = new ArrayList<>();

Telephone

When mapping with @ xmlelementref, the specified information needs to correspond to the global element definition provided by @ xmlrootelement or @ xmlelementdecl (see: http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html ). by default, the root element of the person class is person

@XmlRootElement
public class Person {

address

I used the @ xmlrootelement annotation to override the default name of the address class

@XmlRootElement(name="ADDRESS")
public class Address extends ContactInfomation {

Generated XML schema

This is the generated schema We see that the element definition in the selection structure refers to an existing element instead of defining a local element

<xs:element name="contacts" minOccurs="0">
    <xs:complexType>
      <xs:sequence>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element ref="phone"/>
          <xs:element ref="ADDRESS"/>
        </xs:choice>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

@Xmlelements / @ of xmlelement

I've changed the mapping on the contact field to use @ xmlelements

people

@XmlElementWrapper(name = "contacts")
@XmlElements({
    @XmlElement(name = "phone-number",@XmlElement(name = "home-address",required = true)
})
private final List<ContactInfomation> contacts = new ArrayList<>();

Telephone

All referenced classes do not need to use the @ xmlrootelement annotation (or have the corresponding @ xmlelementdecl annotation)

public class Phone extends ContactInfomation {

address

If his class does have @ xmlrootelement annotation, you do not need to match the @ xmlelement annotation in @ xmlelements

@XmlRootElement(name="ADDRESS")
public class Address extends ContactInfomation {

Generated XML schema

This is the generated schema We see that the element definition in the selection structure is now defined as a local element

<xs:element name="contacts" minOccurs="0">
    <xs:complexType>
      <xs:sequence>
        <xs:choice maxOccurs="unbounded">
          <xs:element name="phone-number" type="phone"/>
          <xs:element name="home-address" type="address"/>
        </xs:choice>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>