.NET DataSet.GetXml() — какая кодировка по умолчанию?

Существующее приложение передает XML в sproc в SQLServer 2000, тип данных входного параметра — TEXT; XML получен из Dataset.GetXML(). Но я заметил, что он не указывает кодировку.

Поэтому, когда пользователь вводит в набор данных неподходящий символ, в частности, ASCII 146 (который выглядит как апостроф) вместо ASCII 39 (одинарная кавычка), sproc завершается ошибкой.

Один из подходов состоит в том, чтобы добавить к результату GetXML префикс

<?xml version="1.0" encoding="ISO-8859-1"?>

В этом случае это работает, но что было бы более правильным, чтобы гарантировать, что sproc не сработает (если появятся другие непредвиденные символы)?

PS. Я подозреваю, что пользователь вводит текст в MS-Word или аналогичный редактор, а затем копирует и вставляет в поля ввода приложения; Я, вероятно, хотел бы позволить пользователю продолжать работать таким образом, просто нужно предотвратить сбои.

РЕДАКТИРОВАТЬ: я ищу ответы, которые подтверждают или опровергают несколько аспектов, например:
- согласно заголовку, какова кодировка по умолчанию, если она не указана в XML?
- Является ли кодировка ISO-8859- 1 правильнее использовать?
 — есть ли лучшая кодировка, которая включала бы больше символов в англоязычном мире и, следовательно, с меньшей вероятностью вызывала бы ошибку в sproc?
 – вы бы отфильтровали по уровень пользовательского интерфейса приложения для стандартного ASCII (только от 0 до 127) и не разрешать расширенный ASCII?
 — любые другие относящиеся к делу детали.


person joedotnot    schedule 09.12.2009    source источник


Ответы (2)


DataSet.GetXml() возвращает string. В .NET строки внутренне кодируются с использованием UTF-16, но здесь это не очень важно.

Причина, по которой в строке нет объявления <?xml encoding=...>, заключается в том, что это объявление полезно или необходимо только для анализа XML в потоке байтов. Строка .NET — это не поток байтов, это просто текст с четко определенной семантикой кодовой точки (то есть Unicode), поэтому она там не нужна.

Если декларация кодировки XML отсутствует, то парсер XML принимает кодировку UTF-8 при отсутствии спецификации. Однако в вашем случае это также совершенно не имеет значения, поскольку проблема не в анализаторе XML (XML не анализируется SQL Server, когда он хранится в столбце TEXT). Проблема в том, что ваш XML содержит некоторые символы Unicode, а TEXT — это тип SQL, отличный от Unicode.

Вы можете закодировать string в любую кодировку, используя метод Encoding.GetBytes().

person Pavel Minaev    schedule 09.12.2009
comment
Неверное предположение, столбец не TEXT, для приема строки XML используется только параметр типа TEXT; TEXT используется, потому что varchar(8000) имеет ограничение на длину; Проблема в с парсером на sqlserver. Сервер: сообщение 6603, уровень 16, состояние 1, процедура sp_xml_preparedocument, строка 40, ошибка синтаксического анализа XML: в текстовом содержимом обнаружен недопустимый символ. Как я уже сказал, когда я объявляю строку XML как ISO-8859-1, в sproc не возникает ошибок, поэтому синтаксический анализатор обрабатывает ASCII 146 как допустимый. - person joedotnot; 10.12.2009
comment
Проблема все еще TEXT, на самом деле. В частности, когда вы передаете Unicode string в свою sproc, его необходимо преобразовать в кодировку, отличную от Unicode, чтобы она соответствовала TEXT; результат, конечно, не закодирован с использованием UTF, и определить, какую кодировку он собирается использовать для преобразования, непросто. Если у вас есть контроль над sproc, просто замените TEXT на NTEXT и не беспокойтесь о кодировках. - person Pavel Minaev; 10.12.2009
comment
Я пришел к тому же выводу, чтобы использовать NTEXT непосредственно перед чтением вашего последнего комментария, тогда мне не нужно будет объявлять ‹br/› ?xml version=1.0 encoding=ISO-8859-1?‹br/›, чтобы он работал (или не нужно будет возиться с кодировками, как вы сказали). Не могли бы вы уточнить несколько вещей: ‹br/› вы говорите, что если я использую NTEXT, строка xml, которую я передаю, будет интерпретироваться синтаксическим анализатором xml как UTF-16? ‹br/›почему сохранение TEXT и объявление строки xml как ISO-8859-1 работает? - person joedotnot; 10.12.2009
comment
По-видимому, когда поставщик ADO.NET MSSQL выполняет преобразование из строки .NET Unicode в TEXT, он использует в качестве кодировки ISO-8859-1 (я подозреваю, что он либо использует текущую системную локаль, либо кодовую страницу, указанную в вашей базе данных). Следовательно, строка, как только она поступает в SQL, кодируется с использованием ISO-8859-1 (поскольку она может представлять символы исходной строки), а затем синтаксический анализатор XML в MSSQL обрабатывает ее как последовательность байтов и предполагает UTF-8 ( или выбирает ваше явное объявление кодировки). Я ожидаю, что с NTEXT он будет обрабатывать его как текст Unicode, а не как необработанные байты. - person Pavel Minaev; 10.12.2009

Я считаю, что ваш подход должен заключаться в использовании WriteXml вместо GetXml. Это должно позволить вам указать кодировку.

Однако обратите внимание, что вам придется писать через промежуточный поток — если вы выводите напрямую в строку, она всегда будет использовать UTF-16. Поскольку вы используете столбец TEXT, это позволит использовать символы, недопустимые для TEXT.

person John Saunders    schedule 09.12.2009
comment
что не так с тем, чтобы сделать это в соответствии с моим примером, конкатенировать [кодировку xml] + DataSet.GetXml()? - person joedotnot; 10.12.2009
comment
1) Не используйте конкатенацию строк для управления XML. Существуют различия в правилах между XML и строками. 2) Ваш метод только объявляет, что такое кодировка - он вообще не меняет кодировку. - person John Saunders; 10.12.2009