JAXB-2 JAXB Annotation 註解

2 JAXB Annotation 註解

Java 對象樹和 XML 文檔都具備層級結構,JAXB 通過註解(Annotation)對 Java 對象樹和 XML 文檔的層級結構進行關聯;每一個 Java 類都可以對應到一個 XML 節點,Java 類中的字段(field)或屬性(get/set)都可以標識爲 XML 中的元素(element)或屬性(attribute)。
該章節,將會了解 JAXB 註解(Annotation) 的應用場景。

Annotation
Java Class Object
XML Doc

2.1 根節點註解 @XmlRootElement

@XmlRootElement 類級別的註解。將類映射爲xml全局元素,也就是根元素。如果要使用 JAXB ,則該註解必不可少

2.1.1 參數說明

@XmlRootElement(name="NodeName", namespace="http://www.w3cschool.org/jaxb2")
  • 參數: name
    默認值: 類名首字母小寫(小駝峯)
    說明:name屬性用於指定生成元素的名字,若不指定,默認使用類名小寫作爲元素名。
  • 參數: namespace
    默認值:不顯示
    說明:namespace屬性用於指定生成的元素所屬的命名空間。 namespace 命名空間是 XML 用於區分同名節點的方式之一;引用:XML namespace

2.1.2 使用情景

1、若不指定 XmlRootElement 的 name 參數,默認使用類名首字母小寫(小駝峯)作爲元素名。

@XmlRootElement
public class Student {
    private String name;
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

生成的XML如下:

<student>
    <name>Tom</name>
    ...
</student>

對應的 XML Schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="studentA" type="Student"/>
    <xs:complexType name="Student">
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

2、若指定 XmlRootElement 的 name 屬性,則使用 name 指定的名稱;

@XmlRootElement(name = "MyStudent")
public class Student {
    private String name;
    // getters, setters
    ... ...
}

生成的XML如下:

<MyStudent>
    <name>Tom</name>
    ...
</MyStudent>

對應的 XML Schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="MyStudent" type="Student"/>
    <xs:complexType name="Student">
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

特別地,name 屬性支持非 ASCII 碼;

@XmlRootElement(name = "學生")
public class Student {
    private String name;
    // getters, setters
    ... ...
}

生成的XML如下:

<學生>
    <name>Tom</name>
    ...
</學生>

對應的 XML Schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="學生" type="Student"/>
    <xs:complexType name="Student">
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

注:schema 生成 Java 對應的 xml(帶中文元素),需要變更 Java 文件的編碼格式。

3、namespace屬性用於指定生成的元素所屬的命名空間。
namespace 屬性一般應用在複雜的對象樹和XML文檔處理,由於可以使用 name 屬性變更對象字段或屬性在 XML 的名稱,如果出現 XML 元素名稱一致但對應的 Java 對象類型不一致時,就需要使用 namespace 屬性來限定其中一個 XML 元素,告訴 JAXB 使用該 namespace 所屬的 Java 類對 XML 元素進行解析。
下面演示 namespace 屬性對應的 XML 文檔:

@XmlRootElement(name="Student", namespace="http://www.w3cschool.org/jaxb2")
public class StudentA {
    private String id;
    // getters, setters
    ... ...
}

生成的XML如下:

<ns2:Student xmlns:ns2="http://www.w3cschool.org/jaxb2">
    <ns2:age>22</ns2:age>
    ...
</ns2:Student>

對應的 XSD Schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.w3cschool.org/jaxb2"
           xmlns:self="http://www.w3cschool.org/jaxb2"
           elementFormDefault="qualified">
    <xs:element name="student" type="self:Student"/>
    <xs:complexType name="Student">
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

使用 targetNamespace 將複雜類型 Student 定義在指定命名空間"http://www.w3cschool.org/jaxb2";
定義對命名空間 “http://www.w3cschool.org/jaxb2” 的引用 xmlns:self,在定義元素時,就可以使用在該命名空間的類型 “self:Student”.

下面演示通過 namespace 屬性區分不同的 XML 元素。
StudentA.java 類,

public class StudentA {
    private String name;
	// getters, setters
}

Student.java 類,包含 StudentA.java 實例,該實例的 XML 元素名稱爲 student。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Student {
	@XmlAttribute
    private String id;
    @XmlElement(name="student", namespace="http://abcwww.w3cschool.org/jaxb2")
    private StudentA studentA;
    // getters, setters
}    

Student.java 對應的 XML 如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student id="001" xmlns:ns2="http://www.w3cschool.org/jaxb2">
    <age>22</age>
    <name>Tom</name>
    <ns2:student>
        <name>Tom</name>
    </ns2:student>
</student>

從以上 XML 中可以看出,使用 ns2 前綴對 StudentA.java 的元素進行限定。
對應的 xsd schema 如下:
1、在命名空間 “http://www.w3cschool.org/jaxb2” 的 xsd 文件定義嵌套的 student 類型

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.w3cschool.org/jaxb2"
           elementFormDefault="qualified">
    <xs:complexType name="Student">
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

2、將以上xsd的命名空間引入新的xsd文件,在創建嵌套 student 時,使用以上的命名空間中的student類型。

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:self="http://www.w3cschool.org/jaxb2"
           elementFormDefault="qualified">
	<xs:element name="student" type="studentType"/>
	<xs:complexType name="studentType">
	  <xs:sequence>
	    <xs:element type="xs:string" name="age"/>
	    <xs:element type="xs:string" name="name"/>
	    <xs:element name="student" type="self:Student"/>
	  </xs:sequence>
	  <xs:attribute type="xs:string" name="id"/>
	</xs:complexType>
</xs:schema>

拓展:JAXB轉換對象到XML前綴 ns2:
ns2其實是Marshaller 在轉換的時候爲未定義的ELEMENT自動生成的一個前綴,因爲xml文件裏面每一個節點都需要有明確的命名空間,也就是定義這個節點的xsd,否則就像類沒有所屬的jar包一樣沒有明確的意義。

2.2 @XmlType

@XmlType 類級別的註解,該註解一般由 JAXB XJC 工具根據 XSD 文檔生成;常與@XMLRootElement,@XmlAccessorType一起使用。

2.2.1 參數說明

@XmlType(name = "personinfo", propOrder = {"firstname" ,"lastname"})
  • 參數:name
    默認值:
    說明:定義 XML Schema 中 type 的名稱
  • 參數:namespace
    默認值:
    說明:指定Schema中的命名空間
  • 參數:propOrder
    默認值:
    說明:指定映射XML時的節點順序,使用該屬性時,必須列出JavaBean對象中的所有字段,否則會報錯。
  • 參數:factoryClass
    默認值:
    說明:指定 UnMarshal 時生成映射類實例所需的工廠類,默認爲這個類本身
  • 參數:factoryMethod
    默認值:
    說明:指定工廠類的工廠方法

2.2.2 使用情景

1、name 屬性來自 XML Schema
引用:schema-complex
定義 Schema Complex Type(複合元素)時,需要爲此指定元素名稱;複合元素指包含其他元素及/或屬性的 XML 元素。

請看這個複合 XML 元素,“employee”,僅包含其他元素:

<employee>
  <firstname>John</firstname>
  <lastname>Smith</lastname>
</employee> 

在 XML Schema 中,我們有兩種方式來定義複合元素:

1) 通過命名此元素,可直接對"employee"元素進行聲明,就像這樣:

<xs:element name="employee">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="firstname" type="xs:string"/>
      <xs:element name="lastname" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element> 

假如您使用上面所描述的方法,那麼僅有 “employee” 可使用所規定的複合類型。請注意其子元素,“firstname” 以及 “lastname”,被包圍在指示器 <sequence>中。這意味着子元素必須以它們被聲明的次序出現。

經由 JAXB XJC 工具生成的 Java 類一般如下:

@XMLRootElement(name = "employee")
@XmlType(propOrder = {"firstname" ,"lastname"})
public class Employee {
    private String firstname;
    private String lastname;
    ...
}

由於是內嵌的複雜類型,@XmlType 的 name 屬性爲 “”。

2) “employee” 元素可以使用 type 屬性,這個屬性的作用是引用要使用的複合類型的名稱:

<xs:element name="employee" type="personinfo"/>

<xs:complexType name="personinfo">
  <xs:sequence>
    <xs:element name="firstname" type="xs:string"/>
    <xs:element name="lastname" type="xs:string"/>
  </xs:sequence>
</xs:complexType> 

同樣的,JAXB 的 XJC 工具會生成如下的 Java 類:

@XMLRootElement(name = "employee")
@XmlType(name = "personinfo", propOrder = {"firstname" ,"lastname"})
public class Employee {
    private String firstname;
    private String lastname;
    ...
}

此時,獨立的複雜類型,@XmlType 的 name 屬性填充 schema 中複雜類型的名稱 “personinfo”。

2、propOrder 屬性指定映射XML時的節點順序
注意:使用該屬性時,必須列出JavaBean對象中的所有字段,否則會報錯。

@XMLRootElement
@XmlType(propOrder = {"id" ,"age", "name"})
public class TeacherA {
    private String id;
    private String name;
    private Integer age;
    ...
}

生成的XML如下,生成的順序是按照propOrder:

<teacherA>
    <id>001</id>
    <age>22</age>
    <name>Tom</name>
</teacherA>

@XmlType 的 propOrder 屬性,一般用於接口參數,服務端可以根據參數的強有序生成相關的校驗碼(如 MD5 等),用於驗證接口訪問的合法性等。

2.3 @XmlAccessorType

@XmlAccessorType 類級別的註解。定義這個類中的何種類型需要映射到XML。類的類型包括字段(field)、屬性(get/set 方法)。該註解將會影響類內部註解的使用方式,如 XmlElement, XmlAttribute等。

2.3.1 參數說明

@XmlAccessorType(XmlAccessType.FIELD)
  • 參數:value
    默認值:XmlAccessType.PUBLIC_MEMBER
    說明:參數 value 可以接受4個指定值,這幾個值是枚舉類型,方便調用:
    • XmlAccessType.FIELD:映射這個類中的所有字段到XML
    • XmlAccessType.PROPERTY:映射這個類中的屬性(get/set方法)到XML
    • XmlAccessType.PUBLIC_MEMBER:將這個類中的所有public的field或property同時映射到XML(默認)
    • XmlAccessType.NONE:不映射

2.3.2 使用情景

使用以下的 XML 作爲需求,現在需要編寫 Java Bean Class 對此進行轉換。

<employee>
  <firstname>John</firstname>
  <lastname>Smith</lastname>
</employee> 

1、value 屬性默認 XmlAccessType.PUBLIC_MEMBER

@XmlRootElement
public class Student {
	@XmlElement(name = "firstname")
    public String firstname;
	private String lastname;
	@XmlElement(name = "lastname")
	public String getLastname(){ return lastname; }
	public void setLastname(String lastname){ this.lastname = lastname; }
}

@XmlAccessType 的默認 value 屬性值爲 XmlAccessType.PUBLIC_MEMBER,會對該類的所有 public 字段(field)或屬性(property)進行 XML 的裝換,此時可以對 firstname 和 get/set 屬性進行 XmlEelement 註解的自定義設置。

2、value 屬性使用 XmlAccessType.FIELD

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Student {
	@XmlElement(name = "firstname")
    private String firstname;
    @XmlElement(name = "lastname")
	private String lastname;
    public String getFirstname(){ return firstname; }
	public void setFirstname(String firstname){ this.firstname = firstname; }
	public String getLastname(){ return lastname; }
	public void setLastname(String lastname){ this.lastname = lastname; }
}

使用 XmlAccessType.FIELD 的 @XmlAccessType,會使代碼有更簡潔的閱讀性;此時只可以對 firstname 和 lastname 字段進行 XmlElement 自定義註解配置。
注:xjc 工具對 schema 文件生成的 Java 代碼,默認使用該 XmlAccessType.FIELD 值。

3、value 屬性值使用 XmlAccessType.PROPERTY

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Student {
    private String firstname;
	private String lastname;
	@XmlElement(name = "firstname")
    public String getFirstname(){ return firstname; }
	public void setFirstname(String firstname){ this.firstname = firstname; }
	@XmlElement(name = "lastname")
	public String getLastname(){ return lastname; }
	public void setLastname(String lastname){ this.lastname = lastname; }
}

使用 XmlAccessType.PROPERTY 的 @XmlAccessType,映射這個類中的屬性(get/set方法)到 XML;此時,只能對 get/set 屬性進行 XmlElement 註解的自定義配置。

2.4 節點標註 @XmlElement

@XmlElement 字段,方法,參數級別的註解。該註解可以將被註解的(非靜態)字段,或者被註解的get/set方法對應的字段映射爲本地元素,也就是子元素。

2.4.1 參數說明

@XmlElement(name = "", defaultValue = "", nillable = false, required = false)
  • 參數:name
    默認值:
    說明:用於指定映射時的節點名稱,指定生成元素的名字,若不指定,默認使用方法名小寫作爲元素名。
  • 參數:namespace
    默認值:
    說明:指定映射時的節點命名空間
  • 參數:required
    默認值:false
    說明:字段是否必須,默認爲false
  • 參數:nillable
    默認值:false
    說明:是否處理空數據,默認爲false;默認某一對象字段/屬性不進行賦值,不會生成對應的 XML 元素。
  • 參數:type
    默認值:
    說明:定義該字段或屬性的關聯類型,通過檢索類級別註解 @XmlType 的 name 屬性進行關聯;
  • 參數:defaultValue
    默認值:
    說明:節點的默認值

2.4.2 使用場景

1、使用自定義的節點名稱

@XmlRootElement
public class Grade {
    private String id;
    private String name;
    @XmlElement(name = "名稱", defaultValue = "一年級", nillable = true, required = true)
    public void setName(String name) {
        this.name = name;
    }
    ...
}

正常情況下得到的XML數據結構:

<grade>
    <id>1001</id>
    <名稱>二年級</名稱>
    <ranking>1</ranking>
</grade>

對應的 XSD Schema.

<xs:element name="姓名" type="xs:string" nillable="true" default="一年級"/>

或者提供別名

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified">
    <xs:element name="student" type="Student"/>

    <xs:element name="name" type="xs:string" nillable="false" default="Tom"/>
    <xs:element name="姓名" substitutionGroup="name"/>
    <xs:complexType name="Student">
        <xs:sequence>
            <xs:element ref="name"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

注:Schema 生成的 Java Bean XmlElement required 屬性默認爲 true,不提供屬性變更該值。
使用 xjc 對 schema 生成 Java 代碼,無法填充 XmlElement 的 name 屬性,當 element 出行非 ASCII 碼時,xjc 會生成對應的 get/set 屬性,此時需要變更相應的 Java 文件的編碼方式,如 GBK 等。

2、處理空數據
如果name是空值,轉換的 XML 將不會顯示該節點;如果標明 nillable=true,則當節點爲 null 時,XML 也會顯示該 null 信息;

@XmlRootElement
public class Grade {
    private String id;
    private String name;
    @XmlElement(nillable = true)
    public void setName(String name) {
        this.name = name;
    }
    ...
}
// Grade grade = new Grade("1002", null, 2);

得到的XML數據結構如下:

<grade>
    <id>1002</id>
    <name xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
    <ranking>2</ranking>
</grade>

2.5 節點屬性標註 @XmlAttribute

@XmlAttribute 字段和方法級別的註解。該註解會將字段或get/set方法對應的字段映射成本類對應元素的屬性。

2.5.1 參數說明

@XmlAttribute(name="" namespace="" required=false)
  • 參數:name
    默認值:
    說明:用於指定映射時的節點屬性名稱,若不指定,默認使用方法名小寫作爲元素名。
  • 參數:namespace
    默認值:
    說明:指定映射時的節點屬性命名空間
  • 參數:required
    默認值:false
    說明:該屬性是否必須,默認爲false

2.5.2 使用情景

@XmlRootElement
public class Desk {
    private String id;
    private String owner;
    @XmlAttribute
    public void setId(String id) {
        this.id = id;
    }
    ...
}

生成的XML如下:

<desk id="004">
    <owner>Tom</owner>
</desk>

2.6 節點不被映射 @XmlTransient

@XmlTrasient 類,字段,方法級別的註解。定義某一字段或屬性不需要被映射。該註解與所有其他JAXB註釋相互排斥,也就是說與其他註釋連用就會報錯。 和某些框架中的Ignore註解相同。
不能和其他註解合用

@XmlTransient
@XmlElement
public void setIsbn(String isbn) {
    this.isbn = isbn;
}
javax.xml.bind.DataBindingException: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
com.example.demo.lesson4.Book#isbn具有互相排斥的註釋 @javax.xml.bind.annotation.XmlTransient 和 @javax.xml.bind.annotation.XmlElement

沒有參數

@XmlTransient
private String isbn;

2.7 解組不匹配節點 @XmlAnyElement

引用:XmlAnyElement
字段和方法級別的註解。在將 xml 內容解組到 JAXB 註釋類的實例中時,此註釋充當 “catch-all” 屬性。它通常註釋多值的 JavaBean 屬性,但它也能夠出現在單值的 JavaBean 屬性中。在解組(UnMarshall)過程中,與類中用於其他 JavaBean 屬性的靜態 @XmlElement 或 @XmlElementRef 註釋不匹配的每個 xml 元素都將被添加到此 “catch-all” 屬性中。
在類及其超類中只能有一個 XmlAnyElement 註釋的 JavaBean 屬性。

class Foo {
	int a;
	int b;
	@XmlAnyElement
	List<Element> any;
}

它可以按如下方式解組實例:

<foo xmlns:e="extra">
	<a>1</a>
	<e:other />  // this will be bound to DOM, because unmarshalling is orderless
	<b>3</b>
	<e:other />
	<c>5</c>     // this will be bound to DOM, because the annotation doesn't remember namespaces.
</foo>

子類

class Bar extends Foo {
	int c;
	// Foo.getAny() also represents wildcard content for type definition bar.
}

它可以按如下方式解組實例:

<bar xmlns:e="extra">
	<a>1</a>
	<e:other />  // this will be bound to DOM, because unmarshalling is orderless
	<b>3</b>
	<e:other />
	<c>5</c>     // this now goes to Bar.c
	<e:other />  // this will go to Foo.any
</bar>

2.8 解組不匹配屬性 @XmlAnyAttribute

引用:XmlAnyAttribute

字段和方法級別的註解。將 JavaBean 屬性映射到通配符屬性的映射表中。
用法受到以下約束的限制:
最多隻能使用 @XmlAnyAttribute 註釋類中的一個字段或屬性。
屬性或字段的類型必須是 java.util.Map。
在處理將解組成爲一個值類的屬性時,與另一個 JavaBean 屬性不存在靜態關聯的(通過 XmlAttribute)每個屬性都被輸入 Map<QName,Object> 表示的通配符屬性映射表中。屬性 QName 是映射表的鍵。鍵值是屬性的字符串值。

2.9 @XmlRegistry

引用:XmlRegistry
標記具有 XmlElementDecl 的類。

2.10 @XmlElementDecl

引用:XmlElementDecl

Maps a factory method to a XML element.
Usage

The annotation creates a mapping between an XML schema element
declaration and a <i> element factory method </i> that returns a
JAXBElement instance representing the element
declaration. Typically, the element factory method is generated
(and annotated) from a schema into the ObjectFactory class in a
Java package that represents the binding of the element
declaration’s target namespace. Thus, while the annotation syntax(英 ['sɪntæks] 句法) allows @XmlElementDecl to be used on any method, semantically([sɪ’mæntɪkli] adv. 語義上) its use is restricted to annotation of element factory method.

The usage is subject to the following constraints:

  • The class containing the element factory method annotated with @XmlElementDecl must be marked with @XmlRegistry.
  • The element factory method must take one parameter assignable to Object.

Example 1: Annotation on a factory method

      // Example: code fragment
      @XmlRegistry
      class ObjectFactory {
          @XmlElementDecl(name="foo")
          JAXBElement<String> createFoo(String s) { ... }
      }
      <!-- XML input -->
      <foo>string</foo>
      // Example: code fragment corresponding to XML input
      JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
      Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
      JAXBElement o =
      (JAXBElement)unmarshaller.unmarshal(aboveDocument);
      // print JAXBElement instance to show values
      System.out.println(o.getName());   // prints  "{}foo"
      System.out.println(o.getValue());  // prints  "string"
      System.out.println(o.getValue().getClass()); // prints "java.lang.String"
      <!-- Example: XML schema definition -->
      <xs:element name="foo" type="xs:string"/>

以上代碼體現了兩個要點:
1、@XmlElementDecl 標註的方法,與 XML Schema 的元素 <element> 一一對應;
2、@XmlElementDecl 所在的方法,所在的類必須標註爲 @XmlRegistry

Example 2: Element declaration with non local scope

The following example illustrates the use of scope annotation parameter in binding of element declaration in schema derived code.

The following example may be replaced in a future revision of this javadoc.

      <!-- Example: XML schema definition -->
      <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:complexType name="pea">
          <xs:choice maxOccurs="unbounded">
            <xs:element name="foo" type="xs:string"/>
            <xs:element name="bar" type="xs:string"/>
          </xs:choice>
        </xs:complexType>
        <xs:element name="foo" type="xs:int"/>
      </xs:schema>
      // Example: expected default binding
      class Pea {
          @XmlElementRefs({
              @XmlElementRef(name="foo",type=JAXBElement.class)
              @XmlElementRef(name="bar",type=JAXBElement.class)
          })
          List<JAXBElement<String>> fooOrBar;
      }
 
      @XmlRegistry
      class ObjectFactory {
          @XmlElementDecl(scope=Pea.class,name="foo")
          JAXBElement createPeaFoo(String s);
 
          @XmlElementDecl(scope=Pea.class,name="bar")
          JAXBElement createPeaBar(String s);
 
          @XmlElementDecl(name="foo")
          JAXBElement createFoo(Integer i);
      }

Without scope createFoo and createPeaFoo would become ambiguous since both of them map to a XML schema element with the same local name “foo”.

以上介紹了 scope 參數的使用
1、@XmlElementRef 用來描述非限定集合元素 <xs:choice maxOccurs="unbounded">,表示該非限定集合值允許接收指定的類型;
2、當不同層級的 XML 標籤重名時,使用 @XmlElementRefscope 參數來明確次級 XML 標籤的上級節點類型;ObjectFactory 對象工廠類,聲明瞭如果解組 XML 中,在 Pea 節點下發現有名稱爲 foo 的節點,利用 createPeaFoo 方法進行將節點數據轉換爲 JAXBElement。

注:當使用可選元素標籤時 <xs:choice>,XML Schema 生成的代碼不包含 <xs:choice> 標籤限定:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <!-- Request XML -->
    <xsd:element name="callback-request" type="CallbackRequest"/>

    <xsd:complexType name="CallbackRequest">
        <xsd:choice>
            <xsd:element name="example-v1-params"      type="ExampleV1Params"/>
            <xsd:element name="example-v2-params"      type="ExampleV2Params"/>
        </xsd:choice>
    </xsd:complexType>
</xsd:schema>
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "CallbackRequest", propOrder = {
    "exampleV1Params",
    "exampleV2Params"
})
public class CallbackRequest {

    @XmlElement(name = "example-v1-params")
    protected ExampleV1Params exampleV1Params;
    @XmlElement(name = "example-v2-params")
    protected ExampleV2Params exampleV2Params;
}

@see XmlRegistry
@since JAXB 2.0

2.11 @XmlElementRefs

引用:XmlElementRefs
標記一個屬性,該屬性引用帶有 XmlElement 或 JAXBElement 的類。

與元素屬性(帶有 XmlElement 註釋的屬性)比較,引用屬性具有不同的替換語義。在將子類分配給屬性時,元素屬性將生成帶有 @xsi:type 的相同標記名稱,而引用屬性則生成一個不同的標記名稱(子類上的標記名稱)。

2.12 @XmlList

引用:XmlList

用來將屬性映射到列表簡單類型。

用法

@XmlList 註釋能夠與以下基礎數據元素(string, integer, double, …)一起使用:

  • JavaBean 屬性
  • 字段

在集合屬性僅使用 @XmlElement 進行註釋時,將通過元素包裝集合中的每一個項。例如,

 @XmlRootElement
 class Foo {
     @XmlElement
     List<String> data;
 }

將生成如下 XML:

<foo>
	<data>abc</data>
	<data>def</data>
</foo>

另一方面,@XmlList 註釋允許將多個值表示爲單個元素中以空格分隔的標記。例如,

@XmlRootElement
class Foo {
    @XmlElement
    @XmlList
    List<String> data;
}

上述代碼將生成如下 XML:

<foo>
	<data>abc def</data>
</foo>

2.13 XmlValue

引用:註釋類型 XmlValue
支持將類映射到帶有 simpleContent 的 XML 模式複雜類型或 XML 模式簡單類型。

  • 如果字段或屬性的類型是集合類型,那麼集合項類型必須映射到簡單模式類型。
  • 如果字段或屬性的類型不是集合類型,那麼類型必須映射到 XML 模式簡單類型。
  • 如果已註釋的 JavaBean 屬性是映射到 XML 模式構造的唯一類成員,那麼該類將被映射到一個簡單類型。
  • 如果存在映射到 XML 屬性的其他 JavaBean 屬性(使用 @XmlValue 註釋註釋的 JavaBean 除外),那麼類將被映射到帶有 simpleContent 的複雜類型。

示例 1:將類映射到 XML 模式 simpleType

// Example 1: Code fragment
public class USPrice {
   @XmlValue
   public java.math.BigDecimal price;
}
<!-- Example 1: XML Schema fragment -->
<xs:simpleType name="USPrice">
  <xs:restriction base="xs:decimal"/>
</xs:simpleType>
<!-- Example 1: XML fragment -->
<USPrice>12.0</USPrice>
<!-- Example 1: XML fragment without @XmlValue -->
<USPrice>
	<price>12.0</price>
</USPrice>

示例 2:將類映射到帶有 simpleContent的 XML 模式 complexType。

// Example 2: Code fragment
public class InternationalPrice {
    @XmlValue
    public java.math.BigDecimal price;

    @XmlAttribute
    public String currency;
}
<!-- Example 2: XML Schema fragment -->
<xs:complexType name="InternationalPrice">
  <xs:simpleContent>
    <xs:extension base="xs:decimal">
      <xs:attribute name="currency" type="xs:string"/>
    </xs:extension>
  </xs:simpleContent>
</xs:complexType> 
<!-- Example 2: XML fragment -->
<USPrice currency="1000.0">12.0</USPrice>
<!-- Example 2: XML fragment without @XmlValue -->
<USPrice currency="1000.0">
	<price>12.0</price>
</USPrice>

上一章:JAXB-1 JAXB 概述
目錄:學習 JAXB
下一章:JAXB-3 JAXB API


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章