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
я изменил отображение на