
本文详解如何在 Java 中使用 JAXP(TrAX)和 DOM 等非废弃 API,安全、规范地为指定字段(如 outerHtml)生成带 包裹的 XML,替代已弃用的 XmlSerializer 和 Apache Xerces 旧序列化器。
本文详解如何在 java 中使用 jaxp(trax)和 dom 等非废弃 api,安全、规范地为指定字段(如 `outerhtml`)生成带 `` 包裹的 xml,替代已弃用的 `xmlserializer` 和 apache xerces 旧序列化器。
在现代 Java 开发中,org.apache.xml.serialize.XMLSerializer 已于 Xerces 2.9.0 起被明确弃用,官方推荐使用 JAXP 的 Transformation API(TrAX) 或 DOM Level 3 LSSerializer 实现 XML 序列化。尤其当需要为特定字段(如 outerHtml)强制输出 CDATA 节点时,关键在于:不能依赖全局配置“自动识别字段名”,而应主动在 DOM 构建阶段显式创建 CDATASection 节点——这是最可靠、可移植、且完全符合 W3C 标准的做法。
✅ 推荐方案:使用 DOM + TrAX(零第三方依赖,JDK 原生支持)
以下是一个完整、生产就绪的实现示例,以 MyObjectJava 类为例,确保 <outerhtml></outerhtml> 内容始终被包裹为 CDATA:
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.IOException;
public class XmlWithCDataGenerator {
public static File generateXmlWithCData(MyObjectJava obj, File outputFile)
throws Exception {
// 1. 创建空 DOM 文档
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.newDocument();
// 2. 构建根元素 <MyObjectJava>
Element root = doc.createElement("MyObjectJava");
doc.appendChild(root);
// 3. 添加普通文本子元素(name, surname)
createElementWithText(doc, root, "name", obj.getName());
createElementWithText(doc, root, "surname", obj.getSurname());
// 4. 关键:为 outerHtml 显式创建 CDATA 节点
Element outerHtmlEl = doc.createElement("outerHtml");
// ✅ 核心:使用 createCDATASection() —— 这是 W3C DOM 标准方法,100% 兼容
outerHtmlEl.appendChild(doc.createCDATASection(obj.getOuterHtml()));
root.appendChild(outerHtmlEl);
// 5. 使用 TrAX 序列化(JAXP 推荐方式)
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
t.setOutputProperty(OutputKeys.STANDALONE, "no");
try (var out = new StreamResult(outputFile)) {
t.transform(new DOMSource(doc), out);
}
return outputFile;
}
private static void createElementWithText(Document doc, Element parent,
String tagName, String text) {
Element el = doc.createElement(tagName);
el.setTextContent(text); // 安全设置纯文本(自动转义 <>& 等)
parent.appendChild(el);
}
// 示例用法
public static void main(String[] args) throws Exception {
MyObjectJava obj = new MyObjectJava();
obj.setName("Leo");
obj.setSurname("DaVinci");
obj.setOuterHtml("<a href=\"https://www.isasite.com\">Is a site</a>");
File xmlFile = new File("output.xml");
generateXmlWithCData(obj, xmlFile);
System.out.println("✅ XML with CDATA generated: " + xmlFile.getAbsolutePath());
}
}? 说明:
doc.createCDATASection(...)是org.w3c.dom.Document接口的标准方法,自 Java 1.5 起即存在,不依赖任何外部库,无编译警告,完全符合 DOM Level 3 规范,是替代XMLSerializer#setCDataElements()的最正统方案。
⚠️ 注意事项与常见误区
- ❌ 不要尝试用 XPath 或字符串匹配定位
outerHtml后再“注入” CDATA:这违反 XML 结构完整性,易导致解析失败。 - ❌ 避免使用
setTextContent()或appendChild(createTextNode())处理outerHtml:这会将, <code>>等字符转义为</>,失去 HTML 原始语义。 - ✅
createCDATASection()是唯一正确方式:它明确告知解析器该段内容为原始字符数据,禁止解析、禁止转义。 - ? 若需支持命名空间(如
<outerhtml></outerhtml>),createElement()可传入 namespace URI;createCDATASection()本身无命名空间,但其父元素已携带命名空间上下文,序列化后仍保持正确。
? 补充:若必须基于 JAXB(而非 DOM)生成 CDATA?
JAXB 本身不原生支持按字段声明 CDATA(@XmlCDATA 并非标准注解)。可行的合规方案有两种:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
-
预构建 DOM 片段 +
@XmlAnyElement(lax=true):将outerHtml字段声明为org.w3c.dom.Element类型,并在 Marshaller 前手动构造含 CDATA 的Element; -
使用 MOXy(EclipseLink JAXB)扩展:其支持
@XmlCDATA注解,但引入了非 JDK 标准依赖。
✅ 强烈建议优先采用 DOM+TrAX 方案:轻量、可控、无额外依赖、兼容所有 Java 8+ 环境,且逻辑清晰可维护。
通过上述方法,你不仅能平滑迁移废弃代码,更能获得更健壮、可测试、符合行业标准的 XML 生成能力。

















