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
JAXB converts @XmlElementRefs and @XmlElements to xs:choice
提问by Majid Azimi
I have 4 classes. Person
class, and abstract ContactInformation
with Phone
and Address
class extending it.
我有4节课。Person
类和抽象ContactInformation
与Phone
和Address
类扩展它。
@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. JAXB
maps them to xs:choice
. The XML output is same as before and schemagen
generates the same schema as before.
Here is a sample output:
问题是,当我换@XmlElementrefs
到@XmlElements
的Person
类,没有任何反应。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 @XmlElementRef
uses it for Substitution group and XML choice. I'm completely confused what is the difference of @XmlElementRefs
/@XmlElementRef
and @XmlElements
/@XmlElement
. Can anyone help?
的文档@XmlElementRef
使用它来替换组和XML的选择。我完全困惑@XmlElementRefs
/@XmlElementRef
和@XmlElements
/的区别是什么@XmlElement
。任何人都可以帮忙吗?
采纳答案by bdoughan
TL;DR
TL; 博士
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. 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
/@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). By default the root element for the Person
class with be person
.
当您使用@XmlElementRef
您指定的信息进行映射时,需要对应于由@XmlRootElement
or提供的全局元素定义@XmlElementDecl
(请参阅:http: //blog.bdoughan.com/2012/07/jaxb-and-root-elements.html)。默认情况下,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.
这是生成的架构。我们看到,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>