
在使用 xslt 将含特殊字符(如 `<script>`)的 xml 转为 <a style="color:#f60; text-decoration:underline;" title= "html" href="https://www.php.cn/zt/15763.html" target="_blank">html 时,`xsl:value-of` 会自动转义文本节点,但属性值中的内联表达式(如 `value="{/contact/name}"`)默认不转义,易引发 xss 风险;本文提供兼容 <a style="color:#f60; text-decoration:underline;" title= ".net" href="https://www.php.cn/zt/64958.html" target="_blank">.net 生态的可靠转义策略。</script>
在 XSLT 1.0(如 .NET 原生 System.Xml.Xsl)中,属性值插值(如 value="{/Contact/Name}")不会对 XPath 表达式结果执行 HTML 实体转义——即使源 XML 中已使用 等编码,XSLT 引擎在求值后会还原为原始字符 < 和 >,直接插入属性导致 HTML 解析异常或脚本注入风险。而 xsl:value-of 默认启用转义,因此文本内容显示安全,但属性值却成为盲区。
✅ 正确解法:升级至 XHTML 输出模式(XSLT 3.0)
核心在于切换输出方法为 method="xhtml"(而非 "html"),并配合支持 XHTML 语义的处理器(如 Saxon)。XHTML 模式下,所有属性值(包括 {} 插值)均按 XML 规则严格转义,确保 < → 、' → ' 等一一映射,生成真正可嵌入 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 = @"<Contact><Name>hello <script>alert('!')</script></Name></Contact>";
var xslt = @"
<xsl:stylesheet version='3.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method='xhtml' indent='yes' html-version='5.0'
doctype-system='about:legacy-compat' omit-xml-declaration='yes'/>
<xsl:template match='/'>
<span data-title='{concat("{ 'title': '", /Contact/Name, "' }")}'>
Name: <xsl:value-of select='/Contact/Name'/>
Input: <input type='text' value='{/Contact/Name}'/>
</span>
</xsl:template>
</xsl:stylesheet>";
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());✅ 输出效果(关键部分):
立即学习“前端免费学习笔记(深入)”;
<span data-title="{ 'title': 'hello <script>alert('!')</script>' }">
Name: hello <script>alert('!')</script>
Input: <input type="text" value="hello <script>alert('!')</script>" />
</span>? 替代技巧(仅限 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 渲染管道。











