当 Freemarker 模板输出 XML 内容时,若原始 JSON 数据包含 Unicode 控制字符(如 u000b、u0011 等 XML 1.0 不允许的字符),会触发“invalid XML character”解析错误;本文提供可直接集成的正则清洗方案,确保数据兼容性。
当 freemarker 模板输出 xml 内容时,若原始 json 数据包含 unicode 控制字符(如 `u000b`、`u0011` 等 xml 1.0 不允许的字符),会触发“invalid xml character”解析错误;本文提供可直接集成的正则清洗方案,确保数据兼容性。
在使用 Freemarker 生成 XML(例如用于打印系统、SOAP 响应或 RSS 输出)时,一个常见但易被忽视的问题是:上游 API 返回的 JSON 数据中可能嵌入了 XML 1.0 规范所禁止的字符——例如制表符之外的控制字符(Unicode 0x00–0x08, 0x0B–0x0C, 0x0E–0x1F)、代理对中的孤立高位/低位码点,或超出 #x10000–#xEFFFF 范围的保留区字符。典型案例如 {"key":"HMA u2013AZACITIDINE"} 中看似正常的破折号(u2013)虽合法,但若混入 u000b(垂直制表符)或 u001f(单元分隔符),XML 解析器将立即报错:An invalid XML character (Unicode: 0xb) was found in the element content。
由于你无法控制 API 数据源,预处理(pre-sanitization)是唯一可靠方案。推荐采用严格遵循 XML 1.0 第四版规范 §2.2 的正则表达式,精准匹配并移除所有非法字符:
// ✅ 兼容 XML 1.0 的完整非法字符清理正则(支持 BMP + 补充字符)
public static String sanitizeForXml(String input) {
if (input == null) return null;
// 匹配所有 XML 1.0 非法字符:排除制表符(u0009)、换行(
)、空格(u0020)及合法 Unicode 范围
String xml10IllegalPattern = "[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD\ud800\udc00-\udbff\udfff]";
return input.replaceAll(xml10IllegalPattern, "");
}
⚠️ 注意事项:
- 该正则已显式保留 u0009(Tab)、u000A(LF)、u000D(CR)和 u0020–uD7FF / uE000–uFFFD 等合法区间,同时正确处理 UTF-16 代理对(\ud800\udc00-\udbff\udfff),避免误删 Emoji 或生僻汉字;
- 切勿使用 String.replace("u000b", "") 等逐字符替换——非法字符种类繁多(共 33 个基础控制符+扩展区),手动枚举极易遗漏;
- 若业务允许,也可将非法字符替换为占位符(如 `)而非直接删除:replaceAll(xml10IllegalPattern, "")`,便于后续人工核查数据质量;
- 在 Freemarker 层面,不要依赖 ?xml 内置转义——它仅处理 , & 等基础实体,对 Unicode 控制符完全无感。
最后,建议将清洗逻辑封装为工具方法,在数据从 JSON 反序列化后、传入 Freemarker TemplateModel 前统一调用。例如在 Spring Boot Controller 中:
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(apiResponse);
String rawValue = node.path("key").asText();
String safeValue = sanitizeForXml(rawValue); // ← 关键清洗步骤
model.put("key", safeValue);
template.process(model, writer);
通过此方案,即可彻底规避因不可控外部数据导致的 XML 解析失败,保障 Freemarker 模板在打印、集成等 XML 场景下的健壮性与稳定性。










