如何去除SQL Server生成XML中的<和>转义字符?
问题
你尝试用SQL Server生成XML文件,但输出不符合预期:
- 当前输出的XML标签被转义(比如
<变成<),且示例输出存在截断 - 期望得到未转义的原始XML标签
你的SQL代码:
set nocount on create table #tmp( NrCrt int identity ,XML varchar(max) ) declare @lni numeric(19,4) set @lni = 0 while (@lni <10000) begin insert into #tmp (XML) select '<ns>TEST</ns>' if (ROUND(@lnI/1000,0) = @lnI/1000) begin print @lnI end set @lnI = @lnI +1 end Select XML as [text()] from #tmp order by NrCrt FOR XML path('') drop table #tmp
当前错误输出:
&lt;ns&gt;TEST&lt;/ns&gt;&lt;ns&gt;TEST&lt;
期望输出:
<ns>TEST</ns><ns>TEST</ns>
解决方案
问题原因
- 你用
varchar(max)存储XML片段,SQL Server执行FOR XML path('')时,会自动将<、>等特殊字符转义为实体引用,导致输出不是原始XML - 示例输出的截断大概率是工具的显示限制,并非实际生成内容的问题
修复方法
方法一:修改临时表字段类型为xml
将临时表的XML字段改为xml类型,配合TYPE指令和.value()方法提取未转义的内容:
set nocount on create table #tmp( NrCrt int identity ,XML xml -- 改为xml类型 ) declare @lni numeric(19,4) set @lni = 0 while (@lni <10000) begin insert into #tmp (XML) select '<ns>TEST</ns>' if (ROUND(@lnI/1000,0) = @lnI/1000) begin print @lnI end set @lnI = @lnI +1 end -- 通过TYPE获取xml类型结果,再提取未转义的字符串 Select (select XML as [text()] from #tmp order by NrCrt FOR XML path(''), TYPE).value('.', 'varchar(max)') drop table #tmp
方法二:简化代码(无需临时表)
用递归CTE生成序列,避免循环插入临时表的性能开销,同样实现需求:
set nocount on; WITH Numbers AS ( SELECT 0 AS NrCrt UNION ALL SELECT NrCrt + 1 FROM Numbers WHERE NrCrt < 9999 ) SELECT (SELECT '<ns>TEST</ns>' AS [text()] FROM Numbers ORDER BY NrCrt FOR XML path(''), TYPE).value('.', 'varchar(max)') OPTION (MAXRECURSION 0);
说明
- 改为
xml类型后,SQL Server会正确识别XML内容,不会随意转义标签 FOR XML path('', TYPE)返回原生xml类型,再用.value('.', 'varchar(max)')可以直接得到未转义的完整XML字符串
内容的提问来源于stack exchange,提问作者Sven Alexander Gal
相关产品推荐
相关产品推荐

