问题
is anybody try to marshal JAXB object with recurisive referency? I have following class:
public class A {
private Long id;
private String name;
private List<A> aList;
}
and I'd like to marshall it to:
<a>
<a>
<a>...</a>
...
</a>
...
</a>
I'm using maven plugin to auto generate JAXB class from XSD. Any suggestions?
回答1:
Below is how you can support this use case starting from your XML schema.
XML SCHEMA (schema.xsd)
The following XML schema is based on the comment you made to a previous answer (http://stackoverflow.com/a/14317461/383861).
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org"
xmlns:tns="http://www.example.org"
elementFormDefault="qualified">
<xs:element name="b">
<xs:complexType>
<xs:sequence>
<xs:element ref="tns:a" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="a">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:long" />
<xs:sequence>
<xs:element ref="tns:a" minOccurs="0" maxOccurs="10" />
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
GENERATED MODEL
The following code was generated using the xjc
tool. The get/set methods and comments have been removed to save space.
A
package org.example;
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"id",
"a"
})
@XmlRootElement(name = "a")
public class A {
protected long id;
protected List<A> a;
}
B
package org.example;
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"a"
})
@XmlRootElement(name = "b")
public class B {
@XmlElement(required = true)
protected List<A> a;
}
package-info
@javax.xml.bind.annotation.XmlSchema(
namespace = "http://www.example.org",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.example;
ObjectFactory
package org.example;
import javax.xml.bind.annotation.XmlRegistry;
@XmlRegistry
public class ObjectFactory {
public ObjectFactory() {
}
public B createB() {
return new B();
}
public A createA() {
return new A();
}
}
DEMO CODE
import java.io.File;
import javax.xml.bind.*;
import org.example.A;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance("org.example");
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum14306965/input.xml");
A a = (A) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(a, System.out);
}
}
INPUT (input.xml)/OUTPUT
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<a xmlns="http://www.example.org">
<id>1</id>
<a>
<id>2</id>
<a>
<id>3</id>
</a>
</a>
</a>
回答2:
You could do the following:
A
You can use the @XmlElementRef
annotation on the aList
field so that the element it uses comes from the @XmlRootElement
annotation on the A
class.
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class A {
private Long id;
private String name;
@XmlElementRef
private List<A> aList;
}
Demo
Below is some sample code to prove that everything works.
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(A.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum14306965/input.xml");
A a = (A) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(a, System.out);
}
}
input.xml/Output
Below is the input to and output from running the demo code.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<a>
<id>1</id>
<name>A</name>
<a>
<id>2</id>
<name>B</name>
<a>
<id>3</id>
<name>C</name>
</a>
</a>
</a>
XML Schema
Below is the XML schema that corresponds to this model. You could generate the model from it or start from the Java model.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="a" type="a"/>
<xs:complexType name="a">
<xs:sequence>
<xs:element name="id" type="xs:long" minOccurs="0"/>
<xs:element name="name" type="xs:string" minOccurs="0"/>
<xs:element ref="a" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
来源:https://stackoverflow.com/questions/14306965/jaxb-marshalling-with-recursive-dependency