XML模式
下面的XML模式包含三个根元素: customer , billing-address和shipping-address 。 customer元素具有匿名的复杂类型,而billing-address和shipping-address具有相同的命名类型( address-type )。
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/customer" xmlns="http://www.example.org/customer" 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>
生成模型
下面是从XML模式生成的JAXB模型。 将JAXB批注添加到现有Java模型时,将应用相同的概念。
顾客
JAXB域类对应于复杂类型。 由于customer元素具有匿名复杂类型,因此Customer类具有@XmlRootElement批注。 这是因为只有一个XML元素可以与匿名类型相关联。
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对其进行注释。
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;}}
对象工厂
@XmlElementDecl批注用于表示与命名的复杂类型相对应的根元素。 它放在@XmlRegistry注释的类中的工厂方法上(从XML模式生成时,该类始终称为ObjectFactory )。 factory方法返回包装在JAXBElement实例中的域对象。 JAXBElement具有一个QName ,它表示元素名称和名称空间URI。
package org.example.customer;import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;@XmlRegistry
public 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();}@XmlElementDecl(namespace = "http://www.example.org/customer", name = "billing-address")public JAXBElement<AddressType> createBillingAddress(AddressType value) {return new JAXBElement<AddressType>(_BillingAddress_QNAME, AddressType.class, null, value);}@XmlElementDecl(namespace = "http://www.example.org/customer", name = "shipping-address")public JAXBElement<AddressType> createShippingAddress(AddressType value) {return new JAXBElement<AddressType>(_ShippingAddress_QNAME, AddressType.class, null, value);}}
包装信息
package-info类用于指定名称空间映射(请参见JAXB和Namespaces )。
@XmlSchema(namespace = "http://www.example.org/customer", elementFormDefault = XmlNsForm.QUALIFIED)
package org.example.customer;import javax.xml.bind.annotation.*;
非海警行动
现在我们来看一下解组XML时根元素类型的影响。
customer.xml
下面是一个示例XML文档,其中有customer作为根元素。 请记住, customer元素具有匿名的复杂类型。
<?xml version="1.0" encoding="UTF-8"?>
<customer xmlns="http://www.example.org/customer"><billing-address><street>1 Any Street</street></billing-address><shipping-address><street>2 Another Road</street></shipping-address>
</customer>
shipping.xml
这是一个示例XML文档,其中shipping-address作为根元素。 送货地址元素具有命名的复杂类型。
<?xml version="1.0" encoding="UTF-8"?>
<shipping-address xmlns="http://www.example.org/customer"><street>2 Another Road</street>
</shipping-address>
解组演示
当解组与用@XmlRootElement注释的类相对应的XML时,您将获得域对象的实例。 但是,当解组与用@XmlElementDecl注释的类相对应的XML时,您将得到包装在J AXBElement实例中的域对象。 在此示例中,您可能需要使用JAXBElement中的QName来确定是否对帐单地址或收货地址进行了编组。
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 CustomerFile customerXML = new File("src/org/example/customer/customer.xml");Customer customer = (Customer) unmarshaller.unmarshal(customerXML);// Unmarshal Shipping AddressFile shippingXML = new File("src/org/example/customer/shipping.xml");JAXBElement<AddressType> je = (JAXBElement<AddressType>) unmarshaller.unmarshal(shippingXML);AddressType shipping = je.getValue();}}
Unmarshal演示– JAXBIntrospector
如果您不想记住解组操作的结果是域对象还是JAXBElement ,则可以使用JAXBIntrospector.getValue(Object)方法始终获取域对象。
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 CustomerFile customerXML = new File("src/org/example/customer/customer.xml");Customer customer = (Customer) JAXBIntrospector.getValue(unmarshaller.unmarshal(customerXML));// Unmarshal Shipping AddressFile shippingXML = new File("src/org/example/customer/shipping.xml");AddressType shipping = (AddressType) JAXBIntrospector.getValue(unmarshaller.unmarshal(shippingXML));}}
元帅行动
您可以直接将带有@XmlRootElement注释的对象编组为XML。 与@XmlElementDecl批注对应的类必须首先包装在JAXBElement的实例中。 用@XmlElementDecl注释的工厂方法是最简单的方法。 如果您是从XML模式生成模型的,则工厂方法位于ObjectFactory类中。
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 ObjectsAddressType billingAddress = new AddressType();billingAddress.setStreet("1 Any Street");Customer customer = new Customer();customer.setBillingAddress(billingAddress);// Marshal Customermarshaller.marshal(customer, System.out);// Marshal Billing AddressObjectFactory objectFactory = new ObjectFactory();JAXBElement<AddressType> je = objectFactory.createBillingAddress(billingAddress);marshaller.marshal(je, System.out);}}
输出量
以下是运行演示代码的输出。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer xmlns="http://www.example.org/customer"><billing-address><street>1 Any Street</street></billing-address>
</customer>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<billing-address xmlns="http://www.example.org/customer"><street>1 Any Street</street>
</billing-address>
参考: Java XML和JSON绑定博客中的JCG合作伙伴 Blaise Doughan的JAXB和Root Elements 。
翻译自: https://www.javacodegeeks.com/2012/08/jaxb-and-root-elements.html