我有 4 个类(class)。 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 */ }
电话
类:
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Phone extends ContactInfomation {
@XmlElement(required = true, nillable = false)
private String number;
}
和地址
类:
@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;
}
问题是当我在 Person
类中将 @XmlElementrefs
更改为 @XmlElements
时,没有任何反应。 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
有什么区别。谁能帮忙?
最佳答案
长话短说
@XmlElement
和 @XmlElementRef
之间的基本区别
@XmlElement
和 @XmlElementRef
之间的区别在于相应生成的元素将包含局部元素定义还是对全局元素定义的引用。
选择和替换组
XML Schema 中的选择实际上是使用替换组可以完成的操作的超集。因此,为了简化映射,JAXB 为两者都利用了一个映射。
JAXB 和架构生成
JAXB 可以从任何 XML 模式生成 Java 模型,另一方面,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
类的根元素为 person
。
@XmlRootElement
public class Person {
地址
我使用了 @XmlRootElement
注释来覆盖 Address 类
的默认名称。
@XmlRootElement(name="ADDRESS")
public class Address extends ContactInfomation {
生成的 XML 架构
这是生成的架构。我们看到 choice
结构中的 element
定义利用 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
我已将您的 contacts
字段上的映射更改为使用 @XmlElements
。
人
@XmlElementWrapper(name = "contacts")
@XmlElements({
@XmlElement(name = "phone-number", type = Phone.class, required = true),
@XmlElement(name = "home-address", type = Address.class, required = true)
})
private final List<ContactInfomation> contacts = new ArrayList<>();
电话
所有引用的类都不需要使用 @XmlRootElement
进行注释(或具有相应的 @XmlElementDecl
注释。
public class Phone extends ContactInfomation {
地址
如果他的类确实有一个 @XmlRootElement
注释,则不需要在 @XmlElements
中匹配 @XmlElement
注释。
@XmlRootElement(name="ADDRESS")
public class Address extends ContactInfomation {
生成的 XML 架构
这是生成的架构。我们看到 choice
结构中的 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>
关于java - JAXB 将@XmlElementRefs 和@XmlElements 转换为 xs :choice,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20873523/