document.asxml()返回带utf-8 bom的字符串,导致解析报错;需手动去除\ufeff;其不支持缩进,美化须用xmlwriter+outputformat;乱码源于错误字节转换;替换根元素后需detach旧根或重建document。

Document.asXML() 返回的字符串带 BOM 头,解析时出错
Dom4j 默认用 UTF-8 编码序列化 XML,但 asXML() 实际返回的是带 UTF-8 BOM(EF BB BF)的字节数组转成的字符串。某些 XML 解析器(如 Java 自带的 DocumentBuilder)看到 BOM 会直接报 Content is not allowed in prolog 错误。
- 这不是文档内容问题,是编码“残留”——
asXML()内部调用Writer时未跳过 BOM - 常见于把
asXML()结果存入数据库、发 HTTP 请求、或传给其他 XML 工具链时突然失败 - 修复方式不是改编码参数(
asXML()不接受编码参数),而是手动去除开头的 BOM 字符
String xml = doc.asXML();
if (xml != null && xml.startsWith("\uFEFF")) {
xml = xml.substring(1);
}
想控制缩进和换行,但 asXML() 总是“压成一行”
asXML() 本身不处理格式化,它只是把当前 DOM 树按节点顺序拼接输出,忽略所有空格和换行。即使原始 XML 有缩进,或你调用了 OutputFormat.createPrettyPrint(),对 asXML() 也完全无效。
- 真正起作用的是
XMLWriter+OutputFormat组合,asXML()是个“快捷但粗糙”的只读快照 - 如果需要美化输出,必须走完整流程:
StringWriter→OutputFormat.createPrettyPrint()→XMLWriter→write(doc) - 注意
OutputFormat的setEncoding("UTF-8")和setIndent(true)都要显式设,否则可能仍无缩进
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
format.setIndent(true);
StringWriter sw = new StringWriter();
XMLWriter writer = new XMLWriter(sw, format);
writer.write(doc);
String prettyXml = sw.toString(); // 这才是带缩进的
asXML() 在中文环境下乱码,但文件写入正常
乱码通常不是因为 Dom4j 本身,而是你把 asXML() 返回的字符串当作了某种编码的字节流去处理。例如:用 new String(xml.getBytes("GBK"), "UTF-8") 强转,或者在日志框架里被二次编码。
本文档主要讲述的是JSON.NET 简单的使用;JSON.NET使用来将.NET中的对象转换为JSON字符串(序列化),或者将JSON字符串转换为.NET中已有类型的对象(反序列化?)。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
-
asXML()返回的是 JavaString,已经是 UTF-16 内存表示,不含编码信息 - 乱码只发生在“字符串 → 字节 → 字符串”往返过程中,比如错误地调用
getBytes()后又用不同 charset 构造新字符串 - 写文件正常,是因为
FileWriter或OutputStreamWriter显式指定了 UTF-8,而控制台/日志默认编码可能是 GBK - 调试时别信
System.out.println()的输出,优先用Files.write(path, xml.getBytes(StandardCharsets.UTF_8))验证内容是否真实正确
替换根元素后 asXML() 不生效
Dom4j 的 Document 是引用式结构,直接 new 一个新 Element 并赋给 doc.setRootElement(),并不会自动清理旧根里的子节点引用。如果你之前对旧根做过 addAttribute() 或 addElement(),这些操作仍保留在内存中,asXML() 会把它们一并输出。
立即学习“Java免费学习笔记(深入)”;
- 常见错误是以为
setRootElement(newRoot)就“清空重来”,其实旧根还在堆里,只是没被 document 指向而已 - 更安全的做法是先调用
oldRoot.detach(),或直接创建全新Document实例 - 如果旧根有监听器或自定义扩展字段,不 detach 可能导致内存泄漏
复杂点在于:Dom4j 没有“深拷贝 Document”的便捷 API,真要彻底隔离,得用 DocumentHelper.parseText(doc.asXML()) 重建——但这又绕回了 BOM 和编码问题。









