JAXB @XmlAdapter用于任意XML
我有一个org.w3c.dom.Element
,我从我的XmlAdapter
返回自定义@XmlElement
,我想将它作为任意XML包含在JAXB对象中(我知道我必须手工制作XSD)。 但是,JAXB抱怨道
org.w3c.dom.Element is an interface, and JAXB can't handle interfaces.
显然,w3c XML类型不支持Java类型 ,这是一种耻辱。 但javax.xml.transform.Result
,当我使用显然支持的javax.xml.transform.Result
时,我得到了同样的错误。
如何在JAXB中包含任意XML元素作为元素?
注意:根据https://forums.oracle.com/thread/1668210我也试过了
MessageFactory factory = MessageFactory.newInstance(); message = factory.createMessage(); SOAPElement element = message.getSOAPBody().addDocument(doc);
但这也给出了同样的错误。
TL; DR
只要将值类型指定为Object
(而不是Element
),就可以使用XmlAdapter
将域对象转换为org.w3c.dom.Element
的实例。
以下是一个完整的例子。
XmlAdapter
java.lang.Object
类型的字段/属性将未知内容保留为DOM节点。 您可以通过在XmlAdapter
值类型指定为Object
来在您的用例中利用它。 您需要确保从marshal
方法返回的根元素与@XmlElement
注释定义的字段/属性匹配。
import javax.xml.bind.annotation.adapters.XmlAdapter; import javax.xml.parsers.*; import org.w3c.dom.*; public class BarAdapter extends XmlAdapter
Java模型
富
@XmlJavaTypeAdapter
注释用于引用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; }
酒吧
import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) public class Bar { String value; }
演示代码
演示
由于创建DocumentBuilderFactory需要付出代价,因此我们可以通过在Marshaller上设置实例来利用JAXB处理XmlAdapter的有状态实例的能力。
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中/输出
Hello World