You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Thymeleaf处理XML模板时UTF-8编码异常问题求助

Thymeleaf渲染XML模板时非ASCII字符被转义为十六进制实体的问题

问题描述

我正尝试使用Thymeleaf对以下XML模板进行简单变量替换:

<?xml version="1.0" encoding="UTF-8"?>  
<note>  
    <to>
        ARABIC: [[${TEST_AR}]]
        HEBREW: [[${TEST_HE}]]  
        CHINESE (MANDARIN): [[${TEST_CH}]]
    </to>
</note>

已配置模板、Java源码、OutputStreamWriter、ClassLoaderTemplateResolver及Maven均为UTF-8编码,但发现Thymeleaf渲染XML模板时,阿拉伯语、希伯来语等非ASCII字符被转换为十六进制实体;而使用TEXT模板(修改文件扩展名及对应代码行)时,UTF-8输出正常。

正常输出示例

<?xml version="1.0" encoding="UTF-8"?>  
<note>  
    <to>
        ARABIC: كتابة مفهومة من قبل اغل
        HEBREW: ניסיון  
        CHINESE (MANDARIN): 
    </to>
</note>

异常输出示例

<?xml version="1.0" encoding="UTF-8"?> 
<note>  
    <to>
        ARABIC: &#x643;&#x62a;&#x627;&#x628;&#x629; &#x645;&#x641;&#x647;&#x648;&#x645;&#x629; &#x645;&#x646; &#x642;&#x628;&#x644; &#x627;&#x63a;&#x644;
        HEBREW: &#x5e0;&#x5d9;&#x5e1;&#x5d9;&#x5d5;&#x5df;  
        CHINESE (MANDARIN): 
    </to>
</note>

完整可复现代码

package com.xerox;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;

public class TestThymeleafUTF8 {
    public static void main(String[] args) {
        try {
               TemplateEngine templateEngine = new TemplateEngine();
                ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
                resolver.setCharacterEncoding("UTF-8");     
                resolver.setTemplateMode(TemplateMode.TEXT);
                templateEngine.setTemplateResolver(resolver);
                Context ct = new Context();             
                ct.setVariable("TEST_AR", "كتابة مفهومة من قبل اغل");
                ct.setVariable("TEST_HE", "ניסיון");
                ct.setVariable("TEST_CN", "王明是中国人。");
                ct.setVariable("currentDate", LocalDateTime.now().toString());
                BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("test_output.txt"), StandardCharsets.UTF_8));
            
                templateEngine.process("test_template.txt", ct,out);
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

POM配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.xerox</groupId>
  <artifactId>testUTF</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>testUTF</name>
  <description>thymeleaf testUTF</description>
  
    <properties>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>   
  <dependencies>
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf</artifactId>
        <version>3.1.0.RELEASE</version>
    </dependency>

  </dependencies>
</project>

请问这是Thymeleaf的UTF-8 XML Bug,还是我遗漏了必要配置?


原因与解决方案

这不是Thymeleaf的Bug,是XML模板模式下的默认行为。Thymeleaf在XML模式中会自动转义非ASCII字符为实体引用,这是为了遵循XML规范——尽管UTF-8支持这些字符,但XML允许用实体表示字符,引擎默认启用了该逻辑;而TEXT模式无XML语法约束,直接输出原始UTF-8字符。

解决方法

方法1:局部关闭变量转义

将模板中的表达式从[[${变量名}]]改为[(${变量名})],Thymeleaf会对该表达式的输出关闭转义:

<?xml version="1.0" encoding="UTF-8"?>  
<note>  
    <to>
        ARABIC: [(${TEST_AR})]
        HEBREW: [(${TEST_HE})]  
        CHINESE (MANDARIN): [(${TEST_CH})]
    </to>
</note>

方法2:全局配置转义规则(不推荐)

若需全局禁用XML模板的非ASCII字符转义,可自定义XmlTemplateModeHandler,但该方式复杂度高,仅适合批量处理场景。

注意事项

关闭转义后需确保变量内容不含XML特殊字符(如<、>、&),否则会破坏XML合法性。若变量可能包含这类字符,建议仅对确定安全的非ASCII字符使用无转义表达式,或先对特殊字符做转义处理。


内容的提问来源于stack exchange,提问作者JavaSheriff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 03:25:29