Как устранить ошибку сохранения документа при наличии символа STX и других недопустимых символов XML в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешним оборудованием (лабораторными анализаторами, кассовой техникой, сканерами или промышленными контроллерами) разработчики нередко сталкиваются с ситуацией, когда данные из файла или COM-порта успешно считываются в строковую переменную, отображаются в отладчике, но при попытке записать объект в базу возникает исключение: «Недопустимый символ XML».

Проанализируем природу этой ошибки, выясним причину ее возникновения и подробно разберем все способы решения проблемы.

Почему возникает ошибка при наличии символа STX (код 2)

Символ STX (Start of Text, шестнадцатеричный код 0x02, десятичный 2) является стандартным служебным символом кадрирования во многих протоколах передачи данных (например, ASTM E1381/E1394, HL7). Если парсер оборудования передает в прикладные реквизиты сырой поток данных без предварительной очистки служебных заголовков, управляющий символ попадает в строку 1С.

В оперативной памяти платформы 1С строки хранятся в кодировке Unicode, поэтому любые присвоения и операции склейки строк выполняются без сбоев. Однако при вызове метода Записать() платформа выполняет внутреннюю сериализацию данных (в частности, при передаче между клиентом и сервером, формировании XML-пакетов регистрации изменений или записи в структуры СУБД).

Согласно стандарту XML 1.0, управляющие символы диапазона кодов от 0 до 31 (за исключением символов с кодами 9 — табуляция, 10 — перевод строки, 13 — возврат каретки) строго запрещены к использованию даже в виде сущностей (). При попытке сериализовать строку с такими символами платформа 1С прерывает операцию с критической ошибкой.

Способ 1. Использование встроенной функции «НайтиНедопустимыеСимволыXML»

Платформа 1С предоставляет встроенную функцию глобального контекста НайтиНедопустимыеСимволыXML(). С ее помощью можно найти позицию первого некорректного символа и обработать строку — удалить невалидные знаки либо заменить их на читаемое представление.

Рассмотрим пример функции, которая заменяет все невалидные символы на их экранированные строковые коды:


Функция ЗаменитьНедопустимыеСимволы(Знач ИсходныйТекст) Экспорт
    Позиция = 1;
    Пока Истина Цикл
        Позиция = НайтиНедопустимыеСимволыXML(ИсходныйТекст, Позиция);
        Если Позиция = 0 Тогда
            Прервать;
        КонецЕсли;
        
        Код = КодСимвола(Сред(ИсходныйТекст, Позиция, 1));
        СпецСимвол = "[" + Формат(Код, "ЧГ=0") + "]";
        
        ИсходныйТекст = Сред(ИсходныйТекст, 1, Позиция - 1) + СпецСимвол + Сред(ИсходныйТекст, Позиция + 1);
        Позиция = Позиция + СтрДлина(СпецСимвол);
    КонецЦикла;
    
    Возврат ИсходныйТекст;
КонецФункции

Разберем, как работает этот алгоритм:

  1. Функция НайтиНедопустимыеСимволыXML ищет запрещенный символ, начиная с указанной позиции. Если такой символ не найден, возвращается 0.
  2. Если символ обнаружен, мы получаем его код через функцию КодСимвола().
  3. Заменяем байт на безопасную текстовую конструкцию (например, [2]) и смещаем указатель поиска дальше по строке.

Способ 2. Очистка с помощью функций БСП

Если конфигурация разработана на базе Библиотеки стандартных подсистем (БСП), писать собственный цикл обработки не требуется. В общем модуле СтроковыеФункцииКлиентСервер предусмотрен готовый оптимизированный метод.

Посмотрим на пример вызова:


ОчищенныйТекст = СтроковыеФункцииКлиентСервер.УдалитьНедопустимыеСимволыXML(СтрокаДанных);
СтрокаТЧ.Результаты = ОчищенныйТекст;

Этот метод за один проход удаляет все управляющие символы, нарушающие спецификацию XML, что гарантирует успешную запись объекта без потери полезных данных.

Способ 3. Фильтрация на этапе разбора протокола обмена

Наиболее архитектурно правильный подход — очищать управляющие символы непосредственно в модуле интеграции при чтении файла или сетевого потока. Если протокол обмена использует символы начала и конца кадра (STX — 0x02, ETX — 0x03, EOT — 0x04, ACK — 0x06), их необходимо отсекать регулярными выражениями или строковыми заменами до передачи в табличные части документов:


// Удаляем известные символы кадрирования
СимволSTX = Символ(2);
СимволETX = Символ(3);
СимволEOT = Символ(4);

ЧистаяСтрока = СтрЗаменить(СтрЗаменить(СтрЗаменить(СыраяСтрока, СимволSTX, ""), СимволETX, ""), СимволEOT, "");

Способ 4. Хранение сырых бинарных пакетов

Если для целей аудита или технической диагностики требуется сохранить точный «сырой» ответ анализатора вместе со всеми непечатными байтами, обычный строковый реквизит использовать нельзя. В таком случае применяют один из двух вариантов:

  1. Реквизит с типом «ХранилищеЗначения»: бинарные данные упаковываются в ДвоичныеДанные и помещаются в ХранилищеЗначения. Данный тип не подвергается строгой XML-валидации символов при записи.
  2. Кодирование в Base64: бинарная строка преобразуется в безопасный текстовый вид с помощью функций Base64Строка() и Base64Значение(). Строка в формате Base64 состоит исключительно из латинских букв, цифр и знаков +, /, =, что полностью исключает конфликты с XML-сериализацией.
← На главную