最近在做合同单据自动生成的时候,我一度被“Word 怎么转成 FTL 模板”这件事卡了两天。搜出来的结果非常一致:先把 Word 另存为 Word 2003 XML,然后把 XML 后缀改成 ftl,接着在 Java 里用 FreeMarker 填充数据。我对这个结论的第一反应是抗拒,都到 2025 年了,为什么还要用 Office 2003 年留下的老旧格式?等我真的把 docx、doc、Word 2003 XML 三种格式全部手工拆开看了一遍,才明白网上那些教程并不是老古董,它们只是选了一条最省事、最少踩坑的路。
这篇东西就给所有正在被 Word 转 FTL 折磨的人一个完整解释:Word 2003 XML 到底解决了什么问题,完整的操作步骤是什么,以及教程里很少提到的那些坑——占位符被 Word 拆散、特殊字符把 XML 搞坏、表格循环怎么写。我的目标是让看完的人能直接在自己的项目里复现,而不是只得到一句“用 2003 XML 就行”。
1. 先解掉一个常见的概念混淆:FTL 不是 Word 格式
1.1 你真正想做的事情
先说结论:Word 转 FTL,本质不是“格式转换”,而是“把一份排版好的 Word 文档,加工成一个可以重复填数据的模板文件”。
FTL 是 FreeMarker 模板文件的后缀,它本身只是一段带占位符的文本。FreeMarker 在渲染时读取这份文本,把里面的 ${变量} 替换成真实数据,把 [#list] 这样的指令展开成重复内容,最后输出一个完整的、不再包含任何模板指令的结果。
问题是 Word 文档并不是文本。doc 是二进制格式,不能直接打开编辑它的内容结构;docx 虽然内部是 XML,却被 zip 压缩成了一个包,你要改里面的内容必须先解压、再修改、最后重新打包;而 Word 2003 XML 是一个没有压缩、没有二次包装的纯 XML 文件,既能被 Word 打开编辑,又能直接用普通文本编辑器处理。
所以“Word 转 FTL”实际上是一条两步链路:
text复制Word 原文件 -> 可编辑的中间 XML -> 加入占位符和 FreeMarker 指令 -> 得到 .ftl 模板
1.2 “转 FTL”不是一次另存为,而是一次模板化加工
很多人一开始会误以为“转 FTL”就是在 Word 里点击“另存为”,然后选一个 FTL 格式。这个操作不存在,Word 并不认识 FTL。
你真正要做的是:
- 把 Word 文档里的固定内容保留;
- 把需要动态变化的位置替换成
${字段名}; - 把需要重复的段落或表格行用
[#list]包起来; - 把需要条件展示的内容用
[#if]包起来; - 将整个文档另存为机器能识别的 XML 文本;
- 再将扩展名改成
.ftl交给 FreeMarker 使用。
如果你做的事只是“给一个现成的 Word 文档替换几个名字”,完全没必要上 FTL。直接用 Apache POI 操作 docx 就行。只有当文档结构复杂、需要循环表格、需要根据不同数据决定是否显示某一段、需要大批量生成几百份不同内容文件时,FTL 模板方案才真正体现出优势。
这也解释了为什么“Word 转 FTL”这个搜索词会被大家频繁搜——它不是某一个标准功能,而是一套由 FreeMarker 项目衍生出来的民间实践。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 为什么教程钟爱 Word 2003 XML:两个格式之间的差距不在“新旧”
2.1 DOCX 是压缩包,2003 XML 是一份纯文本
如果只是“Word 能不能转 FTL”,理论上用 docx 也可以。docx 本质是一个 zip 压缩包,里面的核心内容是 word/document.xml。你完全可以把 document.xml 解压出来,加上 ${占位符},再压缩回去。但为什么 90% 的教程不这么做?
因为 docx 的包结构太复杂了。一个最简 docx 解压出来至少有这些文件:
text复制[Content_Types].xml
_rels/.rels
word/document.xml
word/styles.xml
word/settings.xml
docProps/core.xml
docProps/app.xml
真正要填充的内容藏在 word/document.xml 里,而这个文件本身又带着一长串命名空间属性:
xml复制<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordpro
