Как удалить недопустимые символы из запроса FOR XML PATH в SQLServer - PullRequest
1 голос
/ 28 марта 2019

У меня есть таблица SQL Server, из которой я извлекаю данные в виде 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 я нашел следующее:

Как сделать так, чтобы FOR XML PATH не подавлялся управляющими кодами ASCII

, но это нене помогает, поскольку не решает первоначальный заданный вопрос, но исправляет неправильное прочтение OP спецификации XML.

Существует ли какой-либо глобальный указатель SQL-Server для удаления недопустимых символов вместо генерации этой ошибки?

Спасибо!

1 Ответ

0 голосов
/ 28 марта 2019

Вы должны использовать код для удаления символов перед преобразованием в XML.Обычно я делаю это через CTE, используя следующую логику, а затем использую FOX XML для cte.

Это не будет наиболее эффективным, но поможет:

    Select @FileDatePart = CONVERT(VARCHAR(MAX),Getdate(), 22)

    Select @FileDatePart = Replace(@FileDatePart, a.search, a.replace)
    From (
    Values ( '/', '' )
    ,      ( ':', '' )
    ,      ( ' ', '' )

    ) As a([Search], [Replace])

Toиспользуйте коды 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
...