JAXB和根元素

@XmlRootElement是人们习惯于与JAXB(JSR-222)一起使用的注释。 目的是将根元素与类唯一关联。 由于JAXB类映射到复杂类型,因此一个类有可能对应于多个根元素。 在这种情况下,无法使用@XmlRootElement ,人们开始感到有些困惑。 在本文中,我将演示如何使用@XmlElementDecl映射此用例。

XML模式

下面的XML模式包含三个根元素: customerbilling-addressshipping-addresscustomer元素具有匿名的复杂类型,而billing-addressshipping-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 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
 
如果您不想记住解组操作的结果是域对象还是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 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注释的工厂方法是最简单的方法。 如果您是从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 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);
    }

}

输出量

以下是运行演示代码的输出。

<?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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
若要使用JAXB解析XML数组,需要按照以下步骤进行操作: 1. 创建一个包含所有要解析的数组元素Java类。 2. 在该类上使用`@XmlRootElement`注释,指定XML元素名称。 3. 在该类中使用`@XmlElement`注释,指定XML中数组元素的名称。 4. 在解析XML时,使用JAXB的`unmarshal()`方法将XML转换为Java对象。 5. 将返回的Java对象转换为数组。 以下是一个示例Java类,用于解析包含`book`元素XML数组: ``` @XmlRootElement(name = "books") public class Books { @XmlElement(name = "book") private List<Book> books; public List<Book> getBooks() { return books; } public void setBooks(List<Book> books) { this.books = books; } } public class Book { private String title; private String author; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } } ``` 在上面的示例中,`Books`类包含一个名为`books`的`List`,其中每个元素都是`Book`对象。`Books`类上使用了`@XmlRootElement`注释,指定XML中的元素名称为`books`。`Book`类中没有使用任何JAXB注释,因为不需要指定XML元素的名称。 以下是一个示例XML文件,其中包含两个`book`元素: ``` <books> <book> <title>Java Programming</title> <author>John Smith</author> </book> <book> <title>Python Programming</title> <author>Jane Doe</author> </book> </books> ``` 要解析该XML文件,可以使用以下代码: ``` File file = new File("books.xml"); JAXBContext jaxbContext = JAXBContext.newInstance(Books.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); Books books = (Books) jaxbUnmarshaller.unmarshal(file); List<Book> bookList = books.getBooks(); ``` 在上面的代码中,首先使用`JAXBContext`创建一个`Unmarshaller`对象。然后,使用`unmarshal()`方法将XML文件转换为`Books`对象。最后,使用`getBooks()`方法获取`Books`对象中的`List`,它包含所有的`Book`对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值