XSLT 中安全转义 XML 内容以生成合规 HTML 的完整方案

在使用 xslt 将含特殊字符(如 `

在 XSLT 1.0(如 .NET 原生 System.Xml.Xsl)中,属性值插值(如 value="{/Contact/Name}")不会对 XPath 表达式结果执行 HTML 实体转义——即使源 XML 中已使用 zuojiankuohaophpcn、youjiankuohaophpcn 等编码,XSLT 引擎在求值后会还原为原始字符 ,直接插入属性导致 HTML 解析异常或脚本注入风险。而 xsl:value-of 默认启用转义,因此文本内容显示安全,但属性值却成为盲区。

✅ 正确解法:升级至 XHTML 输出模式(XSLT 3.0)

核心在于切换输出方法为 method="xhtml"(而非 "html"),并配合支持 XHTML 语义的处理器(如 Saxon)。XHTML 模式下,所有属性值(包括 {} 插值)均按 XML 规则严格转义,确保 → youjiankuohaophpcn、' → ' 等一一映射,生成真正可嵌入 HTML 文档且防 XSS 的字符串。

⚠️ 注意:.NET 原生 XslCompiledTransform 仅支持 XSLT 1.0,不支持 xhtml 输出方法或动态转义属性值。必须引入第三方处理器。

? 推荐方案:SaxonCS(.NET 6+/7+)或 Saxon HE + IKVM(.NET Framework)

以下为 .NET 7+ 使用 SaxonCS 12.x(商业版) 的最小可行示例(开源版 SaxonCS 功能受限,需企业许可获取完整 XHTML 支持):

using Saxon.Api;
using System.IO;

var processor = new Processor();
var xml = @"hello zuojiankuohaophpcnscriptyoujiankuohaophpcnalert('!')zuojiankuohaophpcn/scriptyoujiankuohaophpcn";
var xslt = @"

  
  
    
      Name: 
      Input: 
    
  
";

var compiler = processor.NewXsltCompiler();
var executable = compiler.Compile(xslt);
var transformer = executable.Load();

var inputDoc = processor.NewDocumentBuilder().Build(new StringReader(xml));
var output = new StringWriter();
transformer.Transform(inputDoc, processor.NewSerializer(output));

Console.WriteLine(output.ToString());

✅ 输出效果(关键部分):


  Name: hello zuojiankuohaophpcnscriptyoujiankuohaophpcnalert('!')zuojiankuohaophpcn/scriptyoujiankuohaophpcn
  Input: 

? 替代技巧(仅限 XSLT 1.0 场景,不推荐用于生产)

若无法引入 Saxon,可手动调用 disable-output-escaping="no"(默认即为 no)并改用 xsl:attribute 显式构造属性,结合 xsl:call-template 自定义转义逻辑(需预定义模板处理 , ', ", &),但代码臃肿且易出错,强烈建议优先升级工具链

✅ 最佳实践总结

  • 永远避免在 HTML 属性中直接使用 {XPath} 插值处理未信任内容;
  • 强制使用 xsl:output method="xhtml" + XSLT 3.0 处理器(SaxonCS/Saxon HE)是跨平台、标准兼容、零配置的安全方案;
  • 在构建流程中,将 XSLT 编译与执行分离,利用 Saxon 的静态分析能力提前捕获潜在转义漏洞;
  • 对最终 HTML 输出,建议叠加 CSP(Content-Security-Policy)头作为纵深防御补充。

通过此方案,你不仅能解决 data-title 和 value 属性的转义一致性问题,更能构建面向现代 Web 安全要求的可维护 XSLT 渲染管道。