Сериализация 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. Тем не менее чтобы документ стал корректным и мог быть произведен его синтаксический анализ, некоторые символы должны быть преобразованы в сущности. Ниже приведены правила преобразования в сущности, применяемые в процессе сериализации.
Символы &, < и > всегда преобразуются в сущности & < и > соответственно, если они встречаются внутри значения атрибута или содержимого элемента.
Поскольку значения атрибутов в SQL Server заключаются в кавычки (U+0022), знак кавычки в значениях атрибутов преобразуется в сущность ".
Суррогатная пара преобразуется в цифровую ссылку (только при приведении на сервере). Например, суррогатная пара U+D800 U+DF00 преобразуется в ссылку на символ 𐌀.
Чтобы при синтаксическом анализе защитить от нормализации символы табуляции (TAB, U+0009) и перевода строки (LF, U+000A), они в значениях атрибутов преобразуются в свои числовые сущности: 	 и 
 соответственно.
Для предотвращения нормализации при синтаксическом анализе символа возврата каретки (CR, U+000D) он и в значениях атрибутов, и в содержимом элементов преобразуется в числовую ссылку 
.
Чтобы защитить текстовые узлы, не содержащие ничего кроме пробелов, один из них, обычно последний, преобразуется к сущности по числовой ссылке. Таким образом, повторный синтаксический анализ сохраняет текстовый узел с пробелами, независимо от установки параметров обработки пробелов во время синтаксического разбора.
Например:
declare @u NVARCHAR(50)
set @u = N'<a a="
	'+NCHAR(0xD800)+NCHAR(0xDF00)+N'>"> '+NCHAR(0xA)+N'</a>'
select CAST(CONVERT(XML,@u,1) as NVARCHAR(50))
Результат:
<a a="
	𐌀>"> 
</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: <.</a>'
select @x.query('/a/text()')
Результат:
This example contains an entitized char: <.
А это пример использования метода 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.
См. также