ДЛЯ XML-ПУТИ("):Экранирование “специальных” символов
-
20-08-2019 - |
Вопрос
Этот код в основном преобразует символы, основанные на позиции в одной строке, в символ, занимающий ту же позицию в другой строке, и выполняется для всех строк таблицы.
Когда я запускаю это (упрощенная версия):
DECLARE @R char(40)
DECLARE @U char(40)
SET @R=' abcdefghijklmnopqrstuvwxyz!@#$%^&*()_+'+char(181)
SET @U=REVERSE(@R)
DECLARE @TestTable TABLE (RowID int identity(1,1) primary key, Unreadable varchar(500))
INSERT INTO @TestTable VALUES ('+µt$zw!*µsu+yt!+s$xy')
INSERT INTO @TestTable VALUES ('%*!!xµpxu!(')
INSERT INTO @TestTable VALUES ('pxpµnxrµu+yµs%$t')
;WITH CodeValues AS
(
SELECT
Number,SUBSTRING(@R,Number,1) AS R,ASCII(SUBSTRING(@U,Number,1)) AS UA
FROM Numbers
WHERE Number<=LEN(@R)
)
SELECT
t.RowID
,(SELECT
''+c.R
FROM Numbers n
INNER JOIN CodeValues c ON ASCII(SUBSTRING(t.Unreadable,n.Number,1))=c.UA
WHERE n.Number<=LEN(t.Unreadable)
FOR XML PATH('')
) AS readable
FROM @TestTable t
Я получаю следующее:
RowID readable
----------- ---------------------------------------
1 a simple translation
2 hello world
3 wow you ran this
Но нужно:
RowID readable
----------- ---------------------------------------
1 a simple translation
2 hello world
3 wow you ran this
Есть ли какой-нибудь способ, кроме REPLACE()
, чтобы пробелы отображались должным образом?Это также происходит при разрывах строк в моем реальном коде.
Можно ли это переписать лучшим образом?Я в основном просто использовал FOR XML PATH('')
чтобы объединить значения отдельных строк вместе.
Решение
XML, который вы получаете, является правильным.Это так XML - ФАЙЛ, а не текст, и читается как XML анализатором XML.Специальные символы должным образом экранированы, как и должно быть.Какой бы клиентский модуль у вас ни был, который использует этот XML, следует анализировать его как XML, а не как текст, и тогда он будет отображаться правильно.
Обновить:
В случае, если неясно, все, что вам нужно сделать в вашем запросе, это обработать XML как XML и text как текст, а не смешивать XML как текст, т.Е.:
;WITH CodeValues AS
(
SELECT
Number,SUBSTRING(@R,Number,1) AS R,ASCII(SUBSTRING(@U,Number,1)) AS UA
FROM Numbers
WHERE Number<=LEN(@R)
)
, XmlValues AS (
SELECT
t.RowID
,(SELECT
''+c.R
FROM Numbers n
INNER JOIN CodeValues c ON ASCII(SUBSTRING(t.Unreadable,n.Number,1))=c.UA
WHERE n.Number<=LEN(t.Unreadable)
FOR XML PATH(''), TYPE
) AS readable
FROM @TestTable t)
SELECT x.RowId,
x.readable.value('.', 'VARCHAR(8000)') as readable
FROM XmlValues AS x