我在互联网上找到了一些JAXB2 @XmlRegistry
的例子,但没有很好的深入教程讨论将@XmlRegistry
与@XmlElementDecl
一起使用的概念,不知道它的概念是不是一般来说都有很多探索。
无论如何,这是我的问题,首先是一些我用来使用JAXB解组xml的示例类:
我正在尝试使用JAXB解组的主要类 - Employee.java
package com.test.jaxb;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
import com.test.jaxb.dto.Address;
@XmlRootElement
public class Employee {
private int id;
private String name;
private String email;
private List<Address> addresses;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Address> getAddresses() {
return addresses;
}
public void setAddresses(List<Address> addresses) {
this.addresses = addresses;
}
@SuppressWarnings("unused")
@XmlRegistry
public static class XMLObjectFactory {
@XmlElementDecl(scope = Employee.class, name= "id")
JAXBElement<String> createEmployeeId(String value) {
return new JAXBElement<String>(new QName("id"), String.class, "100");
}
@XmlElementDecl(scope = Employee.class, name= "name")
JAXBElement<String> createName(String value) {
return new JAXBElement<String>(new QName("name"), String.class, "Fake Name");
}
@XmlElementDecl(scope = Employee.class, name= "email")
JAXBElement<String> createEmail(String value) {
return new JAXBElement<String>(new QName("email"), String.class, value);
}
@XmlElementDecl(scope = Employee.class, name= "addresses")
JAXBElement<List> createAddresses(List value) {
return new JAXBElement<List>(new QName("addresses"), List.class, value);
}
}
}
子类 - Address.java
package com.test.jaxb.dto;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
import com.test.jaxb.Employee;
@XmlRootElement
public class Address {
private String addressLine1;
private String addressLine2;
private String addressLine3;
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getAddressLine2() {
return addressLine2;
}
public void setAddressLine2(String addressLine2) {
this.addressLine2 = addressLine2;
}
public String getAddressLine3() {
return addressLine3;
}
public void setAddressLine3(String addressLine3) {
this.addressLine3 = addressLine3;
}
@SuppressWarnings("unused")
@XmlRegistry
private static class XMLObjectFactory {
@XmlElementDecl(scope = Employee.class, name= "addressLine1")
JAXBElement<String> createAddressLine1(String value) {
return new JAXBElement<String>(new QName("addressLine1"), String.class, value);
}
@XmlElementDecl(scope = Employee.class, name= "addressLine2")
JAXBElement<String> createAddressLine2(String value) {
return new JAXBElement<String>(new QName("addressLine2"), String.class, value);
}
@XmlElementDecl(scope = Employee.class, name= "addressLine3")
JAXBElement<String> createAddressLine3(String value) {
return new JAXBElement<String>(new QName("addressLine3"), String.class, value);
}
}
}
要解组的xml - employee.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee>
<id>1</id>
<name>Vaishali</name>
<email>Vaishali@example.com</email>
<addresses>
<address>
<addressLine1>300</addressLine1>
<addressLine2>Mumbai</addressLine2>
<addressLine3>India</addressLine3>
</address>
<address>
<addressLine1>301</addressLine1>
<addressLine2>Pune</addressLine2>
<addressLine3>India</addressLine3>
</address>
</addresses>
</employee>
解组码:
package com.test.jaxb;
import java.io.FileReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
public class ObjectFactoryTest {
public static void main(String[] args) throws Exception {
FileReader reader = new FileReader("resources/employee.xml");
JAXBContext context = JAXBContext.newInstance(Employee.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Object obj = unmarshaller.unmarshal(reader);
System.out.println(obj);
}
}
当我使用上面的代码解组员工xml时,地址列表不会被填充。生成的员工对象只有一个空白的地址列表。我的映射有什么问题吗?
要了解正在发生的事情并查看是否实际使用对象工厂创建了员工对象(具有@XMLRegistry注释),我在工厂方法中更改了id和name的值,但这对于输出,告诉我JAXB实际上没有使用ObjectFactory,为什么?
我是否完全错了?任何帮助将不胜感激。
答案 0 :(得分:16)
@XmlRegistry - 它是如何运作的?
@XmlRegistry
用于标记具有@XmlElementDecl
注释的类。要让您的JAXB实现处理此类,您需要确保它包含在用于引导JAXBContext
的类列表中。它是一个域模型类的静态内部类是不够的:
JAXBContext context = JAXBContext.newInstance(Employee.class, Employee.XMLObjectFactory.class);
@XmlElementDecl - 它是如何工作的?
如果字段/属性的值为JAXBElement
,那么您需要利用@XmlElementDecl
。 JAXBElement
捕获可能有用的信息:
JAXBElement
可用于表示具有xsi:nil="true"
。<强> XmlObjectFactory 强>
@XmlElementDecl
还允许您指定范围。我已经修改了你的模型。我已经介绍了一个XmlObjectFactory
类,它有两个@XmlElementDecl
。两者都指定了address
的名称。我利用了scope
属性,因此对于Employee
类中的属性,可以使用与@XmlElementDecl
类对应的Address
。
package forum11078850;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
@XmlRegistry
public class XmlObjectFactory {
@XmlElementDecl(scope = Employee.class, name = "address")
JAXBElement<Address> createAddress(Address value) {
return new JAXBElement<Address>(new QName("address"), Address.class, value);
}
@XmlElementDecl(name = "address")
JAXBElement<String> createStringAddress(String value) {
return new JAXBElement<String>(new QName("address"), String.class, value);
}
}
<强>员工强>
@XmlElementRef
注释将导致属性的值与其根元素名称匹配。可能的匹配将包括使用@XmlRootElement
或@XmlElementDecl
映射的类。
package forum11078850;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlType(propOrder = { "id", "name", "email", "addresses" })
public class Employee {
private int id;
private String name;
private String email;
private List<JAXBElement<Address>> addresses;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@XmlElementWrapper
@XmlElementRef(name="address")
public List<JAXBElement<Address>> getAddresses() {
return addresses;
}
public void setAddresses(List<JAXBElement<Address>> addresses) {
this.addresses = addresses;
}
}
<强> ObjectFactoryTest 强>
package forum11078850;
import java.io.FileReader;
import javax.xml.bind.*;
public class ObjectFactoryTest {
public static void main(String[] args) throws Exception {
FileReader reader = new FileReader("src/forum11078850/input.xml");
JAXBContext context = JAXBContext.newInstance(Employee.class, XmlObjectFactory.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Object obj = unmarshaller.unmarshal(reader);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(obj, System.out);
}
}
我的原始答案中的Address
类和input.xml
可用于运行此示例。
原始回答
我不确定您是如何尝试使用@XmlRegistry
的,因此我将重点关注您帖子的以下部分:
当我使用上面的代码解组员工xml时,地址列表 不会填充。生成的员工对象只有一个空白 地址清单。我的映射有什么问题吗?
您的Address
对象列表包含在分组元素(addresses
)中,因此您需要使用@XmlElementWrapper
注释来映射此用例。以下是一个完整的例子:
<强>员工强>
package forum11078850;
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlType(propOrder = { "id", "name", "email", "addresses" })
public class Employee {
private int id;
private String name;
private String email;
private List<Address> addresses;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@XmlElementWrapper
@XmlElement(name = "address")
public List<Address> getAddresses() {
return addresses;
}
public void setAddresses(List<Address> addresses) {
this.addresses = addresses;
}
}
<强>地址强>
package forum11078850;
public class Address {
private String addressLine1;
private String addressLine2;
private String addressLine3;
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getAddressLine2() {
return addressLine2;
}
public void setAddressLine2(String addressLine2) {
this.addressLine2 = addressLine2;
}
public String getAddressLine3() {
return addressLine3;
}
public void setAddressLine3(String addressLine3) {
this.addressLine3 = addressLine3;
}
}
<强> ObjectFactoryTest 强>
package forum11078850;
import java.io.FileReader;
import javax.xml.bind.*;
public class ObjectFactoryTest {
public static void main(String[] args) throws Exception {
FileReader reader = new FileReader("src/forum11078850/input.xml");
JAXBContext context = JAXBContext.newInstance(Employee.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Object obj = unmarshaller.unmarshal(reader);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(obj, System.out);
}
}
<强> input.xml中/输出强>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee>
<id>1</id>
<name>Vaishali</name>
<email>Vaishali@example.com</email>
<addresses>
<address>
<addressLine1>300</addressLine1>
<addressLine2>Mumbai</addressLine2>
<addressLine3>India</addressLine3>
</address>
<address>
<addressLine1>301</addressLine1>
<addressLine2>Pune</addressLine2>
<addressLine3>India</addressLine3>
</address>
</addresses>
</employee>
答案 1 :(得分:-1)
您必须获取Address的List对象。在该对象中,您必须添加包含addressline1等数据的对象。地址线2等。
i.e.
List addrObjList = new List();
addrObjList.add(object); // Bind an object containing data and add one by one