OutputKeys.INDENT设为"yes"单独无效,必须同时设置"{http://xml.apache.org/xslt}indent-amount"缩进量、确保输入为DOMSource等结构化源,并注意JDK版本差异。
在使用 java 的 transformer(如 jaxp)将 dom 或 source 转为 xml 字符串时,outputkeys.indent 是控制格式化输出的关键配置项。它本身**不直接生效**,必须配合正确的缩进设置和换行策略才能输出真正可读、缩进规范的 xml。
必须启用 indent 并指定缩进宽度
OutputKeys.INDENT 默认值是 "no",设为 "yes" 仅是第一步。JAXP 实现(如 Xalan 或 JDK 内置 Transformer)还需知道“每级缩进几个空格”,否则可能无缩进或缩进异常:
- 设置
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - 同时设置缩进宽度(JDK 7+ 推荐用标准属性):
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
或更兼容的方式(部分老版本需用此 URI):transformer.setOutputProperty("indent-amount", "2");
确保源节点结构完整,避免“扁平化”输出
如果输入 DOM 树中节点间没有文本节点(例如换行符、空白),即使启用了 indent,Transformer 也可能跳过换行——因为它只对已有结构做缩进,不自动插入换行符:
- 构建 DOM 时,手动在元素间插入空白文本节点(如
doc.createTextNode("\n"))可增强控制力 - 更稳妥的做法:使用
DocumentBuilder.setIgnoringElementContentWhitespace(false),并确保 XML 源未声明xml:space="preserve"干扰处理 - 若从字符串解析,建议用
DocumentBuilderFactory.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false)保留原始空白结构
注意 Transformer 实现差异与 JDK 版本行为
不同 JDK 版本和底层 XSLT 引擎对 INDENT 的支持程度不同:
- JDK 8 及以前默认使用 Xalan,
indent-amount必须用带命名空间的属性名 - JDK 9+ 默认切换为内置 LightWeightTransformer,对
indent-amount的识别更宽松,但依然推荐显式指定命名空间 - 若输出仍无换行,可临时添加:
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");(有时触发格式化逻辑)
替代方案:用第三方库规避原生限制
若原生 Transformer 行为不稳定,可改用成熟 XML 工具链:
-
JDOM2:调用
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());,自动处理缩进、换行、编码,无需手动配 key -
Dom4j:用
OutputFormat.createPrettyPrint()+XMLWriter,支持自定义缩进字符(空格/Tab)、行末符(\n或\r\n) -
SimpleXML 或 JAXB(配合
@XmlAccessorType(XmlAccessType.FIELD))也能生成可读 XML,适合对象序列化场景

















