SpringBoot中Freemarker模板触发SAXParseException的原因及解决方法
问题分析与解决:Freemarker生成XML文档时的实体解析错误
问题场景
在SpringBoot中使用Freemarker生成XML格式文档时,模板片段如下:
<tr> <td style="width: 100%" align='center'> <div class="logo-container"> <img class="company-logo" src="${companyLogo}" alt="LOGO" align='center'" /> </div> </td> </tr>
传入的companyLogo变量值为带签名的S3 URL:
..../image/tmpimages.png.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20240725T043642Z&X-Amz-SignedHeaders=host&X-Amz-Expires=360000&X-Amz-Credential=xxxxxxxxxxxx%wdddeddd%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Signature=.....
运行时抛出错误:
"Can't load the XML resource (using TrAX transformer). org.xml.sax.SAXParseException; lineNumber: 87; columnNumber: 180; The reference to entity \"X-Amz-Date\" must end with the ';' delimiter."
错误成因
XML语法规定,&是实体引用的起始标记,必须以;结尾(如&代表普通的&符号)。但传入的URL中直接用&分隔参数,生成的XML内容会保留原始&,XML解析器会将&X-Amz-Date识别为未完成的实体引用,从而触发解析错误。
解决方法
- 模板中使用Freemarker内置转义函数:将模板里的变量输出改为
${companyLogo?xml},该函数会自动把XML特殊字符(包括&、<、>等)转义为合法的实体引用。修改后的模板片段:<img class="company-logo" src="${companyLogo?xml}" alt="LOGO" align='center'" /> - 代码层提前转义URL:在将
companyLogo传入模板前,手动替换URL中的&为&,示例代码:String companyLogo = "原始带&的URL"; String escapedLogoUrl = companyLogo.replace("&", "&"); model.addAttribute("companyLogo", escapedLogoUrl); - 配置Freemarker自动转义:在SpringBoot配置文件中设置Freemarker输出格式为XML,让框架自动处理内容转义。在
application.properties中添加:spring.freemarker.output-format=XML
内容的提问来源于stack exchange,提问作者Mandroid
相关产品推荐
相关产品推荐

