Рассмотрим распространенную и крайне неприятную ситуацию: при попытке открыть список документов определенного вида платформа 1С завершает операцию аварийной ошибкой: «Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа», а в подробном описании указывается «Ошибка преобразования данных XDTO» и «Текст XML содержит недопустимый символ». Проблема может возникать даже на самых простых и пустых формах списка без единой строчки программного кода.
Проанализируем техническую сторону сбоя. В соответствии со стандартом XML 1.0 в текстовых полях категорически запрещено использование непечатаемых управляющих символов ASCII (символы с кодами от 0 до 8, от 11 до 12 и от 14 до 31).
Если подобный управляющий байт попадает в любой строковый реквизит объекта (номер документа, наименование, комментарий или артикул), платформа 1С теряет возможность корректно сформировать XML-пакет (XDTO) для передачи данных от сервера к тонкому клиенту.
Чаще всего недопустимые символы попадают в базу данных 1С следующими путями:
Сбой сериализации XDTO происходит внутри ядра платформы 1С (на уровне C++) в момент формирования сетевого пакета. Динамический список формы пытается сгенерировать порцию данных для отображения пользователю. Если среди запрашиваемых записей оказывается хотя бы один документ с битым символом, серверная часть платформы не может собрать XML-структуру, и генерация формы аварийно завершается еще до выполнения клиентского кода.
Стандартные процедуры проверки конфигуратором (тестирование и исправление, очистка ссылок) также не всегда находят такие повреждения, так как с точки зрения структуры базы данные корректны, а сбой происходит лишь на этапе XML-сериализации.
Поскольку открыть форму списка в интерфейсе невозможно, найдем битый объект программным путем. Воспользуемся встроенным в платформу методом НайтиНедопустимыеСимволыXML().
Создадим внешнюю обработку и выполним выборку по интересующему документу:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Док.Ссылка КАК Ссылка,
| Док.Номер КАК Номер,
| Док.Комментарий КАК Комментарий
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Док";
Результат = Запрос.Выполнить().Выгрузить();
Для Каждого Стр Из Результат Цикл
// Проверяем номер документа
ПозицияВНомере = НайтиНедопустимыеСимволыXML(Стр.Номер);
Если ПозицияВНомере > 0 Тогда
Сообщить("Найден битый символ в НОМЕРЕ документа: " + Строка(Стр.Ссылка) + " (Позиция: " + Строка(ПозицияВНомере) + ")");
КонецЕсли;
// Проверяем комментарий
ПозицияВКомм = НайтиНедопустимыеСимволыXML(Стр.Комментарий);
Если ПозицияВКомм > 0 Тогда
Сообщить("Найден битый символ в КОММЕНТАРИИ документа: " + Строка(Стр.Ссылка) + " (Позиция: " + Строка(ПозицияВКомм) + ")");
КонецЕсли;
КонецЦикла;
Удалять документ целиком не рекомендуется, так как это приведет к расхождению учета и нарушению последовательности движений. Оптимальный вариант — очистить поврежденную строку от недопустимых символов и перезаписать объект.
В конфигурациях на базе Библиотеки Стандартных Подсистем (БСП) для этого предусмотрена функция ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыXML(). Разберем программный код для автоматической исправления обнаруженного документа:
// Получаем объект найденного документа
ДокОбъект = СсылкаНаНайденныйДокумент.ПолучитьОбъект();
// Очищаем номер от управляющих символов
ОчищенныйНомер = ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыXML(ДокОбъект.Номер);
ДокОбъект.Номер = ОчищенныйНомер;
// Отключаем необходимые проверки обмена при записи
ДокОбъект.ОбменДанными.Загрузка = Истина;
Попытка
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
Сообщить("Документ " + Строка(СсылкаНаНайденныйДокумент) + " успешно исправлен!");
Исключение
Сообщить("Не удалось записать документ: " + ОписаниеОшибки());
КонецПопытки;
Чтобы избежать повторного возникновения ошибки XDTO-сериализации в будущем, рекомендуется придерживаться следующих правил:
ЗаменитьНедопустимыеСимволыXML().