FreeMarker作为轻量级的模板引擎,常被用于根据数据动态生成各类文本文件,其中生成XML文件是常见需求之一。要实现这一功能,需要同时掌握FreeMarker的FTL语法规则和XML的书写规范,避免生成的内容出现格式错误。

FreeMarker生成XML的基础准备
首先需要搭建FreeMarker的运行环境,在Java项目中可以通过Maven引入依赖:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version>
</dependency>
接着需要创建FreeMarker的配置实例,指定模板文件的加载路径,核心初始化代码如下:
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class XmlGenerator {
public static void main(String[] args) throws IOException, TemplateException {
// 创建FreeMarker配置实例
Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
// 指定模板文件所在目录
cfg.setDirectoryForTemplateLoading(new File("src/main/resources/templates"));
// 设置字符编码
cfg.setDefaultEncoding("UTF-8");
// 加载FTL模板文件
Template template = cfg.getTemplate("user.xml.ftl");
// 准备模板数据
Map<String, Object> data = new HashMap<>();
data.put("userName", "张三");
data.put("age", 25);
data.put("hobbies", new String[]{"读书", "跑步", "编程"});
// 生成XML文件
FileWriter writer = new FileWriter("output/user.xml");
template.process(data, writer);
writer.close();
}
}
FTL基础语法在XML生成中的应用
变量输出
在FTL模板中,使用${变量名}的格式输出数据,生成XML时需要注意XML的特殊字符转义,FreeMarker默认会对输出的内容进行HTML转义,如果需要生成XML,建议手动处理特殊字符,或者使用?xml内置函数:
<?xml version="1.0" encoding="UTF-8"?>
<user>
<name>${userName?xml}</name>
<age>${age}</age>
</user>
如果变量值中包含<、>、&等XML特殊字符,?xml函数会自动将其转义为对应的实体,避免XML格式错误。
循环语法
当XML中需要生成重复的节点时,可以使用FTL的<#list>循环语法,例如生成用户的爱好列表:
<?xml version="1.0" encoding="UTF-8"?>
<user>
<name>${userName?xml}</name>
<age>${age}</age>
<hobbies>
<#list hobbies as hobby>
<hobby>${hobby?xml}</hobby>
</#list>
</hobbies>
</user>
上述代码中,<#list hobbies as hobby>会遍历hobbies数组,每次循环将当前元素赋值给hobby变量,生成对应的<hobby>节点。
条件判断语法
如果需要根据数据动态决定是否生成某个XML节点,可以使用<#if>条件判断语法,例如只有当用户年龄大于18岁时才生成成年标记:
<?xml version="1.0" encoding="UTF-8"?>
<user>
<name>${userName?xml}</name>
<age>${age}</age>
<#if age > 18>
<adult>true</adult>
</#if>
</user>
条件判断还支持<#else>分支,满足复杂的条件逻辑需求:
<#if age > 18> <user_type>成年用户</user_type> <#else> <user_type>未成年用户</user_type> </#if>
生成复杂XML的进阶技巧
处理XML命名空间
如果生成的XML需要包含命名空间,直接在FTL模板中按照XML规范书写即可:
<?xml version="1.0" encoding="UTF-8"?>
<user xmlns="http://www.ipipp.com/user"
xmlns:addr="http://www.ipipp.com/address">
<name>${userName?xml}</name>
<addr:location>北京</addr:location>
</user>
自定义函数处理数据
如果需要对数据做特殊处理再输出到XML中,可以在Java代码中自定义方法,放到模板数据中使用,例如格式化日期:
import freemarker.template.SimpleMethodModel;
import freemarker.template.TemplateMethodModelEx;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class DateFormatMethod implements TemplateMethodModelEx {
@Override
public Object exec(List arguments) {
Date date = (Date) arguments.get(0);
String pattern = arguments.get(1).toString();
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.format(date);
}
}
// 在main方法中添加数据
data.put("createTime", new Date());
data.put("formatDate", new DateFormatMethod());
对应的FTL模板中使用方式:
<create_time>${formatDate(createTime, "yyyy-MM-dd HH:mm:ss")}</create_time>
常见问题与注意事项
- XML文件的声明
<?xml version="1.0" encoding="UTF-8"?>需要放在FTL模板的第一行,前面不能有任何空白字符或者换行,否则会导致XML格式错误。 - 生成XML时建议统一使用UTF-8编码,避免中文乱码问题,FreeMarker的配置和输出流的编码都需要保持一致。
- 如果FTL模板中包含大量的静态XML内容,注意静态内容中的
<、>不需要转义,只有动态输出的变量中如果包含这些字符才需要处理。 - 如果XML结构比较复杂,建议先写好静态的XML样例,再逐步替换为FTL的动态语法,降低出错概率。
通过以上FTL语法和注意事项,就可以使用FreeMarker模板稳定生成符合要求的XML文件,满足各类业务场景的需求。
FreeMarkerXMLFTL语法模板生成修改时间:2026-06-10 12:24:30