前言

O/X Mapping 指 Java 对象与 XML 文档对象之间的转换,这是个古老的话题。可选的方案有:

  • XMLBeans:目前主要作为 Apache POI 的模块,用于文档对象转换
  • JAXB:选择 JAXB 在于作为语言特性,轻量级,结合性良好
  • XStream:对命名空间支持较弱、默认对任何类都可以进行转换,较低版本存在安全漏洞,互联网业务慎用
  • Castor:2004 年停止维护
  • JiBX:最终版本 1.2.3,2011 年停止维护

最早 JSR31 发布 Jaxb1.0 版本,JSR 222 发布 Jaxb2.0,JDK1.6 并引入作为一部分。 最新版本 3.0 命名为 Jakarta XML Binding,作为 Jakarta EE 9 一部分。在JDK1.6/Jaxb 2.0 以下版本的环境中,使用过程中存在诸多问题。以下讨论仅限于 JDK6/Jaxb2.0 以上版本。

参考

Jaxb 转换方案

处理麻烦点

  • 命名空间前缀问题
  • CDATA 转义问题

定义 package-info.java

解决命名中自定义前缀及程序生成的前缀

1
2
3
4
5
6
7
8
@XmlSchema(namespace = "https://www.bytedusk.com", 
xmlns = { @XmlNs(namespaceURI = "https://www.bytedusk.com", prefix = ""),
@XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")
},
elementFormDefault = XmlNsForm.QUALIFIED)

package com.bytedusk.dev.biz.sundry.jaxb.model;
import javax.xml.bind.annotation.XmlNs;

前缀问题主要在于 NamespacePrefixMapper ,未设置命名空间的项将使用程序自动生成的前缀,所以解决办法就有两种:

  • 为所有的项加上命名空间
  • 重载 NamespacePrefixMapper 根据不同命名空间返回不同前缀。

解决 CDATA 问题

  • 解决 CDATA 转义的问题思路就是,在待处理的变量上加注解,通过动态代理方式,在 Jaxb 处理前做转义。
    EclipseLink 提供了一种 JaxbContext 实现方式来处理 CDATA。

配置:JaxbContext 对应扫描的 package 添加 jaxb.properties,内容如下

1
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

代码中注解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="", propOrder={"xml"})
public class Body {

@XmlCDATA
private String xml;

public String getXml() {
return xml;
}

public void setXml(String xml) {
this.xml = xml;
}
}
  • 注意:EclipseLink 2.7.4 与 Spring ORM 4.3.5 冲突