При работе с обменом данными, особенно через XML, мы часто сталкиваемся с ошибкой вида "Текст XML содержит недопустимый символ в позиции...". Эта проблема может поставить в тупик, ведь иногда кажется, что мы передаем "чистые" данные. Давайте вместе разберемся, почему возникает такая ошибка и какие эффективные методы ее решения существуют в 1С и за ее пределами.
Выясним причину: эта ошибка возникает, когда в формируемом XML-документе присутствуют символы, которые не соответствуют строгой спецификации XML. Это чаще всего происходит с управляющими символами (Control Characters) из таблицы ASCII, которые не предназначены для отображения и имеют специальное значение в других контекстах (например, разделители). В XML 1.0 разрешены только символы табуляции ( ), перевода строки (
) и возврата каретки (
). Все остальные управляющие символы в диапазонах от U+0000 до U+0008, U+000B до U+000C, U+000E до U+001F считаются недопустимыми.
Одним из таких частых "виновников" является символ char(29) (Group Separator, GS, U+001D), который был упомянут в обсуждении. Он часто используется в штрихкодах GS1 для разделения элементов данных, но при попадании напрямую в XML вызывает ошибку. Помимо управляющих символов, существуют также зарезервированные символы (<, >, &, ', "), которые имеют специальное значение в синтаксисе XML и требуют экранирования.
Давайте рассмотрим подробнее несколько подходов к решению этой проблемы, которые мы можем применить в наших решениях на базе 1С.
Один из наиболее прямых способов борьбы с недопустимыми символами — это их экранирование. Экранирование означает замену проблемного символа на его эквивалентное представление, которое XML-парсер сможет корректно обработать. Это похоже на то, как база данных MS SQL экранирует char(29) в виде "".
Разберем по шагам:
nnnn; (десятичный код) или hhhh; (шестнадцатеричный код). Например, для char(29) это будет . Для зарезервированных символов XML используются предопределенные сущности:
< для <> для >& для &' для ' (в атрибутах)" для " (в атрибутах)В 1С мы можем использовать функцию СтрЗаменить() для замены конкретных символов. Например, если мы знаем, что проблема в Символ(29):
ПередаваемаяСтрока = СтрЗаменить(ИсходнаяСтрока, Символ(29), "");
Для более комплексной очистки данных в 1С существуют функции в "Библиотеке стандартных подсистем" (БСП), такие как ЗаменитьНедопустимыеСимволыXML и УдалитьНедопустимыеСимволыXML. Эти функции могут помочь автоматически найти и обработать проблемные символы в строке перед ее записью в XML.
Этот подход является очень мощным и универсальным решением, особенно когда данные содержат много "проблемных" символов или являются бинарными по своей сути. Идея заключается в том, чтобы закодировать всю строку, содержащую недопустимые символы, в формат Base64 перед ее включением в XML. На принимающей стороне эти данные затем декодируются обратно.
Проанализируем ситуацию: строка Base64 состоит исключительно из допустимых символов ASCII (буквы латинского алфавита, цифры и несколько специальных символов), что гарантирует ее беспроблемное включение в любой XML-документ. XML-парсер не столкнется с недопустимыми символами, потому что все содержимое будет восприниматься как обычный текст.
Посмотрим на пример реализации в 1С:
Для кодирования нам понадобятся функции ПолучитьДвоичныеДанныеИзСтроки() и Base64Строка(). Первая преобразует строку в двоичные данные, а вторая кодирует эти двоичные данные в строку Base64.
// Функция для кодирования строки в Base64
Функция ПреобразоватьКод_GS1(Знач СтрШК) Экспорт
// Сначала получаем двоичные данные из исходной строки
ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки(СтрШК);
// Затем кодируем двоичные данные в строку Base64
Возврат Base64Строка(ДвоичныеДанные);
КонецФункции // ПреобразоватьКод_GS1()
На принимающей стороне для восстановления исходной строки мы используем обратные функции: Base64Значение() для декодирования строки Base64 в двоичные данные и ПолучитьСтрокуИзДвоичныхДанных() для преобразования двоичных данных обратно в строку.
// Функция для декодирования строки Base64 обратно в исходную строку
Функция ВосстановитьКод_GS1(Знач СтрШК_Base64) Экспорт
// Декодируем строку Base64 в двоичные данные
ДвоичныеДанные = Base64Значение(СтрШК_Base64);
// Преобразуем двоичные данные обратно в строку
Возврат ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанные);
КонецФункции // ВосстановитьКод_GS1()
Таким образом, перед передачей данных с клиента на сервер или при формировании XML-файла мы вызываем ПреобразоватьКод_GS1(), а после получения данных и их извлечения из XML — ВосстановитьКод_GS1().
Секции CDATA (Character Data) предоставляют еще один способ включения текста, который XML-парсер не должен обрабатывать как разметку XML. Весь текст внутри секции воспринимается как обычные символьные данные, и в нем не нужно экранировать зарезервированные символы (например, <, >, &).
Рассмотрим подробнее: это особенно полезно, когда ваш текст содержит много специальных символов или даже фрагменты, которые выглядят как XML-разметка, но не должны интерпретироваться как таковые. Например, если вы передаете фрагмент HTML или XML как данные внутри другого XML-документа.
Пример использования:
<Документ>
<Описание>
, &,
а также управляющие символы, которые будут проигнорированы парсером.
Например, Символ(29) здесь не вызовет ошибку,
но и не будет интерпретирован как разметка.
]]>
Описание>
Документ>
Важный момент: хотя секции CDATA избавляют от необходимости экранировать зарезервированные символы, они не решают проблему с управляющими символами (такими как char(29)) в XML 1.0. Большинство XML-парсеров все равно выдадут ошибку, если внутри секции CDATA обнаружится недопустимый управляющий символ. Поэтому для управляющих символов лучше использовать экранирование (HHHH;) или кодирование в Base64.
В заключение, давайте обобщим, какие общие подходы и инструменты помогут нам избежать подобных проблем в будущем:
ЗаписьXML и ЧтениеXML, которые корректно обрабатывают многие аспекты формирования и парсинга XML.ЗаменитьНедопустимыеСимволыXML и УдалитьНедопустимыеСимволыXML, которые могут быть полезны для предварительной очистки строк, особенно если данные поступают из внешних источников (например, скопированы из интернета или из текстовых файлов).Применяя эти методы, мы сможем эффективно бороться с ошибками "Текст XML содержит недопустимый символ в позиции..." и обеспечивать надежный обмен данными в наших решениях на платформе 1С.
← К списку