Java JAXB将@XmlElementRefs和@XmlElements转换为xs:choice

Java JAXB将@XmlElementRefs和@XmlElements转换为xs:choice,java,xml,jaxb,Java,Xml,Jaxb,我有四节课人员类,以及抽象的联系人信息,其中电话和地址类扩展了它 @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) public class Person { @XmlElement(required = true, nillable = false) private String first; @XmlElement(required = true, nillable = false) private St

我有四节课<代码>人员类,以及抽象的
联系人信息
,其中
电话
地址
类扩展了它

@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<>();
}
Phone
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;
}
地址
类别:

@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
类中将
@xmlementrefs
更改为
@xmlements
时,什么都没有发生
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>

马吉德
阿齐米
美国
洛杉矶
美国
纽约
5551037
下面是模式:

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

@xmlementref
的文档将其用于替换组和XML选择。我完全搞不清楚
@xmlementrefs
/
@xmlementref
@xmlements
/
@xmlementref
有什么区别。有人能帮忙吗?

TL;博士
@xmlementref
之间的基本区别

@xmlementref
@xmlementref
之间的区别在于相应生成的元素是否包含本地元素定义或对全局元素定义的引用

选择和替代组

XML模式中的选择实际上是替换组的超集。因此,为了简化映射,JAXB利用一个映射来实现两者

JAXB和模式生成

@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<>();
JAXB可以从任何XML模式生成Java模型,另一方面,JAXB并不保留关于XML模式的所有元数据。因此,JAXB不能生成所有XML模式


@xmlementrefs
/
@xmlementref
@XmlRootElement
以下是您的模型中的内容

@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<>();
我修改了
联系人
字段上的映射,以使到
地址
类的映射更加清晰

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

我使用了
@XmlRootElement
注释来覆盖
地址类的默认名称

@XmlRootElement(name="ADDRESS")
public class Address extends ContactInfomation {
生成的XML模式

下面是生成的模式。我们看到
选项
结构中的
元素
定义利用
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>
电话

引用的类都不需要用
@XmlRootElement
注释(或具有相应的
@XmlElementDecl
注释)

public class Phone extends ContactInfomation {
地址

如果类确实有
@XmlRootElement
注释,则不需要匹配
@XmlElement
中的
@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>