以XML数据类型存储特殊字符(例如&)

时间:2012-06-10 06:47:02

标签: sql sql-server xml sql-server-2008

如果我这样做

Declare @t table(Email xml)
Declare @email varchar(100) = 'xxx&xx@monop.com'
Insert into @t  
select '<Emails> <Email>' + @email +'</Email></Emails>'
select * From @t

我会得到预期的错误

Msg 9411,Level 16,State 1,Line 8 XML解析:第1行,第27个字符,预期分号

我在几乎所有地方(包括SO)找到的一个解决方案是replace '&' with '&amp;,它可以正常工作

Insert into @t  
select CAST('<Emails><Email>' + REPLACE(@email, '&', '&amp;') + '</Email></Emails>' AS XML)

输出

<Emails><Email>xxx&amp;xx@monop.com</Email></Emails>

但是,我尝试使用CData方法(只是解决问题的另一种方法)

Declare @t table(Email xml)
Declare @email varchar(100) = 'xxx&xx@monop.com'
Insert into @t  
Select CAST('<![CDATA[Emails> <Email>' + @email + '</Email> </Emails]]>' AS XML)
select * From @t

当我得到以下输出

Emails&gt; &lt;Email&gt;xxx&amp;xx@monop.com&lt;/Email&gt; &lt;/Emails

我想要实现的是按原样存储数据,即所需的输出应该是

<Emails><Email>xxx&xx@monop.com</Email></Emails>

是否可能?

我知道如果xml无法理解的任何其他特殊字符将作为输入传递给它,则替换函数将失败,例如'&LT;'我再次需要更换它......

由于

2 个答案:

答案 0 :(得分:3)

标签是PCDATA,而不是CDATA,所以不要将它们放在CDATA部分。

答案 1 :(得分:2)

使用XML时,您应该使用SQL Server的XML相关功能。

例如:

/* Create xml and add a variable to it */
DECLARE 
    @xml xml = '<Emails />',
    @email varchar(100) = 'xxx&xx@monop.com';

SET @xml.modify ('insert (
    element Email {sql:variable("@email")}
) into (/Emails)[1]');

SELECT @xml;

/* Output:
<Emails>
  <Email>xxx&amp;xx@monop.com</Email>
</Emails>
*/

/* Extract value from xml */

DECLARE @email_out varchar(200);

SET @email_out = @xml.value ('(/Emails/Email)[1]', 'varchar (200)');

SELECT @email_out; /* Returns xxx&xx@monop.com */
祝你好运

罗马