转换时转义 XML 个特殊字符
Escape XML special characters upon convert
我有工作 csv 分离器满足我的需要。
您可以直接抓住并 运行 原样:
declare @t table(data varchar(max))
insert into @t select 'a,b,c,d'
insert into @t select 'e,,,h'
;with cte(xm) as
(
select convert(xml,'<f><e>' + replace(data,',', '</e><e>') + '</e></f>') as xm
from @t
)
select
xm.value('/f[1]/e[1]','varchar(32)'),
xm.value('/f[1]/e[2]','varchar(32)'),
xm.value('/f[1]/e[3]','varchar(32)'),
xm.value('/f[1]/e[4]','varchar(32)')
from cte
唯一的问题是,如果我在 数据 中引入 XML 敏感字符,例如 &:
insert into @t select 'i,j,&,k'
失败并出现错误:字符 24,非法字符
一种解决方案是即时将 & 字符替换为 &,如下所示:
select convert(xml,'<f><e>' + replace(replace(data,'&','&'),',', '</e><e>') + '</e></f>') as xm
但是有几十个特殊的XML字符我需要在转换时转义,我真的不能嵌套几十个replace(replace(replace(... 在那里发挥作用。我就是这样做的,而且很乱。
如何修改以上代码以转义 XML 个敏感字符,并产生相同的结果?
谢谢!
您已经从 Martin Smith 那里得到了答案。但我认为,值得在这里为追随者提供一个答案。想要提供一些解释,此外,rextester-link 将来可能无法访问...
如果你想到这样一个 table 中的字符串 ...
DECLARE @mockup TABLE(SomeXMLstring VARCHAR(100));
INSERT INTO @mockup VALUES('This is a string with forbidden characters like "<", ">" or "&"');
-- ...您可以轻松添加 XML-tags:
SELECT '<root>' + SomeXMLstring + '</root>'
FROM @mockup ;
--结果看起来像 XML
<root>This is a string with forbidden characters like "<", ">" or "&"</root>
--但事实并非如此!你可以测试一下,CAST( AS XML)
会失败:
SELECT CAST('<root>This is a string with forbidden characters like "<", ">" or "&"</root>' AS XML);
--有时人们会尝试自己进行替换,并开始用相应的实体 <, > and &
替换 <, > and &
。但这将需要大量替换才能安全。
--但是XML正在暗中为我们做这一切
SELECT SomeXMLstring
FROM @mockup
FOR XML PATH('')
--这是结果
<SomeXMLstring>This is a string with forbidden characters like "<", ">" or "&"</SomeXMLstring>
--有趣的是:我们可以用 AS [*]
:
轻松创建一个无名元素
SELECT SomeXMLstring AS [*]
FROM @mockup
FOR XML PATH('')
--结果是一样的,只是去掉了标签:
This is a string with forbidden characters like "<", ">" or "&"
--虽然这在 SSMS 中看起来像 XML,但在用作字符串时将隐式转换为 NVARCHAR(MAX)
。
--只要您觉得需要使用字符串连接构建 XML,就可以使用它隐式转义字符串:
SELECT CAST('<root>' + (SELECT SomeXMLstring AS [*] FOR XML PATH('')) + '</root>' AS XML)
FROM @mockup ;
最后回答你的问题
这一行必须使用的技巧:
select convert(xml,'<f><e>' + replace((SELECT data AS [*] FOR XML PATH('')),',', '</e><e>') + '</e></f>') as xm
我有工作 csv 分离器满足我的需要。
您可以直接抓住并 运行 原样:
declare @t table(data varchar(max))
insert into @t select 'a,b,c,d'
insert into @t select 'e,,,h'
;with cte(xm) as
(
select convert(xml,'<f><e>' + replace(data,',', '</e><e>') + '</e></f>') as xm
from @t
)
select
xm.value('/f[1]/e[1]','varchar(32)'),
xm.value('/f[1]/e[2]','varchar(32)'),
xm.value('/f[1]/e[3]','varchar(32)'),
xm.value('/f[1]/e[4]','varchar(32)')
from cte
唯一的问题是,如果我在 数据 中引入 XML 敏感字符,例如 &:
insert into @t select 'i,j,&,k'
失败并出现错误:字符 24,非法字符
一种解决方案是即时将 & 字符替换为 &,如下所示:
select convert(xml,'<f><e>' + replace(replace(data,'&','&'),',', '</e><e>') + '</e></f>') as xm
但是有几十个特殊的XML字符我需要在转换时转义,我真的不能嵌套几十个replace(replace(replace(... 在那里发挥作用。我就是这样做的,而且很乱。
如何修改以上代码以转义 XML 个敏感字符,并产生相同的结果?
谢谢!
您已经从 Martin Smith 那里得到了答案。但我认为,值得在这里为追随者提供一个答案。想要提供一些解释,此外,rextester-link 将来可能无法访问...
如果你想到这样一个 table 中的字符串 ...
DECLARE @mockup TABLE(SomeXMLstring VARCHAR(100));
INSERT INTO @mockup VALUES('This is a string with forbidden characters like "<", ">" or "&"');
-- ...您可以轻松添加 XML-tags:
SELECT '<root>' + SomeXMLstring + '</root>'
FROM @mockup ;
--结果看起来像 XML
<root>This is a string with forbidden characters like "<", ">" or "&"</root>
--但事实并非如此!你可以测试一下,CAST( AS XML)
会失败:
SELECT CAST('<root>This is a string with forbidden characters like "<", ">" or "&"</root>' AS XML);
--有时人们会尝试自己进行替换,并开始用相应的实体 <, > and &
替换 <, > and &
。但这将需要大量替换才能安全。
--但是XML正在暗中为我们做这一切
SELECT SomeXMLstring
FROM @mockup
FOR XML PATH('')
--这是结果
<SomeXMLstring>This is a string with forbidden characters like "<", ">" or "&"</SomeXMLstring>
--有趣的是:我们可以用 AS [*]
:
SELECT SomeXMLstring AS [*]
FROM @mockup
FOR XML PATH('')
--结果是一样的,只是去掉了标签:
This is a string with forbidden characters like "<", ">" or "&"
--虽然这在 SSMS 中看起来像 XML,但在用作字符串时将隐式转换为 NVARCHAR(MAX)
。
--只要您觉得需要使用字符串连接构建 XML,就可以使用它隐式转义字符串:
SELECT CAST('<root>' + (SELECT SomeXMLstring AS [*] FOR XML PATH('')) + '</root>' AS XML)
FROM @mockup ;
最后回答你的问题
这一行必须使用的技巧:
select convert(xml,'<f><e>' + replace((SELECT data AS [*] FOR XML PATH('')),',', '</e><e>') + '</e></f>') as xm