gpt4 book ai didi

java - @XmlRegistry - 它是如何工作的?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:36:05 25 4
gpt4 key购买 nike

我在互联网上找到了一些 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,为什么?

我是不是错了?任何帮助将不胜感激。

最佳答案

@XmlRegistry - how does it work?

@XmlRegistry 用于标记具有 @XmlElementDecl 注释的类。要让 JAXB 实现处理这个类,您需要确保它包含在用于引导 JAXBContext 的类列表中。它是您的域模型类之一的静态内部类是不够的:

JAXBContext context = JAXBContext.newInstance(Employee.class, Employee.XMLObjectFactory.class);

@XmlElementDecl - how does it work?

如果字段/属性的值将成为 JAXBElement,那么您需要利用 @XmlElementDeclJAXBElement 捕获有用的信息:

  • 元素名称,如果要映射到多个元素类型相同的选择结构,则这是必需的。如果元素名称不对应于唯一类型,那么您将无法往返文档。
  • 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;
}

}

对象工厂测试

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 的,因此我将重点关注您帖子的以下部分:

When I unmarshal the employee xml using above code, the address list does not get populated. The resulting employee object only has a blank list of adresses. Is there anything wrong with my mappings?

您的 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;
}

}

对象工厂测试

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>

关于java - @XmlRegistry - 它是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11078850/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com