JAXB在自引用对象和向下广播方面存在问题

JAXB在自引用对象和向下广播方面存在问题,jaxb,Jaxb,我在JAXB中对自引用类进行向下转换时遇到了问题 我的设置: @XmlRootElement class IdentifiableObject { @XmlID @XmlAttribute String id; @XmlAttribute String name; } @XmlRootElement class Node extends IdentifiableObject { @XmlElement @XmlJavaAdapter(SimpleAdapterTh

我在JAXB中对自引用类进行向下转换时遇到了问题

我的设置:

@XmlRootElement
class IdentifiableObject {
  @XmlID
  @XmlAttribute
  String id;

  @XmlAttribute
  String name;
}

@XmlRootElement
class Node extends IdentifiableObject {
  @XmlElement
  @XmlJavaAdapter(SimpleAdapterThatJustDowncastsToIdentifiableObject.class)
  Node parent;

  @XmlElement
  String aField;
}
我已经用很多其他物体做过了,效果很好。但是当我使用一个引用自身的类时,它就不起作用了

我能做些什么来解决这个问题吗?我知道使用XmlID/XmlIDREF可以解决这个问题,但我真的希望不仅仅是一个简单的ref(我希望id和name来自identificated)

澄清一下,我得到的是:

<nodes>
    <node id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5" name="Node 1">
        <aField>This is Node 1</aField>
    </node>
    <node id="0a1d1895-49e1-4079-abc1-749c304cc5a2" name="Node 2">
        <parent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="node" id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5" name="Node 1">
            <aField>This is Node 1</aField>
        </parent>
        <aField>This is Node 2</aField>
    </node>
</nodes>

这是节点1
这是节点1
这是节点2
这就是我想要的:

<nodes>
    <node id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5" name="Node 1">
        <aField>This is Node 1</aField>
    </node>
    <node id="0a1d1895-49e1-4079-abc1-749c304cc5a2" name="Node 2">
        <parent id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5" name="Node 1"/>
        <aField>This is Node 2</aField>
    </node>
</nodes>

这是节点1
这是节点2
更新:请注意,schemagen实际上做了正确的事情。所以这可能是JAXB RI中的一个bug

问候,,
Morten

您的用例不需要
XmlAdapter
。您可以通过使用
@xmltransive
标记
可识别对象
类来解决此问题:

节点

package forum8257098;

import java.util.List;

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Nodes {

    @XmlElement(name="node")
    private List<Node> nodes;

}
可识别对象

package forum8257098;

import javax.xml.bind.annotation.*;

@XmlTransient
public class IdentifiableObject {

    @XmlID
    @XmlAttribute
    private String id;

    @XmlAttribute
    private String name;

}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nodes>
    <node name="Node 1" id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5">
        <aField>This is Node 1</aField>
    </node>
    <node name="Node 2" id="0a1d1895-49e1-4079-abc1-749c304cc5a2">
        <parent name="Node 1" id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5"/>
        <aField>This is Node 2</aField>
    </node>
</nodes>
演示

package forum8257098;

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(Nodes.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum8257098/input.xml");
        Nodes nodes = (Nodes) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(nodes, System.out);
    }

}
输入/输出

package forum8257098;

import javax.xml.bind.annotation.*;

@XmlTransient
public class IdentifiableObject {

    @XmlID
    @XmlAttribute
    private String id;

    @XmlAttribute
    private String name;

}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nodes>
    <node name="Node 1" id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5">
        <aField>This is Node 1</aField>
    </node>
    <node name="Node 2" id="0a1d1895-49e1-4079-abc1-749c304cc5a2">
        <parent name="Node 1" id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5"/>
        <aField>This is Node 2</aField>
    </node>
</nodes>



您的用例不需要
XmlAdapter
。您可以通过使用
@xmltransive
标记
可识别对象
类来解决此问题:

节点

package forum8257098;

import java.util.List;

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Nodes {

    @XmlElement(name="node")
    private List<Node> nodes;

}
可识别对象

package forum8257098;

import javax.xml.bind.annotation.*;

@XmlTransient
public class IdentifiableObject {

    @XmlID
    @XmlAttribute
    private String id;

    @XmlAttribute
    private String name;

}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nodes>
    <node name="Node 1" id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5">
        <aField>This is Node 1</aField>
    </node>
    <node name="Node 2" id="0a1d1895-49e1-4079-abc1-749c304cc5a2">
        <parent name="Node 1" id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5"/>
        <aField>This is Node 2</aField>
    </node>
</nodes>
演示

package forum8257098;

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(Nodes.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum8257098/input.xml");
        Nodes nodes = (Nodes) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(nodes, System.out);
    }

}
输入/输出

package forum8257098;

import javax.xml.bind.annotation.*;

@XmlTransient
public class IdentifiableObject {

    @XmlID
    @XmlAttribute
    private String id;

    @XmlAttribute
    private String name;

}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nodes>
    <node name="Node 1" id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5">
        <aField>This is Node 1</aField>
    </node>
    <node name="Node 2" id="0a1d1895-49e1-4079-abc1-749c304cc5a2">
        <parent name="Node 1" id="49ad1cb6-f6fe-47f9-a544-4a1c6337c4a5"/>
        <aField>This is Node 2</aField>
    </node>
</nodes>