我有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
课程中将@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
的区别。有人可以帮忙吗?
答案 0 :(得分:10)
@XmlElement
和@XmlElementRef
之间的基本差异
@XmlElement
和@XmlElementRef
之间的区别在于相应的生成元素是否包含本地元素定义或对全局元素定义的引用。
选择和替换组
XML Schema中的选择实际上是替换组可以做什么的超集。因此,为了简化映射,JAXB为两者利用了一个映射。
JAXB和架构生成
JAXB可以从任何XML Schema生成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 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
我已将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
注释,则不需要匹配@XmlElement
中的@XmlElements
注释。
@XmlRootElement(name="ADDRESS")
public class Address extends ContactInfomation {
生成的XML架构
这是生成的架构。我们看到element
结构中的choice
定义现在定义为本地元素。
<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>