freemarker生成xml需禁用html转义,推荐在模板顶部声明output_format="xml",变量输出用${user.name?xml}或${user.name!}确保xml字符安全转义。

FreeMarker生成XML的关键是关闭HTML转义
默认情况下,FreeMarker会对输出内容做HTML转义(比如 变成 <code><),这会让生成的XML直接失效。必须显式禁用转义,否则得到的不是合法XML,而是被“污染”的文本。
- 使用
全局包裹不推荐——它只对字符串生效,且容易漏掉嵌套结构 - 更可靠的方式是:在模板顶部声明
,强制整个模板按XML格式渲染 - 如果已有全局HTML配置(如Spring Boot中默认设为HTML),需在具体模板里覆盖:
变量输出必须用 ! 或 ?xml 显式处理特殊字符
即使设了 output_format="XML",FreeMarker仍不会自动转义变量值里的 、<code>&、" 等——这些必须手动处理,否则XML解析失败。
- 推荐写法:
${user.name?xml}—— 安全转义所有XML敏感字符 - 简写等价:
${user.name!}(前提是全局output_format="XML"已生效) - 避免直接写
${user.name},哪怕值看起来“干净”,只要含&或就会破坏XML结构
注意命名空间、CDATA 和空元素的写法
FreeMarker本身不校验XML语法,但生成结果必须符合规范,否则下游系统(如SOAP服务、配置加载器)会拒收。
- 命名空间要写全:
<rss xmlns="http://purl.org/rss/1.0/"></rss>,不能靠变量拼接导致引号错位 - 含HTML片段的内容应包进
:<description></description> - 自闭合标签必须写明确:
<image></image>而非<image></image>,后者在严格XML解析器里可能被当成有子节点
<#ftl output_format="XML" encoding="UTF-8">
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<book id="${book.id?xml}">
<title>${book.title?xml}</title>
<author>${book.author?xml}</author>
<summary><![CDATA[${book.summary}]]></summary>
</book>
</catalog>
XML生成真正难的不是语法,而是**信任边界**:你永远不知道数据源里有没有未预期的 、BOM头、或混合了UTF-8和Latin-1的字段。别依赖“看起来没问题”,每个变量输出都要过 ?xml。









