Using @XmlPath with jaxb/MOXy to map complex type(使用 @XmlPath 和 jaxb/MOXy 映射复杂类型)
问题描述
我有一个深度 XML 结构,其中包含许多无意义的包装器,我将它们映射到单个 Java 类.用@XmlPath 映射简单的数据类型是在公园里散步,但是当涉及到实际上需要自己的类的类型时,我不太确定如何去做,尤其是当这些类型也应该放在一个列表中时.
I have a deep XML structure with a lot of pointless wrappers I'm mapping to a single Java class. Mapping the simple datatypes with @XmlPath is a walk in the park, but when it comes to types that actually require their own class I'm not quite sure how to do it, especially when those types should be put in a list as well.
我在将以下示例中的所有 element
类型映射到我的 Element
类时遇到问题.由于 elements
包装器位于使用 @XmlPath
映射的资源中,因此我不能使用 @XmlElementWrapper
,否则我通常会采用这种方式会这样做.
I'm having problems to map all the element
types in the below example to my Element
class. Since the elements
wrapper resides in resource which is mapped using @XmlPath
I can not use the @XmlElementWrapper
, which would otherwise be the way I usually would do this.
示例 XML 结构
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<s:root xsi:schemaLocation="http://www.example.eu/test ResourceSchema.xsd" xmlns:s="http://www.example.eu/test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<s:resource>
<s:information>
<s:date>2013-07-04</s:date>
<s:name>This example does not work</s:name>
</s:information>
<s:elements>
<s:refobj>
<s:id>1</s:id>
<s:source>First Source</s:source>
</s:refobj>
<s:refobj>
<s:id>2</s:id>
<s:source>Second Source</s:source>
</s:refobj>
<s:refobj>
<s:id>5</s:id>
<s:source>Fifth Source</s:source>
</s:refobj>
</s:elements>
</s:resource>
</s:root>
Root.java
@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlPath("resource/information/date/text()")
private String date;
@XmlPath("s:resource/s:information/s:name/text()")
private String name;
@XmlPath("resource/elements/refobj")
private List<RefObj> refObjs;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
RefObj.java
@XmlRootElement(name = "refobj")
@XmlAccessorType(XmlAccessType.FIELD)
public class RefObj {
@XmlElement(name = "id")
private int id;
@XmlElement(name = "source")
private String source;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
}
编组器/解组器
public static void main(String[] args) {
String xml = getXML();
Root root = null;
try {
JAXBContext context = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
StringReader stringReader = new StringReader(xml);
root = (Root) unmarshaller.unmarshal(stringReader);
} catch (Exception ex) {
System.err.println("Failed to unmarshal XML!");
}
try {
JAXBContext context = JAXBContext.newInstance(Root.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.eu/test ResourceSchema.xsd");
StringWriter stringWriter = new StringWriter();
marshaller.marshal(root, stringWriter);
System.out.println(new String(stringWriter.toString().getBytes(Charset.forName("UTF-8"))));
} catch (Exception ex) {
System.err.println("Failed to marshal object!");
}
}
package-info.java
@XmlSchema(
namespace = "http://www.example.eu/test",
attributeFormDefault = XmlNsForm.QUALIFIED,
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns = {
@XmlNs(
prefix = "s",
namespaceURI = "http://www.example.eu/test")
},
location = "http://www.example.eu/test ResourceSchema.xsd")
package se.example.mavenproject1;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
我可以执行应用程序,但是当我解组/编组 XML 内容时没有映射任何元素,而是得到一个仅包含信息的 XML 表示.
I can execute the application, but no element is mapped when I unmarshal/marshal the XML content, instead I get a XML representation containing just the information.
更新
在发布上一个示例后,我意识到它实际上按预期工作,这让我更加困惑.尽管我试图在我的生产代码中复制(以前的)工作示例但没有任何成功,尽管我已经设法将我遇到的问题实际引入到示例代码中.由于我需要为出现问题添加命名空间,因此我假设它与命名约定和 X(ml)Path 有关.
After posting the previous example I realized that it actually worked as intended, which made me even more confused. Although I've tried to replicate the (previously) working example in my production code without any success, although I've managed to actually introduce the problems I'm having into the example code. Since I needed to add a namespace for the problems to appear I'm assuming it has something to do with naming conventions and X(ml)Path.
我还添加了 package-info.java
和我在处理这些对象时使用的编组器/解组器.由于 jaxb.properties 不包含任何令人兴奋的内容,因此我将其省略了.
I've also added package-info.java
and the marshaller/unmarshaller I'm using when working with those objects. Since the jaxb.properties doesn't contain anything exciting I've left it out.
推荐答案
当我运行您的示例时,一切正常.由于您的真实模型可能具有 get/set 方法,您需要确保将 @XmlAccessorType(XmlAccessType.FIELD)
添加到您的类中,否则 MOXy(或任何其他 JAXB impl)也会处理相应的属性被映射(参见:http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html).
When I ran your example everything worked fine. Since your real model probably has get/set methods you will need to ensure that you add @XmlAccessorType(XmlAccessType.FIELD)
to your class otherwise MOXy (or any other JAXB impl) will also treat the corresponding properties as being mapped (see: http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html).
import java.util.List;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlPath("resource/information/date/text()")
private String date;
@XmlPath("resource/information/name/text()")
private String name;
@XmlPath("resource/elements/element")
private List<Element> elements;
}
您还需要确保在与域模型相同的包中具有 jaxb.properties
文件,并使用以下条目将 MOXy 指定为您的 JAXB 提供程序(请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
You also need to ensure that you have a jaxb.properties
file in the same package as your domain model with the following entry to specify MOXy as your JAXB provider (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
更多信息
- http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
更新 #1
当您的文档是命名空间限定时,@XmlPath
注释需要考虑这一点.路径中的节点可以根据 @XmlSchema
注释限定.
When your document is namespace qualified the @XmlPath
annotation needs to factor this in. The nodes in the path can be qualified according to the @XmlSchema
annotation.
包裹信息
在您的 package-info
类中,前缀 s
分配给命名空间 URI http://www.example.eu/test
.
In your package-info
class the prefix s
is assigned to the namespace URI http://www.example.eu/test
.
@XmlSchema(
namespace = "http://www.example.eu/test",
attributeFormDefault = XmlNsForm.QUALIFIED,
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns = {
@XmlNs(
prefix = "s",
namespaceURI = "http://www.example.eu/test")
},
location = "http://www.example.eu/test ResourceSchema.xsd")
package se.example.mavenproject1;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
根
这意味着具有 http://www.example.eu/test
命名空间的节点应该在 @XmlPath<中具有前缀
s
/code> 注释.
This means that the nodes qualified with the http://www.example.eu/test
namespace should have the prefix s
in the @XmlPath
annotation.
import java.util.List;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlPath("s:resource/s:information/s:date/text()")
private String date;
@XmlPath("s:resource/s:information/s:name/text()")
private String name;
@XmlPath("s:resource/s:elements/s:element")
private List<Element> elements;
}
<小时>
更新 #2
所以似乎需要在@XmlPath 中指定命名空间将路径映射到复杂对象时,但可以跳过将路径映射到简单对象,例如字符串或整数.
So it seems as if the namespace needs to be specified in the @XmlPath when mapping the path to a complex object, but can be skipped when mapping the path to a simple object such as a String or an integer.
这是一个错误.您应该以与复杂对象相同的方式对简单对象的 @XmlPath
进行命名空间限定(参见更新 #1).正确的映射今天有效,我们将修复以下错误,以便不正确的映射正确运行.您可以使用下面的链接来跟踪我们在该问题上的进展:
This is a bug. You should namespace qualify the @XmlPath
for simple objects the same way you do for complex objects (see UPDATE #1). The correct mapping works today, we will fix the following bug so that the incorrect mapping behaves correctly. You can use the link below to track our progress on that issue:
- http://bugs.eclipse.org/412311
这篇关于使用 @XmlPath 和 jaxb/MOXy 映射复杂类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用 @XmlPath 和 jaxb/MOXy 映射复杂类型
- Java包名称中单词分隔符的约定是什么? 2022-01-01
- C++ 和 Java 进程之间的共享内存 2022-01-01
- Jersey REST 客户端:发布多部分数据 2022-01-01
- Spring Boot连接到使用仲裁器运行的MongoDB副本集 2022-01-01
- Eclipse 插件更新错误日志在哪里? 2022-01-01
- 如何使用WebFilter实现授权头检查 2022-01-01
- Safepoint+stats 日志,输出 JDK12 中没有 vmop 操作 2022-01-01
- 将log4j 1.2配置转换为log4j 2配置 2022-01-01
- value & 是什么意思?0xff 在 Java 中做什么? 2022-01-01
- 从 finally 块返回时 Java 的奇怪行为 2022-01-01