Поделиться через


Сериализация XML-данных

При явном или неявном приведении данных типа XML к строковому или двоичному типу данных SQL они сериализуются в соответствии с правилами, изложенными в этом разделе.

Кодировка сериализации

Если целевой тип данных — VARBINARY, результат сериализуется в UTF-16 с отметкой порядка байтов UTF-16 в начале, но без XML-декларации. Если целевой тип слишком мал, возникает ошибка.

Например:

select CAST(CAST(N'<Δ/>' as XML) as VARBINARY(MAX))

Результат:

0xFFFE3C0094032F003E00

Если целевой тип данных — NVARCHAR или NCHAR, результат сериализуется в UTF-16 без отметки порядка байтов UTF-16 в начале и без XML-декларации. Если целевой тип слишком мал, возникает ошибка.

Например:

select CAST(CAST(N'<Δ/>' as XML) as NVARCHAR(MAX))

Результат:

<Δ/>

Если целевой тип данных — VARCHAR или NCHAR, результат сериализуется в кодировке, соответствующей кодовой странице параметров сортировки базы данных без отметки порядка байтов и XML-декларации. Если целевой тип слишком мал или значение не может быть отображено на целевую кодовую страницу параметров сортировки, возникнет ошибка.

Например:

select CAST(CAST(N'<Δ/>' as XML) as VARCHAR(MAX))

Этот запрос может выдать ошибку, если в кодовой странице текущих параметров сортировки символ Юникода «Δ» не может быть представлен либо может быть представлен в конкретной кодировке.

При возврате XML-результатов клиенту данные будут отправлены в кодировке UTF-16. Поставщик с клиентской стороны, в свою очередь, представит данные в соответствии с правилами своего API.

Сериализация XML-структур

Содержимое типа данных xml сериализуется обычным образом. То есть узлы элементов сопоставляются разметке элементов, а текстовые узлы сопоставляются текстовому содержимому. При этом условия, в соответствии с которыми символы преобразуются в сущности, и способы сериализации типизированных атомарных значений описаны в последующих разделах.

Преобразование XML-символов в сущности при сериализации

Для каждой сериализованной XML-структуры должна быть возможность повторного синтаксического анализа. Поэтому некоторые символы сериализуются в виде сущностей, что позволяет избежать их искажения на стадии нормализации синтаксического анализатора XML. Тем не менее чтобы документ стал корректным и мог быть произведен его синтаксический анализ, некоторые символы должны быть преобразованы в сущности. Ниже приведены правила преобразования в сущности, применяемые в процессе сериализации.

  • Символы &, < и > всегда преобразуются в сущности &amp; &lt; и &gt; соответственно, если они встречаются внутри значения атрибута или содержимого элемента.

  • Поскольку значения атрибутов в SQL Server заключаются в кавычки (U+0022), знак кавычки в значениях атрибутов преобразуется в сущность &quot;.

  • Суррогатная пара преобразуется в цифровую ссылку (только при приведении на сервере). Например, суррогатная пара U+D800 U+DF00 преобразуется в ссылку на символ &#x00010300;.

  • Чтобы при синтаксическом анализе защитить от нормализации символы табуляции (TAB, U+0009) и перевода строки (LF, U+000A), они в значениях атрибутов преобразуются в свои числовые сущности: &#x9; и &#xA; соответственно.

  • Для предотвращения нормализации при синтаксическом анализе символа возврата каретки (CR, U+000D) он и в значениях атрибутов, и в содержимом элементов преобразуется в числовую ссылку &#xD;.

  • Чтобы защитить текстовые узлы, не содержащие ничего кроме пробелов, один из них, обычно последний, преобразуется к сущности по числовой ссылке. Таким образом, повторный синтаксический анализ сохраняет текстовый узел с пробелами, независимо от установки параметров обработки пробелов во время синтаксического разбора.

Например:

declare @u NVARCHAR(50)
set @u = N'<a a="&#xD;&#x9;'+NCHAR(0xD800)+NCHAR(0xDF00)+N'>">   '+NCHAR(0xA)+N'</a>'
select CAST(CONVERT(XML,@u,1) as NVARCHAR(50))

Результат:

<a a="&#xD;&#x9;&#x00010300;&gt;">   &#xA;</a>

Если применять правило защиты последнего пробела не нужно, при приведении из типа xml к строковому или двоичному типу данных можно явно указать CONVERT с параметром 1. Например, избежать преобразования сущностей можно следующим образом:

select CONVERT(NVARCHAR(50), CONVERT(XML, '<a>   </a>', 1), 1)

Обратите внимание, что результатом метода query() (тип данных xml) будет экземпляр типа данных xml. Поэтому любой результат метода query(), который приводится к строковому или двоичному типу, преобразуется в сущности в соответствии с описанными выше правилами. Если нужно получить строковое значение без преобразования в сущности, пользуйтесь методом value() (тип данных xml). Ниже приведен пример использования метода query():

declare @x xml
set @x = N'<a>This example contains an entitized char: &lt;.</a>'
select @x.query('/a/text()')

Результат:

This example contains an entitized char: &lt;.

А это пример использования метода value():

select @x.value('(/a/text())[1]', 'nvarchar(100)')

Результат:

This example contains an entitized char: <.

Сериализация типизированных XML-данных

Экземпляр типизированных XML-данных содержит значения, типизированные согласно своему типу XML-схемы. Эти значения сериализуются в соответствии с типом XML-схемы в том же формате, какой получается в результате приведения к типу xs:string в XQuery. Дополнительные сведения см. в разделе Правила приведения типов в запросах XQuery.

Например, значение 1.34e1 типа xs:double сериализуется в значение 13.4, как показано в следующем примере:

declare @x xml
set @x =''
select CAST(@x.query('1.34e1') as nvarchar(50))

Возвращается строковое значение 13.4.