
本文介绍在使用 xslt(尤其是 .net 环境)将含特殊字符(如 `<script>`)的 xml 数据转换为 <a style="color:#f60; text-decoration:underline;" title= "html" href="https://www.php.cn/zt/15763.html" target="_blank">html 时,如何确保**所有文本内容(包括属性值和元素内容)均被正确 html 转义**,防止 xss 风险与解析错误。</script>
在标准 .NET System.Xml.Xsl(XSLT 1.0)中,
例如,原始 XML 中的:
<Name>hello <script>alert('!')</script></Name>在 XSLT 1.0 中使用:
<input type="text" value="{/Contact/Name}"/>会生成未转义的 value="hello <script>alert('!')</script>",而非预期的 value="hello <script>alert('!')</script>"。
立即学习“前端免费学习笔记(深入)”;
✅ 正确方案:升级至 XSLT 3.0 + XHTML 输出方法
XSLT 3.0 规范明确要求:当 时,所有属性值中的动态内容必须按 XHTML 规则进行 HTML 字符实体转义(参见 XSLT 3.0 § 19.2.4)。这是解决该问题最标准、最可靠的方式。
示例代码(基于 SaxonCS / Saxon HE + .NET 6+)
using net.sf.saxon.s9api;
using System.IO;
var processor = new Processor(false);
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.AsSource()).Load30();
var inputDoc = processor.NewDocumentBuilder().Build(xml.AsSource());
using var output = new StringWriter();
executable.ApplyTemplates(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>⚠️ 注意事项:.NET 原生 XslCompiledTransform 不支持 XSLT 3.0,必须引入第三方处理器(如 SaxonCS 商业版,或开源兼容方案如 IKVM + Saxon HE Java 版)。使用 method="xhtml" 而非 "html" 是关键:xhtml 模式启用严格转义策略;html 模式为向后兼容,对属性值插值不做转义。若需保留 JSON-like 属性(如 data-title),建议用 concat() 构造字符串,避免模板中引号嵌套混乱;也可改用 xsl:attribute 显式构造并配合 xsl:value-of disable-output-escaping="no"(默认即为 no)。
? 替代方案(仅限 XSLT 1.0 场景)
若无法升级 XSLT 版本,可借助扩展函数手动转义(需自定义 msxsl:script 或 C# 扩展),但存在维护性差、跨平台受限等问题,不推荐用于生产环境。
✅ 总结
| 方案 | 是否推荐 | 原因 |
|---|---|---|
| XSLT 1.0 + System.Xml.Xsl | ❌ | 属性值插值无自动转义,存在 XSS 和解析风险 |
| XSLT 3.0 + method="xhtml"(Saxon) | ✅✅✅ | 标准合规、自动转义、语义清晰、安全可靠 |
| 自定义扩展函数转义 | ⚠️ | 可行但耦合度高、难以测试、非标准 |
始终优先采用 XSLT 3.0 + XHTML 输出方法,这是现代 Web 安全与标准化实践的必然选择。











