java Jaxb 复杂的 xml 解组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6020234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Jaxb complex xml unmarshall
提问by BSingh
I am having issues to unmarshall nested xml below. Can someone please advise if I am missing something.body
tag can contain any Jaxb anotated obj.
Do I have to create a custom adapter for marshalling/unmarshalling such xml?
我在解组下面的嵌套 xml 时遇到问题。有人可以告诉我是否遗漏了什么。body
标签可以包含任何 Jaxb 注释的 obj。
我是否必须创建一个自定义适配器来编组/解组此类 xml?
Input XML
输入 XML
<?xml version="1.0" encoding="UTF-8"?>
<serviceRq xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="serviceRq">
<body>
<createRq>
<id>1234</id>
</createRq>
</body>
</serviceRq>
My Jaxb-annotated classes are:
我的 Jaxb 注释类是:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "serviceRq")
public class ServiceRq{
private Object body;
<!-- getters and setters omitted-->
}
Here, body can be any jaxb annotated object, in this case its CreateRq.
这里,body 可以是任何 jaxb 注释的对象,在本例中是它的 CreateRq。
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "createRq")
public class CreateRq{
private String id;
<!-- getters and setters omitted-->
}
I am looking for a generic way to support any Jaxb annotated object in body of the input xml.
我正在寻找一种通用方法来支持输入 xml 正文中的任何 Jaxb 注释对象。
回答by bdoughan
You could use a @XmlAnyElement(lax=true)
and an XmlAdapter
to handle this use case:
您可以使用 a@XmlAnyElement(lax=true)
和 anXmlAdapter
来处理这个用例:
ServiceRq
服务请求
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "serviceRq")
public class ServiceRq{
@XmlJavaTypeAdapter(value=BodyAdapter.class)
private Object body;
// getters and setters omitted
}
BodyAdapter
身体适配器
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class BodyAdapter extends XmlAdapter<Body, Object>{
@Override
public Object unmarshal(Body v) throws Exception {
return v.getValue();
}
@Override
public Body marshal(Object v) throws Exception {
Body body = new Body();
body.setValue(v);
return body;
}
}
Body
身体
import javax.xml.bind.annotation.XmlAnyElement;
public class Body {
private Object value;
@XmlAnyElement(lax=true)
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
CreateRq
创建请求
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "createRq")
public class CreateRq{
private String id;
// getters and setters omitted
}
Demo
演示
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(ServiceRq.class);
System.out.println(jc);
Unmarshaller unmarshaller = jc.createUnmarshaller();
ServiceRq serviceRq = (ServiceRq) unmarshaller.unmarshal(new File("input.xml"));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(serviceRq, System.out);
}
}
For More Information
想要查询更多的信息
回答by bdoughan
You could use @XmlAnyElement(lax=true)
and the @XmlPath
extension in EclipseLink JAXB (MOXy)to handle this use case (Note: I'm the MOXy lead). For an approach that would work with any JAXB implementation (Metro, MOXy, JaxMe, etc) see: Jaxb complex xml unmarshall.
您可以使用EclipseLink JAXB (MOXy) 中@XmlAnyElement(lax=true)
的@XmlPath
扩展来处理这个用例(注意:我是 MOXy 的负责人)。有关适用于任何 JAXB 实现(Metro、MOXy、JaxMe等)的方法,请参阅: Jaxb complex xml unmarshall。
ServiceRq
服务请求
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "serviceRq")
public class ServiceRq{
@XmlPath("body/createRq")
@XmlAnyElement(lax=true)
private Object body;
// getters and setters omitted
}
CreateRq
创建请求
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "createRq")
public class CreateRq{
private String id;
// getters and setters omitted
}
Demo
演示
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(ServiceRq.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
ServiceRq serviceRq = (ServiceRq) unmarshaller.unmarshal(new File("input.xml"));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(serviceRq, System.out);
}
}
jaxb.properties
jaxb.properties
To use MOXy as your JAXB provider you must include a file named jaxb.properties in the same package as your domain model with the following entry:
要将 MOXy 用作您的 JAXB 提供程序,您必须在与域模型相同的包中包含一个名为 jaxb.properties 的文件,其中包含以下条目:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
For More Information
想要查询更多的信息
- http://bdoughan.blogspot.com/2010/08/using-xmlanyelement-to-build-generic.html
- http://bdoughan.blogspot.com/2011/05/specifying-eclipselink-moxy-as-your.html
- http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html
- http://bdoughan.blogspot.com/2011/03/map-to-element-based-on-attribute-value.html
- http://bdoughan.blogspot.com/2010/08/using-xmlanyelement-to-build-generic.html
- http://bdoughan.blogspot.com/2011/05/specifying-eclipselink-moxy-as-your.html
- http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html
- http://bdoughan.blogspot.com/2011/03/map-to-element-based-on-attribute-value.html