如何在XML中嵌入控制字符且不引发普通字符双重转义?
如何在XML中嵌入控制字符且不引发普通字符双重转义?
我来给你捋捋这个问题哈!你遇到的核心麻烦是XML本身不允许直接包含STX这类C0控制字符(除了制表、换行、回车这三个例外),而且你原来的嵌套FOR XML写法导致了普通字符被双重转义,比如&变成了&,这确实挺头疼的。
先说说你原来代码的问题:你内层用了一次FOR XML PATH('')把字符串转义,外层又套了一次FOR XML PATH('Test'),这就相当于把已经转义过的内容又转义了一遍,自然就出现了双重转义的情况。
那怎么解决呢?给你几个实用的办法:
方案一:把控制字符替换成XML实体引用,避免双重转义
你可以先手动把字符串里的STX字符(用NCHAR(2)表示)替换成XML实体,然后用TYPE指令来生成XML,这样SQL Server会正确处理内容,不会再次转义已经写好的实体引用,同时普通字符只会被转义一次。
比如这个代码:
DECLARE @Data table (String nvarchar(max)); -- 插入包含&和STX的测试数据 INSERT INTO @Data (String) VALUES (N'& hi' + NCHAR(2)); -- 处理控制字符并生成正确的XML SELECT -- 直接输出XML类型的结果 (SELECT REPLACE(String, NCHAR(2), N'') AS [*] FROM @Data FOR XML PATH('Test'), TYPE ) AS XML_Result; -- 或者输出XML字符串形式查看 SELECT CAST( (SELECT REPLACE(String, NCHAR(2), N'') AS [*] FROM @Data FOR XML PATH('Test'), TYPE ) AS NVARCHAR(MAX) ) AS XML_String_Result;
运行后,你会看到&被正确转义成&,而STX变成了,最终的XML内容是<Test>& hi</Test>,完全符合你的需求,没有双重转义。
方案二:用十六进制文本替代控制字符
如果你觉得实体引用不够直观,也可以把STX替换成0x0002这种十六进制文本,代码只需要把REPLACE的目标改成对应的字符串就行:
DECLARE @Data table (String nvarchar(max)); INSERT INTO @Data (String) VALUES (N'& hi' + NCHAR(2)); SELECT CAST( (SELECT REPLACE(String, NCHAR(2), N'0x0002') AS [*] FROM @Data FOR XML PATH('Test'), TYPE ) AS NVARCHAR(MAX) ) AS Result;
这样生成的XML就是<Test>& hi0x0002</Test>,也满足你的要求。
关键注意点
- 不要嵌套使用
FOR XML PATH,这是导致双重转义的核心原因,一次FOR XML PATH配合TYPE指令就足够处理了 TYPE指令很重要,它告诉SQL Server把结果当作XML类型处理,而不是普通字符串,这样手动替换的实体引用不会被再次转义
如果还有其他控制字符需要处理,只需要扩展REPLACE的逻辑,比如把所有需要处理的控制字符都替换成对应的实体或者文本就行。
内容来源于stack exchange
相关产品推荐
相关产品推荐

