java - 如何使用 JAXB 附加外部生成的 XML 而不是 POJO 的变量值?

标签 java xml jaxb

如何使用 JAXB 附加外部生成的 XML 而不是 POJO 的变量值?

我有具体的数据结构如下:

Map<CustomEnum, CustomList>

到目前为止,我使用实用程序类生成此结构中数据的 xml 表示形式。它使用 SAX 生成 xml 输出。

进一步阅读,CustomEnumjava enumCustomList扩展了java.util.List,它的实现通过工厂方法获得。它允许只包含实现特定接口(interface)的对象。它们的实现也是通过工厂方法获得的,主要是根据具体情况。我无权修改任何这些类。

这就是为什么通过 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;

并在覆盖的 marshal 方法中返回由我的实用程序生成的 xml。

但它给出了类似的输出:

<items>&#xD;&lt;item itemType="1"&gt;&#xD; ...

正如我所见,它是带有 xml 数据而不是 xml 标签树的转义字符串。

我的问题是: 有没有办法告诉 jaxb 不要从属性值生成 xml,而是将外部生成的 xml 作为其自己的 xml 的一部分插入?

附言抱歉,描述太长,但我想尽可能清晰地展示图片。 请注意,我知道这种设计并不理想,但我需要它才能正常工作。我正计划进行总体重构,但这似乎是一个远景。

最佳答案

默认情况下,JAXB 的编码器实现转义所有字符,即使对于自定义适配器也是如此(因为它们也通过相同的编码器)。防止字符转义的解决方案是覆盖默认机制。所以我们需要提供一个 CharacterEscapeHandler 的自定义实现,它绝对不会在字符转义方面做任何事情。 JAXB documentation 中给出了有关如何执行此操作的说明。 :

  1. 编写一个实现 com.sun.xml.bind.marshaller.CharacterEscapeHandler 接口(interface)的类。
  2. 为其创建一个新实例。
  3. 使用此属性(即 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 thread 的极大启发.

关于java - 如何使用 JAXB 附加外部生成的 XML 而不是 POJO 的变量值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21117119/

相关文章:

java - 使用 Spring 配置 CXF 以使用 MOXY 进行 XML 编码/解码

hibernate - 如何关闭Grails中所有域类的 hibernate 延迟加载?

java - 从字符串转换为日期抛出无法解析的日期异常

java - 如何使用 main.xml 中定义的布局添加按钮?

XML SOAP 消息的 Java HTTP post

使用 Xerces 的 getElementsByTagName 的 Java 代码不返回子节点

java - 为什么当我声明 WindowsCanvas 类时会发生这种情况

java - Spring Data (Hibernate) 动态 WHERE 子句

java - 删除 Activity 中的标题栏也会删除图像

java - Jersey 2.26 REST API - Json 返回不起作用