JAXB преобразует @XmlElementRefs и @XmlElements в xs:выбор

у меня 4 классов. Person класс, и аннотация ContactInformation С Phone и Address класса, унаследованного от него.

@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 используется только в качестве контейнера:

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

Phone класс:

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

и Address класс:

@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;
}

проблема в том, когда я меняю @XmlElementrefs to @XmlElements на Person класс, ничего не происходит. JAXB отображает их в xs:choice. Вывод XML такой же, как и раньше, и schemagen генерирует одну и ту же схему как раньше. Вот пример вывода:

<?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>

и вот схема:

<?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>

документация @XmlElementRef использует его для группы подстановки и выбора XML. Я совершенно запутался, в чем разница @XmlElementRefs/@XmlElementRef и @XmlElements/@XmlElement. Кто-нибудь может помочь?

1 ответов


TL; DR

Основные Differenece Между @XmlElement и @XmlElementRef

разницу между @XmlElement и @XmlElementRef если соответствующий сгенерированный элемент будет содержать локальное определение элемента или ссылку на глобальное определение элемента.

группы выбора и замены

выбор в XML-схеме действительно является надмножеством того, что можно сделать с группами подстановки. Так simplifiy сопоставление JAXB использует одно отображение для обоих.

генерация JAXB и схемы

JAXB может генерировать модель Java из любой схемы XML, на обратной стороне JAXB не сохраняет все метаданные о схеме XML. Поэтому JAXB не может генерировать каждую XML-схему.


@XmlElementRefs/@XmlElementRef и @XmlRootElement

ниже-это то, что у вас есть в вашей модели.

человек

я изменил отображение на contacts поле для отображения в Address класс более отчетливыми.

@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<>();

телефон

когда вы сопоставляете с @XmlElementRef указанная вами информация должна соответствовать глобальному определению элемента, предоставленному @XmlRootElement или @XmlElementDecl (см.:http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html). По умолчанию корневой элемент для Person класс с be person.

@XmlRootElement
public class Person {

адрес

я использовал @XmlRootElement аннотация для переопределения имени по умолчанию для Address class.

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

сгенерированная XML-схема

вот сгенерированная схема. Мы видим, что element определения в пределах choice структура кредитного плеча ref для ссылки на существующий элемент вместо определения локальной элемент.

  <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/@XmlElement

я изменил отображение на