XML-схема
Схема XML ниже содержит три корневых элемента: покупатель , адрес выставления счета и адрес доставки . Элемент customer имеет анонимный сложный тип, в то время как адрес выставления счета и адрес доставки имеют одинаковый именованный тип (тип адреса ).
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<?xml version="1.0" encoding="UTF-8"?><xs:schema elementFormDefault="qualified"> <xs:element name="customer"> <xs:complexType> <xs:sequence> <xs:element ref="billing-address"/> <xs:element ref="shipping-address"/> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="address-type"> <xs:sequence> <xs:element name="street" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:element name="billing-address" type="address-type"/> <xs:element name="shipping-address" type="address-type"/></xs:schema> |
Сгенерированная модель
Ниже приведена модель JAXB, созданная на основе схемы XML. Те же понятия применяются при добавлении аннотаций JAXB к существующей модели Java.
Клиент
Классы домена JAXB соответствуют сложным типам. Поскольку элемент customer имеет анонимный сложный тип, класс Customer имеет аннотацию @XmlRootElement . Это потому, что только один элемент XML может быть связан с анонимным типом.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package org.example.customer;import javax.xml.bind.annotation.*;@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "", propOrder = {"billingAddress","shippingAddress"})@XmlRootElement(name = "customer")public class Customer { @XmlElement(name = "billing-address", required = true) protected AddressType billingAddress; @XmlElement(name = "shipping-address", required = true) protected AddressType shippingAddress; public AddressType getBillingAddress() { return billingAddress; } public void setBillingAddress(AddressType value) { this.billingAddress = value; } public AddressType getShippingAddress() { return shippingAddress; } public void setShippingAddress(AddressType value) { this.shippingAddress = value; }} |
Тип адреса
Опять же, поскольку классы модели JAXB соответствуют сложным типам, класс создается для сложного типа адресного типа . Поскольку для этого именованного сложного типа могут существовать несколько элементов корневого уровня, это не аннотируется @XmlRootElement .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
package org.example.customer;import javax.xml.bind.annotation.*;@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "address-type", propOrder = {"street"})public class AddressType { @XmlElement(required = true) protected String street; public String getStreet() { return street; } public void setStreet(String value) { this.street = value; }} |
ObjectFactory
Аннотация @XmlElementDecl используется для представления корневых элементов, соответствующих именованным сложным типам. Он помещается в метод фабрики в классе, аннотированном @XmlRegistry (при создании из схемы XML этот класс всегда называется ObjectFactory ). Метод фабрики возвращает объект домена, завернутый в экземпляр JAXBElement. JAXBElement имеет QName, который представляет имя элемента и URI пространства имен.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package org.example.customer;import javax.xml.bind.JAXBElement;import javax.xml.bind.annotation.*;import javax.xml.namespace.QName;@XmlRegistrypublic class ObjectFactory { private final static QName _BillingAddress_QNAME = new QName("http://www.example.org/customer", "billing-address"); private final static QName _ShippingAddress_QNAME = new QName("http://www.example.org/customer", "shipping-address"); public ObjectFactory() { } public Customer createCustomer() { return new Customer(); } public AddressType createAddressType() { return new AddressType(); } public JAXBElement<AddressType> createBillingAddress(AddressType value) { return new JAXBElement<AddressType>(_BillingAddress_QNAME, AddressType.class, null, value); } public JAXBElement<AddressType> createShippingAddress(AddressType value) { return new JAXBElement<AddressType>(_ShippingAddress_QNAME, AddressType.class, null, value); }} |
Пакет-инфо
Класс package-info используется для определения сопоставления пространства имен (см. JAXB & Namespaces ).
|
1
2
3
4
|
package org.example.customer;import javax.xml.bind.annotation.*; |
Unmarshal Operation
Теперь мы рассмотрим влияние типа корневого элемента при демаршаллинге XML.
customer.xml
Ниже приведен пример XML-документа с клиентом в качестве корневого элемента. Помните, что элемент customer имел анонимный сложный тип.
|
1
2
3
4
5
6
7
8
9
|
<?xml version="1.0" encoding="UTF-8"?> <billing-address> <street>1 Any Street</street> </billing-address> <shipping-address> <street>2 Another Road</street> </shipping-address></customer> |
shipping.xml
Вот пример XML-документа с адресом доставки в качестве корневого элемента. Элемент shipping-address имеет названный комплексный тип.
|
1
2
3
4
|
<?xml version="1.0" encoding="UTF-8"?> <street>2 Another Road</street></shipping-address> |
Демарш Демо
При демаршировании XML, который соответствует классу, аннотированному @XmlRootElement, вы получаете экземпляр объекта домена. Но при демаршировании XML, который соответствует классу, аннотированному @XmlElementDecl, вы получаете объект домена, обернутый в экземпляр J AXBElement . В этом примере вам может понадобиться использовать QName из JAXBElement, чтобы определить, не выписали ли вы адрес для выставления счета или адрес доставки.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package org.example.customer;import java.io.File;import javax.xml.bind.*;public class UnmarshalDemo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance("org.example.customer"); Unmarshaller unmarshaller = jc.createUnmarshaller(); // Unmarshal Customer File customerXML = new File("src/org/example/customer/customer.xml"); Customer customer = (Customer) unmarshaller.unmarshal(customerXML); // Unmarshal Shipping Address File shippingXML = new File("src/org/example/customer/shipping.xml"); JAXBElement<AddressType> je = (JAXBElement<AddressType>) unmarshaller.unmarshal(shippingXML); AddressType shipping = je.getValue(); }} |
Демо Unmarshal — JAXBIntrospector
Если вы не хотите иметь дело с запоминанием, будет ли результатом операции unmarshal будет объект домена или JAXBElement , то вы можете использовать метод JAXBIntrospector.getValue (Object), чтобы всегда получать объект домена.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package org.example.customer;import java.io.File;import javax.xml.bind.*;public class JAXBIntrospectorDemo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance("org.example.customer"); Unmarshaller unmarshaller = jc.createUnmarshaller(); // Unmarshal Customer File customerXML = new File("src/org/example/customer/customer.xml"); Customer customer = (Customer) JAXBIntrospector.getValue(unmarshaller .unmarshal(customerXML)); // Unmarshal Shipping Address File shippingXML = new File("src/org/example/customer/shipping.xml"); AddressType shipping = (AddressType) JAXBIntrospector .getValue(unmarshaller.unmarshal(shippingXML)); }} |
Маршал Операция
Вы можете напрямую упорядочить объект, аннотированный @XmlRootElement, в XML. Классы, соответствующие аннотациям @XmlElementDecl, должны быть сначала помещены в экземпляр JAXBElement . Фабричный метод, который вы аннотировали @XmlElementDecl, — это самый простой способ сделать это. Метод фабрики находится в классе ObjectFactory, если вы сгенерировали свою модель из схемы XML.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package org.example.customer;import javax.xml.bind.*;public class MarshalDemo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance("org.example.customer"); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // Create Domain Objects AddressType billingAddress = new AddressType(); billingAddress.setStreet("1 Any Street"); Customer customer = new Customer(); customer.setBillingAddress(billingAddress); // Marshal Customer marshaller.marshal(customer, System.out); // Marshal Billing Address ObjectFactory objectFactory = new ObjectFactory(); JAXBElement<AddressType> je = objectFactory.createBillingAddress(billingAddress); marshaller.marshal(je, System.out); }} |
Выход
Ниже приведен результат запуска демонстрационного кода.
|
01
02
03
04
05
06
07
08
09
10
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <billing-address> <street>1 Any Street</street> </billing-address></customer><?xml version="1.0" encoding="UTF-8" standalone="yes"?> <street>1 Any Street</street></billing-address> |
Ссылка: JAXB и Root Elements от нашего партнера JCG Блэза Дафана в блоге Java XML & JSON Binding .