我正在使用属于不同命名空间的MOXy和类,但MOXy总是向引用的对象添加错误的命名空间。为什么这个简单的例子没有按预期工作?
AtomLink.java:
package org.atom;
@XmlAccessorType(XmlAccessType.NONE)
public class AtomLink {
@XmlAttribute
protected String rel;
@XmlAttribute(required = true)
@XmlSchemaType(name = "anyURI")
protected String href;
public AtomLink() {
}
public AtomLink(String rel, String href) {
this.rel = rel;
this.href = href;
}
}
Person.java
package org.example;
import org.atom.AtomLink;
@XmlRootElement(name = "person")
@XmlAccessorType(XmlAccessType.NONE)
public class Person {
@XmlElement
protected String name;
@XmlElement
protected AtomLink link;
public Person() {
}
public Person(String name, AtomLink link) {
this.name = name;
this.link = link;
}
}
package-info.java
@XmlSchema(namespace = "http://www.w3.org/2005/Atom", xmlns={
@XmlNs(namespaceURI = "http://www.w3.org/2005/Atom", prefix = "atom")}, elementFormDefault = XmlNsForm.QUALIFIED, attributeFormDefault = XmlNsForm.QUALIFIED)
package org.atom;
package-info.java
@XmlSchema(namespace = "http://www.test.org", xmlns={
@XmlNs(namespaceURI = "http://www.test.org", prefix = "test")}, elementFormDefault = XmlNsForm.QUALIFIED, attributeFormDefault = XmlNsForm.UNQUALIFIED)
package org.example;
试验编号:
Person person = new Person("Test", new AtomLink("self", "http://www.test.org/person/Test"));
try {
JAXBContext context = JAXBContextFactory.createContext(new Class[] { Person.class }, null);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(person, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
结果:
<?xml version="1.0" encoding="UTF-8"?>
<test:person xmlns:atom="http://www.w3.org/2005/Atom" xmlns:test="http://www.test.org">
<test:name>Test</test:name>
<test:link atom:rel="self" atom:href="http://www.test.org/person/Test"/>
</test:person>
但我期待:
...
<atom:link atom:rel="self" atom:href="http://www.test.org/person/Test"/>
...
为什么MOXy没有意识到AtomLink类属于不同的命名空间?如您所见,只有元素的命名空间是错误的,但其属性被分配给正确的命名空间。
我按照建议完成了以下更改。这些类看起来如下:
AtomLink.java
@XmlRootElement(name = "link")
@XmlAccessorType(XmlAccessType.NONE)
public class AtomLink {
@XmlAttribute
protected String rel;
@XmlAttribute(required = true)
@XmlSchemaType(name = "anyURI")
protected String href;
public AtomLink() {
}
}
Person.java:
@XmlRootElement(name = "person")
@XmlAccessorType(XmlAccessType.NONE)
public class Person {
@XmlElement
private String name;
@XmlElementRef
private AtomLink link;
public Person() {
}
public Person(String name, AtomLink link) {
this.name = name;
this.link = link;
}
}
结果是一个无效的XML文档,它将n0定义为link元素的targetNamespace,但其属性被分配给我的atom-prefix。
<?xml version="1.0" encoding="UTF-8"?>
<test:person xmlns:test="http://www.test.org" xmlns:ns0="http://www.w3.org/2005/Atom>
<test:name>Test</test:name>
<ns0:link atom:rel="self" atom:href="http://www.test.org/person/Test"/>
</test:person>
使用atom-entry扩展“http://www.test.org”命名空间不是解决方案,因为即使XML文档中不存在atom-element,也会在命名空间声明中产生。
如果我使用Java内部JAXB实现,则Everythings按预期工作...... MOXy实现中必定存在错误。
答案 0 :(得分:1)
这是JAXB的工作方式。局部元素的命名空间(就像它的名称一样,很自然)由其@XmlElement
注释的属性指定。
如果您想要AtomLink
而不是Person
来决定这些(名称空间和名称,因为它们在一起),您必须使其@XmlRootElement
并使用@XmlElementRef
在人。
如果您想留在@XmlElement
@XmlElement(namespace="http://www.w3.org/2005/Atom")
private AtomLink link;
是要走的路。
答案 1 :(得分:1)
您遇到的是MOXy中的bug,现在已在EclipseLink 2.4.2和2.5.0流中修复。您可以从2013年2月13日起从以下位置下载每晚构建。
就正确的映射而言,请参阅answer given by Michał Politowski。