2

我正在使用 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;
    }

}

人.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;
    }

}

包信息.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;

包信息.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 类属于不同的命名空间?如您所见,只有元素的命名空间是错误的,但它的属性被分配给了正确的命名空间。

更新

我已按照建议进行了以下更改。这些类如下所示:

原子链接.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() {
    }

}

人.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 定义为链接元素的 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,这也总是会导致命名空间声明。

更新2

如果我使用 Java 内部 JAXB-Implementation,一切都按预期工作...... MOXy 实现中一定有错误。

4

2 回答 2

1

这就是 JAXB 的工作方式。局部元素的命名空间(就像它的名字一样,很自然)由其@XmlElement注解的属性指定。

如果你想要AtomLink而不是Person决定这些(命名空间和名称,因为它们一起出现),你必须在 Person中创建@XmlRootElement并使用它。@XmlElementRef

如果你想留下来@XmlElement

@XmlElement(namespace="http://www.w3.org/2005/Atom")
private AtomLink link;

是要走的路。

于 2013-02-12T08:29:02.683 回答
1

您遇到的是 MOXy 中的一个错误,该错误现已在 EclipseLink 2.4.2 和 2.5.0 流中得到修复。自 2013 年 2 月 13 日起,您可以从以下位置下载每晚构建的版本。

关于正确的映射,请参见Michał Politowski 给出的答案

于 2013-02-12T21:04:48.263 回答