Zine.net online

Witaj na Zine.net online Zaloguj się | Rejestracja | Pomoc
w Szukaj

dev2dev

Dziennik pokładowy MSSQL 2008 (wpis nr 0x0002)

Trafił mi się dziwny przypadek z XML-em w SQL Server 2008. Napisałem taki oto kod:
declare @xml xml

set @xml = '<?xml version="1.0" encoding="utf-8" ?><head></head>'

declare @mt table (col xml)

insert into @mt (col) values (@xml)

select col from @mt
uruchomiłem go i dostałem wynik:
<head/>
Wynik został uproszczony do jednego tag'a. Sprytne, pomyślałem sobie. Ale spróbowałem powyższy kod zapisać inaczej. O tak:
declare @xml xml

declare @t nvarchar(max)

set @t = '<?xml version="1.0" encoding="utf-8" ?><head></head>'

set @xml = @t

declare @mt table (col xml)

insert into @mt (col) values (@xml)

select col from @mt
Zmiana wydaje się być nieistotna. Ale jednak nie jest. Uruchomienie tego kodu kończy się komunikatem błędu:
Msg 9402, Level 16, State 1, Line 7
XML parsing: line 1, character 39, unable to switch the encoding
Jeżeli zmienię atrybut encoding na utf-16 to drugi przykład wykona się poprawnie i zgodnie z oczekiwaniami. Kto popełnia błąd? Ja czy SQL Server 2008? Sprawa jest jasna. Zmiennej nadałem typ nvarchar. OK, wobec tego zbuduję procedurę składowaną, która przez parametr będzie przekazywała nagłówek dokumentu XML czyli
<?xml version="1.0" encoding="utf-8" ?>
i parametr ten będzie przekazywany jak zmienna typu nvarchar. Procedura będzie zwracała wynik przez parametr też typu nvarchar.
CREATE PROCEDURE xmlCommand
@xmlHead nvarchar(256),
@xmlOut nvarchar(max) OUTPUT
AS
BEGIN
    DECLARE @xml = '<head></head>'

    SET @xmlOut = @xmlHead+CAST(@xml AS nvarchar(max))

END
Wynik będzie przekazywany do aplikacji .NET. I po jej stronie walidowany. String w .NET jest kodowany jako Unicode czyli utf-16 (chociaż dokumentacja podaje, że nie zawsze). Spodziewam się, że skoro nvarchar jest kodowany jako utf-16 to i takie kodowanie otrzyma aplikacja. Po stronie aplikacji kod walidacji wygląda następująco:
         db.ExecuteNonQuery(command);

         message = (string)replyCommand.Parameters["@xmlOut"].Value;

            try
            {
                XmlReaderSettings xrs = new XmlReaderSettings();
                xrs.ValidationType = ValidationType.Schema;

                xrs.Schemas = Schemas.Instance;

                UnicodeEncoding utf16 = new UnicodeEncoding();
                XmlTextReader xr=new XmlTextReader(new MemoryStream(utf16.GetBytes(message)));
                XmlReader xvr = XmlReader.Create(xr, xrs);
                XmlDocument xml = new XmlDocument();
                xml.Load(xvr);

            }
            catch (Exception exception)
            {
               
                throw new Exception(Utilities.NotValidated+exception.Message);
            }
I taki kod zgłasza wyjątek na okoliczność problemów z kodowaniem dokumentu. Jeżeli zamienię kodowanie na utf-8
                UTF8Encoding utf8 = new UTF8Encoding();
                XmlTextReader xr=new XmlTextReader(new MemoryStream(utf8.GetBytes(message)));
To walidacja przechodzi bez błędu. Gdzieś tu jest niespójność.

Opublikowane 19 października 2008 18:17 przez marekpow
Filed under: , , ,

Komentarze:

Brak komentarzy
Komentarze anonimowe wyłączone
W oparciu o Community Server (Personal Edition), Telligent Systems