与FOR XML更改编码连接

时间:2017-03-16 15:19:32

标签: sql-server xml tsql

我有一个查询,它将一个数字转换为一组ASCII字符,然后尝试将它们连接成一个字符串:

declare @number int = 651854564

;with cte as (
select @number prev_nr
    , cast(char(@number % 256) as nvarchar(100)) nextchar
union all
select prev_nr / 256    prev_nr
    , cast(char((prev_nr / 256) % 256) as nvarchar(100)) nextchar
from cte
where prev_nr <> 0)
select 
    cast(nextchar + '' as nvarchar(100))
from cte
where prev_nr <> 0
for xml path ('');

将上述数字拆分为单个字符所产生的字符为:

characters
ä
‚
Ú
&

但是当尝试将它们与FOR XML连接起来时,它们会更改编码,以便最终将&转换并连接到最终结果中:ä‚Ú&amp;

如何解决此问题,以便我可以获得正确的编码并生成ä‚Ú&结果?

我已经尝试将所有内容转换为nvarchar(100),但我觉得这没有任何影响(实际上几乎与编码无关 - 或者至少在我的方案中无用)。

我还尝试过知名的STUFFFOR XML,但这并没有真正帮助。

3 个答案:

答案 0 :(得分:5)

使用type directive in for xml queries

试试这个:

declare @number int = 651854564

;with cte as (
select @number prev_nr
    , cast(char(@number % 256) as nvarchar(100)) nextchar
union all
select prev_nr / 256    prev_nr
    , cast(char((prev_nr / 256) % 256) as nvarchar(100)) nextchar
from cte
where prev_nr <> 0
)

select (select 
    cast(nextchar + '' as nvarchar(100))
from cte
where prev_nr <> 0
for xml path (''), type).value('.','nvarchar(max)')

rextester演示:http://rextester.com/QRUE46541

返回:ä‚Ú&

答案 1 :(得分:1)

我认为更大的问题是:你为什么首先使用FOR XML? XML不适合这项任务,因为它有几个需要编码的“特殊”字符,因为它们在XML中具有功能意义。列表很短,甚至可以根据上下文(即属性与元素/内容)进行更改,如下所示:

SELECT N'& < > " ?' FOR XML PATH('');
-- &amp; &lt; &gt; " ?


SELECT N'& < > " ?' AS [attr] FOR XML RAW;
-- <row attr="&amp; &lt; &gt; &quot; ?"/>

考虑到你要完成的任务,你最好按照以下方式进行实际的字符串连接,而不是靠近XML:

DECLARE @number INT = 651854564;
DECLARE @Result NVARCHAR(MAX) = N'';

;WITH cte AS (
  SELECT @number prev_nr
      , CAST(CHAR(@number % 256) AS NVARCHAR(100)) nextchar
  UNION ALL
  SELECT prev_nr / 256    prev_nr
      , CAST(CHAR((prev_nr / 256) % 256) AS NVARCHAR(100)) nextchar
  FROM cte
  WHERE prev_nr <> 0
)
SELECT  @Result += CAST(nextchar + N'' AS NVARCHAR(100))
FROM cte
WHERE prev_nr <> 0;

SELECT @Result;

-- ä‚Ú&

我只是声明了@Result NVARCHAR(MAX) = N'',然后将SELECT更改为@Result +=,并删除了FOR XML

答案 2 :(得分:0)

如果您想避免使用XML编码,那么您可以执行以下操作:

SELECT STUFF((SELECT ','+Name AS [text()] FROM #Test FOR XML PATH(''), 
TYPE).value('.', 'VARCHAR(MAX)'),1,1,'') AS 'NameList'

添加:     ,类型).value(&#39;。&#39;,&#39; VARCHAR(MAX)&#39;),1,1,&#39;&#39;) 你跳过XML编码。