FOR XML PATH ( ''): gli spruzzi di caratteri “speciali”
-
20-08-2019 - |
Domanda
Questo codice si traduce fondamentalmente caratteri in base alla posizione in una stringa al carattere nella stessa posizione in un'altra stringa e funziona per tutte le righe della tabella.
Quando ho eseguito questo (versione semplificata):
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
ottengo il seguente:
RowID readable
----------- ---------------------------------------
1 a simple translation
2 hello world
3 wow you ran this
Ma necessità:
RowID readable
----------- ---------------------------------------
1 a simple translation
2 hello world
3 wow you ran this
C'è un modo, diverso REPLACE()
, di avere gli spazi appaiono correttamente? Questo accade anche su interruzioni di riga, nel mio codice vero e proprio.
Può questo essere riscritta in un modo migliore? Sono fondamentalmente solo usato il FOR XML PATH('')
per concatenare i singoli valori di riga insieme.
Soluzione
L'XML che si ottiene è corretta. E ' XML , non il testo, e leggibile in formato XML da un parser XML. I caratteri speciali sono correttamente fuggiti, come dovrebbero essere. Qualunque modulo client si dispone che consuma che XML dovrebbe analizzare come XML, non come testo, e allora sarà visualizzato correttamente.
Aggiornamento:
Nel caso in cui non è chiaro, tutto quello che dovete fare nella query è per il trattamento di XML come XML e testo come testo, non mescolare XML come testo, vale a dire:
;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