我有一个SQL Server表,该表以XML形式从XML中提取数据
SELECT * FROM myTable FOR XML PATH( 'myElement' ), ROOT( 'myDocument' ), TYPE
通过某种方式,用户设法将控制字符输入到自由文本字段(Ctrl-V)中,这意味着上面的查询失败并显示错误:
FOR XML could not serialize the data for node 'MYFIELDNAME' because it contains a character
(0x0016) which is not allowed in XML. To retrieve this data using FOR XML, convert it into
binary, varbinary, or use the BINARY BASE64 directive.
由于我期望数据是文本,所以我不想将其转换为二进制形式,而是在源代码中去除所有无效的XML字符。
我在SO上找到了以下内容:
How to make FOR XML PATH not choke on ASCII Control Codes
但是它没有帮助,因为它不能解决最初提出的问题,但是可以纠正OP对XML规范的误读。
是否存在全局指导SQL Server去除无效字符而不是生成此错误的任何东西?
谢谢!
答案 0 :(得分:0)
在转换为XML之前,您必须使用代码剥离字符。 通常,我会使用以下逻辑通过CTE进行此操作,然后在cte上使用FOX XML。
这不是最有效的,但可以解决问题:
Select @FileDatePart = CONVERT(VARCHAR(MAX),Getdate(), 22)
Select @FileDatePart = Replace(@FileDatePart, a.search, a.replace)
From (
Values ( '/', '' )
, ( ':', '' )
, ( ' ', '' )
) As a([Search], [Replace])
要使用ASCII码
Select @FileDatePart = Replace(@FileDatePart, a.search, a.replace)
From (
Values (char(47), '' )
, ( char(58), '' )
, ( char(32), '' )
) As a([Search], [Replace])
用于ASCII值表
DECLARE @i INTEGER = 0
DECLARE @j INTEGER = 0
DECLARE @Step INTEGER = 16
DECLARE @Lim INTEGER = 255
DECLARE @aLine VARCHAR(MAX) = ''
DECLARE @Dec VARCHAR(MAX) = ''
SELECT @Dec += 'Declare @i AS INTEGER = 1' + CHAR(13) + 'Declare @step as integer = ' + CAST(@Step AS VARCHAR(25)) + CHAR(13) + 'While @i * @Step < ' + CAST(@Lim AS VARCHAR(25)) + ' Begin '
+ CHAR(13)
WHILE(@i < @Step)
BEGIN
SELECT @i += 1
SELECT @aLine =
@aLine + ' @i -1 + ' + CAST(@i AS VARCHAR(25)) + ' as Col' + CAST(@i AS VARCHAR(25)) + ', Isnull(cast(char(@i +' + CAST(@i - 1 AS VARCHAR(25)) + ') as Varchar(25)),''*NA*'') as VAL'
+ CAST(@i AS VARCHAR(25)) + CASE
WHEN @i < @Step THEN ','
ELSE ''
END
END
SELECT @i = 1
DECLARE @output VARCHAR(MAX) = 'Select ' + REPLACE(@aLine, '@i', CAST(@i + @j AS VARCHAR(5)))
SELECT @i += @Step
WHILE @i <= @Lim
BEGIN
SELECT @output += CHAR(13) + 'union Select ' + REPLACE(@aLine, '@i', CAST(@i + @j AS VARCHAR(5)))
SELECT @i += @Step
END
EXEC(@output)
GO