简体   繁体   English

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

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

I have 4 classes. 我有4节课。 Person class, and abstract ContactInformation with Phone and Address class extending it. 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 is used only as container: ContactInformation仅用作容器:

public abstract class ContactInfomation { /* empty class */ }

Phone class: Phone类:

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Phone extends ContactInfomation {
    @XmlElement(required = true, nillable = false)
    private String number;
}

And Address class: 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;
}

The problem is when I change @XmlElementrefs to @XmlElements in Person class, nothing happens. 问题是,当我改变@XmlElementrefs@XmlElementsPerson类,没有任何反应。 JAXB maps them to xs:choice . JAXB将它们映射到xs:choice The XML output is same as before and schemagen generates the same schema as before. XML输出与以前相同, schemagen生成与以前相同的模式。 Here is a sample output: 这是一个示例输出:

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

And here is the schema: 这是架构:

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

Documentation of @XmlElementRef uses it for Substitution group and XML choice. @XmlElementRef文档将其用于替换组和XML选择。 I'm completely confused what is the difference of @XmlElementRefs / @XmlElementRef and @XmlElements / @XmlElement . 我完全混淆了@XmlElementRefs / @XmlElementRef@XmlElements / @XmlElement的区别。 Can anyone help? 有人可以帮忙吗?

TL;DR TL; DR

Basic Differenece Between @XmlElement and @XmlElementRef @XmlElement@XmlElementRef之间的基本区别

The difference between @XmlElement and @XmlElementRef is if the corresponding generated element will contain a local element definition or a reference to a global element definition. @XmlElement@XmlElementRef之间的区别在于,相应的生成元素是否包含本地元素定义或对全局元素定义的引用。

Choice and Substitution Groups 选择和替代团体

Choice in XML Schema is really a superset of what can be done with substitution groups. XML Schema中的选择实际上是替换组可以完成的超集。 So to simplifiy the mapping JAXB leverages one mapping for both. 因此,为了简化映射,JAXB利用两个映射。

JAXB and Schema Generation JAXB和Schema Generation

JAXB can generated a Java model from any XML Schema, on the flip side JAXB does not preserve all metadata about the XML schema. JAXB可以从任何XML Schema生成Java模型,另一方面JAXB不保留有关XML模式的所有元数据。 Therefore JAXB can't generate every XML schema. 因此,JAXB无法生成每个XML架构。


@XmlElementRefs / @XmlElementRef and @XmlRootElement @XmlElementRefs / @XmlElementRef@XmlRootElement

Below is what you have in your model. 以下是您的模型中的内容。

Person

I have modified the mapping on the contacts field to make the mapping to the Address class more distinct. 我修改了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<>();

Phone 电话

When you map with @XmlElementRef the information you specify needs to correspond to a global element definition supplied by @XmlRootElement or @XmlElementDecl (see: http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html ). 使用@XmlElementRef进行映射时,您指定的信息需要与@XmlRootElement@XmlElementDecl提供的全局元素定义相对应(请参阅: http@XmlRootElement 。 HTML )。 By default the root element for the Person class with be person . 默认情况下, Person类的根元素为person

@XmlRootElement
public class Person {

Address 地址

I have used the @XmlRootElement annotation to override the default name for the Address class . 我使用了@XmlRootElement批注来覆盖Address class的默认名称。

@XmlRootElement(name="ADDRESS")
public class Address extends ContactInfomation {

Generated XML Schema 生成的XML架构

Here is the generated schema. 这是生成的架构。 We see that the element definitions within the choice structure leverage ref to reference an existing element instead of defining a local element. 我们看到, 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 @XmlElements / @XmlElement

I have changed the mapping on your contacts field to use @XmlElements . 我已将contacts字段上的映射更改为使用@XmlElements

Person

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

Phone 电话

None of the referenced classes are required to be annotated with @XmlRootElement (or have a corresponding @XmlElementDecl annotation. 所有引用的类都不需要使用@XmlRootElement注释(或者具有相应的@XmlElementDecl注释。

public class Phone extends ContactInfomation {

Address 地址

If he class does have an @XmlRootElement annotation it is not required to match the @XmlElement annotation within the @XmlElements . 如果他类确实有一个@XmlRootElement它不需要匹配注释@XmlElement的内注释@XmlElements

@XmlRootElement(name="ADDRESS")
public class Address extends ContactInfomation {

Generated XML Schema 生成的XML架构

Here is the generated schema. 这是生成的架构。 We see that the element definitions within the choice structure are now defined as local elements. 我们看到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