解决XSLT转换中的中文乱码问题

xslt中文乱码主因是编码链断裂,需确保文件声明(首行无bom)、处理器配置(如xsltproc加–encoding utf-8、saxon用streamsource)、xsl:output显式设encoding=”utf-8″、java避免string中间转换、http头与html meta统一为utf-8。

解决XSLT转换中的中文乱码问题

确认XSLT处理器默认编码是否为UTF-8

很多XSLT处理器(如Saxon、Xalan、libxslt)在未显式声明编码时,会按系统默认编码(如Windows上的GBK)读取XSL或XML文件,导致中文被错误解析。关键不是“有没有设UTF-8”,而是“有没有被真正生效”。

  • <?xml version="1.0" encoding="UTF-8"?> 必须出现在XML/XSL文件的**第一行且无BOM前导空格**,否则部分处理器(尤其是Java系)会忽略该声明
  • Saxon 9+ 默认用UTF-8,但若通过StreamSource构造时传入InputStream而非File,则编码由InputStreamReader决定,与XML声明无关
  • libxslt(命令行xsltproc)默认按系统locale解析,需加--encoding UTF-8参数强制指定

在XSL中显式声明输出编码并禁用HTML转义

即使输入正确,输出仍可能乱码——常见于用<output method="html"></output>时,浏览器按meta或HTTP头推断编码失败。

  • 必须在XSL根元素内添加:
    <xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes" indent="no"/>
  • 若输出含中文标签名或属性值(如张三姓名>),确保method="xml"encoding="UTF-8",否则某些处理器会把非ASCII字符转成实体
  • 避免在XSL中用<text disable-output-escaping="yes"></text>包裹中文,这容易触发双重编码(如张三

Java调用时绕过String中间转换

Java中常见错误:用new String(bytes, "GBK")再转回getBytes("UTF-8"),等于把乱码当原文二次编码。

  • 直接用StreamSource加载文件:
    new StreamSource(new File("input.xml"))

    —— 此时SAXParser自动读取XML声明中的encoding

  • 若必须用字符串输入,用StreamSource(new ByteArrayInputStream(xmlStr.getBytes(StandardCharsets.UTF_8))),并手动设置setSystemId("UTF-8")(部分老版本Xalan需要)
  • 输出到OutputStream时,务必用OutputStreamWriter(out, StandardCharsets.UTF_8)包装,不要用PrintWriter默认构造

检查HTTP响应头与HTML meta是否冲突

当XSLT输出HTML并在浏览器中打开时,乱码常源于编码声明打架。

  • 如果服务端返回HTTP头Content-Type: text/html; charset=GBK,即使HTML里有<meta charset="UTF-8">,Chrome也会优先信HTTP头
  • curl -I确认实际响应头;若用Jetty/Tomcat,检查response.setCharacterEncoding("UTF-8")是否调用
  • XSL中生成<meta>要写全:
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

    (仅charset="UTF-8"在旧IE中不生效)

XSLT中文乱码本质是编码链断裂:文件读取→DOM构建→模板匹配→序列化输出→HTTP传输→浏览器渲染,任一环节未对齐UTF-8都会出问题。最易被忽略的是libxslt命令行缺--encoding,以及Java中String构造时隐式使用平台默认编码。