TL;DR
You can have an XmlAdapter
that converts you domain object to an instance of org.w3c.dom.Element
as long as you specify the value type as Object
(not Element
).
Below is a full example.
XmlAdapter
A field/property of type java.lang.Object
will keep unknown content as DOM nodes. You can leverage this in your use case by specifying the value type in your XmlAdapter
as Object
. You will need to ensure that the root element returned from the marshal
method matches the field/property as defined by the @XmlElement
annotation.
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.*;
import org.w3c.dom.*;
public class BarAdapter extends XmlAdapter<Object, Bar>{
private DocumentBuilder documentBuilder;
public BarAdapter() {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
documentBuilder = dbf.newDocumentBuilder();
} catch(Exception e) {
// TODO - Handle Exception
}
}
@Override
public Bar unmarshal(Object v) throws Exception {
Bar bar = new Bar();
Element element = (Element) v;
bar.value = element.getTextContent();
return bar;
}
@Override
public Object marshal(Bar v) throws Exception {
Document document = documentBuilder.newDocument();
Element root = document.createElement("bar");
root.setTextContent(v.value);
return root;
}
}
Java Model
Foo
The @XmlJavaTypeAdapter
annotation is used to reference the XmlAdapter
.
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {
@XmlJavaTypeAdapter(BarAdapter.class)
private Bar bar;
}
Bar
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class Bar {
String value;
}
Demo Code
Demo
Since there is a cost to creating the DocumentBuilderFactory we can leverage JAXB's ability to handle stateful instances of XmlAdapter by setting an instance on the Marshaller.
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Foo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum18272059/input.xml");
Foo foo = (Foo) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setAdapter(new BarAdapter());
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(foo, System.out);
}
}
input.xml/Output
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar>Hello World</bar>
</foo>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…