sql - 转换时转义 XML 特殊字符

标签 sql xml csv tsql sql-server-2014

我有适合我需要的工作 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

唯一的问题是,如果我在 data 中引入 XML 敏感字符,例如 &:

insert into @t select 'i,j,&,k'

失败并出现错误:字符 24,非法字符

一种解决方案是即时将 & 字符替换为 &,如下所示:

select convert(xml,'<f><e>' + replace(replace(data,'&','&amp'),',', '</e><e>') + '</e></f>') as xm 

但是有几十个特殊的 XML 字符我需要在转换时转义,我真的不能在里面嵌套几十个 replace(replace(replace(... 函数。就是这样我做到了,但很乱。

如何修改上述代码以转义 XML 敏感字符,并产生相同的结果?

谢谢!

最佳答案

您已经从 Martin Smith 那里得到了答案。但我认为,值得在这里为追随者提供一个答案。想要提供一些解释,此外,rextester-link 将来可能无法访问...

如果你在这样的表中想到一个字符串......

DECLARE @mockup TABLE(SomeXMLstring VARCHAR(100));
INSERT INTO @mockup VALUES('This is a string with forbidden characters like "<", ">" or "&"');

-- ...您可以轻松添加 XML 标签:

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 &与相应的实体 &lt;, &gt; and &amp; .但这将需要大量替换以确保安全

--但是 XML 正在为我们隐式地做这一切

SELECT SomeXMLstring 
FROM @mockup
FOR XML PATH('')

--这是结果

<SomeXMLstring>This is a string with forbidden characters like "&lt;", "&gt;" or "&amp;"</SomeXMLstring>

--有趣的是:我们可以很容易地用AS [*]创建一个无名元素。 :

SELECT SomeXMLstring AS [*]
FROM @mockup
FOR XML PATH('')

--结果是一样的,但是没有标签:

This is a string with forbidden characters like "&lt;", "&gt;" or "&amp;"

--虽然这在 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

关于sql - 转换时转义 XML 特殊字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53677197/

相关文章:

python - libxml 解决 python 的 utf 编码问题还是我的问题?

Java:使用 Jackson 将 CSV 转换为 XML

sql - 为什么在访问函数(在 SELECT 中)返回的数组时需要添加括号?

MySQL 过程 - 如果不存在则插入行

php - 将 if 语句和多个 sql 查询合并为一个查询

php - 错误 SQLSTATE[42000] : Syntax error or access violation: 1064 You have an error in your SQL syntax

java - 从URL下载xml文件进行解析

java - 升级到 Spring Security 4 后尝试登录时出现 404

javascript - 虚线不起作用

java - 在Java中显示表情符号(jFrame)