@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和Schema Generation
JAXB可以从任何XML Schema生成Java模型,另一方面JAXB不保留有关XML模式的所有元数据.因此,JAXB无法生成每个XML架构.
@ XmlElementRefs / @ XmlElementRef和@XmlRootElement
以下是您的模型中的内容.
人
我修改了联系人字段上的映射,以使映射到Address类更加清晰.
@XmlElementWrapper(name = "contacts") @XmlElementRefs({ @XmlElementRef(name = "phone",@XmlElementRef(name = "ADDRESS",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架构
这是生成的架构.我们看到选择结构中的元素定义利用引用现有元素而不是定义局部元素.
<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的
我已将联系人字段上的映射更改为使用@XmlElements.
人
@XmlElementWrapper(name = "contacts") @XmlElements({ @XmlElement(name = "phone-number",@XmlElement(name = "home-address",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架构
这是生成的架构.我们看到选择结构中的元素定义现在被定义为局部元素.
<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>