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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20873523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 04:56:03  来源:igfitidea点击:

JAXB converts @XmlElementRefs and @XmlElements to xs:choice

javaxmljaxb

提问by Majid Azimi

I have 4 classes. Personclass, and abstract ContactInformationwith Phoneand Addressclass extending it.

我有4节课。Person类和抽象ContactInformationPhoneAddress类扩展它。

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

ContactInformationis used only as container:

ContactInformation仅用作容器:

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

Phoneclass:

Phone班级:

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

And Addressclass:

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 @XmlElementrefsto @XmlElementsin Personclass, nothing happens. JAXBmaps them to xs:choice. The XML output is same as before and schemagengenerates the same schema as before. Here is a sample output:

问题是,当我换@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>

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 @XmlElementRefuses it for Substitution group and XML choice. I'm completely confused what is the difference of @XmlElementRefs/@XmlElementRefand @XmlElements/@XmlElement. Can anyone help?

的文档@XmlElementRef使用它来替换组和XML的选择。我完全困惑@XmlElementRefs/@XmlElementRef@XmlElements/的区别是什么@XmlElement。任何人都可以帮忙吗?

采纳答案by bdoughan

TL;DR

TL; 博士

Basic Differenece Between @XmlElementand @XmlElementRef

@XmlElement和之间的基本区别@XmlElementRef

The difference between @XmlElementand @XmlElementRefis 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. So to simplifiy the mapping JAXB leverages one mapping for both.

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

JAXB and Schema Generation

JAXB 和模式生成

JAXB can generated a Java model from any XML Schema, on the flip side JAXB does not preserve all metadata about the XML schema. Therefore JAXB can't generate every XML schema.

JAXB 可以从任何 XML 模式生成 Java 模型,另一方面,JAXB 不保留有关 XML 模式的所有元数据。因此 JAXB 不能生成每个 XML 模式。



@XmlElementRefs/@XmlElementRefand @XmlRootElement

@XmlElementRefs/@XmlElementRef@XmlRootElement

Below is what you have in your model.

以下是您的模型中的内容。

Person

I have modified the mapping on the contactsfield to make the mapping to the Addressclass 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 @XmlElementRefthe information you specify needs to correspond to a global element definition supplied by @XmlRootElementor @XmlElementDecl(see: http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html). By default the root element for the Personclass with be person.

当您使用@XmlElementRef您指定的信息进行映射时,需要对应于由@XmlRootElementor提供的全局元素定义@XmlElementDecl(请参阅:http: //blog.bdoughan.com/2012/07/jaxb-and-root-elements.html)。默认情况下,Person类的根元素为person

@XmlRootElement
public class Person {

Address

地址

I have used the @XmlRootElementannotation 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 elementdefinitions within the choicestructure leverage refto 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 contactsfield 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 @XmlElementDeclannotation.

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

public class Phone extends ContactInfomation {

Address

地址

If he class does have an @XmlRootElementannotation it is not required to match the @XmlElementannotation 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 elementdefinitions within the choicestructure are now defined as local elements.

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