只有一个XMLElementRef编组

时间:2013-02-21 08:50:06

标签: java jaxb moxy

我有以下课程

@XmlRootElement(name = "entity")
public class Entity {

    @XmlElementRef
    protected AtomLink first;
    @XmlElementRef
    protected AtomLink second;

    public Entity() {
    }

    public Entity(AtomLink first, AtomLink second) {
        this.first = first;
    this.second = second;
    }
}

这是我的测试代码:

Entity entity = new Entity(new AtomLink("first", "http://test/first"), new AtomLink("second", "http://test/second"));
JAXBContext context;
try {
    context = JAXBContextFactory.createContext(new Class[] { Entity.class } , null);
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.marshal(entity, System.out);
} catch (JAXBException e) {
    e.printStackTrace();
}

MOXy的输出错误,因为缺少第一个链接:

<entity xmlns:atom="http://www.w3.org/2005/Atom">
    <atom:link rel="second" href="http://test/second"/>
</entity>

Java JAXB RI的输出是正确的:

<entity xmlns:atom="http://www.w3.org/2005/Atom">
    <atom:link rel="first" href="http://test/first"/>
    <atom:link rel="second" href="http://test/second"/>
</entity>

这是MOXy中的错误吗?

1 个答案:

答案 0 :(得分:1)

注意:我是EclipseLink JAXB (MOXy)主管,是JAXB (JSR-222)专家组的成员。

  

这是MOXy中的错误吗?

不,不是真的。问题是,使用@XmlElementRef注释的两个相同类型的属性是无效的。如果您使用JAXB RI解组:

<entity xmlns:atom="http://www.w3.org/2005/Atom">
    <atom:link rel="first" href="http://test/first"/>
    <atom:link rel="second" href="http://test/second"/>
</entity>

然后将其归还,就像MOXy一样,你会得到:

<entity xmlns:atom="http://www.w3.org/2005/Atom">
    <atom:link rel="second" href="http://test/second"/>
</entity>

替代方法 - 任何JAXB(JSR-222)实施

在JAXB中,重复元素应该在集合属性中表示:

@XmlRootElement
public class Entity {

    @XmlElementRef
    protected List<AtomLink> first;

    public Entity() {
    }

}

使用MOXy的@XmlPath

以下是如何利用MOXy的@XmlPath扩展来支持此用例的示例。

包信息

假设您在@XmlSchema注释中指定了以下命名空间信息。

@XmlSchema(
    xmlns={
       @XmlNs(prefix="atom", namespaceURI="http://www.w3.org/2005/Atom")
    }
)
package forum14998000;

import javax.xml.bind.annotation.*;

<强>实体

然后,您可以使用@XmlPath将字段映射到具有特定属性值的元素。由于我们匹配的不仅仅是元素名称/ URI,因此我们不会遇到原始问题。

package forum14998000;

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name = "entity")
public class Entity {

    @XmlPath("atom:link[@rel='first']")
    protected AtomLink first;

    @XmlPath("atom:link[@rel='second']")
    protected AtomLink second;

    public Entity() {
    }

    public Entity(AtomLink first, AtomLink second) {
        this.first = first;
    this.second = second;
    }

}

AtomLink

既然rel注释中涵盖了@XmlPath属性,我们也不会将其作为AtomLink类中的字段包含在内。

import javax.xml.bind.annotation.*;

@XmlRootElement(namespace="http://www.w3.org/2005/Atom", name="link")
@XmlAccessorType(XmlAccessType.FIELD)
public class AtomLink {

    @XmlAttribute
    private String href;

}

了解更多信息