繁体   English   中英

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

[英]JAXB converts @XmlElementRefs and @XmlElements to xs:choice

我有4节课。 Person类,以及使用PhoneAddress类扩展它的抽象ContactInformation

@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@XmlElementsPerson类,没有任何反应。 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的区别。 有人可以帮忙吗?

TL; DR

@XmlElement@XmlElementRef之间的基本区别

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

选择和替代团体

XML Schema中的选择实际上是替换组可以完成的超集。 因此,为了简化映射,JAXB利用两个映射。

JAXB和Schema Generation

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@XmlRootElement 。 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架构

这是生成的架构。 我们看到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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM