如何使用JAXB附加外部生成的XML而不是POJO的变量值?
我的具体数据结构如下:
Map<CustomEnum, CustomList>
到目前为止,我使用实用程序类来生成此结构中数据的xml表示。它使用SAX
生成xml输出。
为了进一步阅读,CustomEnum
是java enum
,CustomList
扩展了java.util.List
,其实现是通过factory methods
获得的。它只允许包含实现specific interface
的对象。它们的实现也是通过factory methods
获得的,主要是基于特定的条件。我没有修改这些类的权限。
这就是为什么通过jaxb
转换这个结构在我看来相当复杂,但还有许多其他原因,为什么该实用程序类被写入(有很多条件求值,例如,如果某些值不为空,则从其他值获取数据,否则提供默认值,等等)
现在,这个数据结构需要作为更大结构的一部分,基于POJO,并使用jaxb转换为xml。
类似这样的东西:
public class CustomPojo {
...
private String data;
...
private Map<CustomEnum, CustomList> items;
}
XML输出应为:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rootElement>
<data> value </data>
...
<items>
<!-- generated xml from my utility class -->
</items>
</rootElement>
我需要的是,无论jaxb-marshaller在哪里找到Map类型的pojo成员变量,而不是试图从该变量生成xml,插入我的实用程序类生成的xml。
所以我想出了实现自定义适配器的想法:
public class CustomAdapter extends XmlAdapter<String, Map<CustomEnum, CustomList>>
将其用作
...
@XmlJavaTypeAdapter(CustomAdapter.class)
private Map<CustomEnum, CustomList> items;
在overridenmarshal
方法中,让返回我的实用程序生成的xml。
但它给出了与此类似的输出:
<items>
<item itemType="1">
 ...
因此,正如我所看到的,它是带有xml数据的转义字符串,而不是xml标记树。
我的问题是:有没有办法告诉jaxb不要从属性值生成xml,而是将外部生成的xml作为自己xml的一部分插入?
附言:很抱歉描述太长了,但我想把图片写得尽可能清楚。请注意,我知道这个设计并不理想,但我需要它发挥作用。我正在计划一般的重构,但这似乎是一个很长的机会。
默认情况下,JAXB的编组器实现转义所有字符,即使对于自定义适配器也是如此(因为它们也通过相同的编组器)。防止字符转义的解决方案是覆盖默认机制。因此,我们需要提供一个CharacterEscapeHandler
的自定义实现,它在字符转义方面绝对不会起任何作用。JAXB文档中给出了如何做到这一点的说明:
- 编写一个实现com.sun.xml.bind.marshaller.CharacterEscapeHandler接口的类
- 创建它的新实例
- 使用此属性(即
com.sun.xml.bind.characterEscapeHandler
)将该实例设置为Marshaller
因此,这样的实现看起来像。。。
public class NullCharacterEscapeHandler implements CharacterEscapeHandler {
public NullCharacterEscapeHandler() {
super();
}
public void escape(char[] ch, int start, int length, boolean isAttVal, Writer writer) throws IOException {
// Proxy the characters to the writer, with no encoding escape.
writer.write( ch, start, length );
}
}
并以这种方式使用:
Marshaller m = jcb.createMarshaller();
m.setProperty("com.sun.xml.bind.marshaller.CharacterEscapeHandler",
new NullCharacterEscapeHandler());
这个回复受到了这条stackoverflow线索的极大启发。