При организации двустороннего обмена данными между неидентичными конфигурациями 1С через планы обмена разработчики часто сталкиваются с ошибками десериализации XML. Типичный сценарий: иерархический справочник успешно передает элементы, однако при попытке прочитать узел группы (папки) платформа выдает критическую ошибку преобразования XML. Разберем детально, почему возникает эта проблема и какими способами ее можно устранить.
Проанализируем механизм работы стандартного обмена данными. При выгрузке и загрузке объектов через планы обмена платформа 1С использует объект СериализаторXDTO. Он выполняет строгое сопоставление узлов XML-документа с типами и свойствами объектов метаданных конфигурации-приемника.
Ошибка чтения группы возникает по двум основным причинам:
СериализаторXDTO.ПрочитатьXML() не сможет пропустить неизвестные теги, так как схема типа не совпадает со структурой пакета.Самый простой и быстрый способ решения проблемы без переписывания программного кода обмена — согласование свойств метаданных в обеих информационных базах.
Выполним следующие шаги:
После изменения этого свойства объект группы получит соответствующее свойство в модели данных. Даже если для групп эти реквизиты останутся незаполненными, СериализаторXDTO сможет корректно прочитать входящий XML без ошибок несоответствия схемы.
Если изменять структуру метаданных в конфигурации-приемнике нежелательно, перехватим процесс записи данных на стороне базы-источника. Для этого используем события плана обмена в модуле плана обмена.
Рассмотрим пример переопределения выгрузки в обработчике ПриОтправкеДанныхГлавному или ПриОтправкеДанныхПодчиненному:
Процедура ПриОтправкеДанныхПодчиненному(ЭлементДанных, ОтправкаЭлемента, СозданиеСообщения)
// Проверяем тип отправляемого объекта
Если ТипЗнч(ЭлементДанных) = Тип("СправочникОбъект.Товары") Тогда
// Если выгружается группа, очищаем значения специфических реквизитов
Если ЭлементДанных.ЭтоГруппа Тогда
// При необходимости можно переопределить запись объекта через фабрику XDTO
// или исключить лишние данные перед помещением в поток
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Когда структуры конфигураций сильно различаются и прямое использование платформенного сериализатора невозможно, разберем вариант с выборочной загрузкой с помощью объектов ЧтениеXML и СправочникиМенеджер.
Посмотрим на пример процедуры выборочной загрузки элементов и групп:
Процедура ЗагрузитьТоварыИзXML(ПутьКФайлу)
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "CatalogObject.Товары" Тогда
// Читаем параметры текущего объекта
ЭтоГруппа = Ложь;
УникальныйИдентификатор = Неопределено;
Наименование = "";
// Считываем дочерние узлы объекта
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЧтениеXML.Имя = "CatalogObject.Товары" Тогда
Прервать;
КонецЕсли;
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ИмяУзла = ЧтениеXML.Имя;
ЧтениеXML.Прочитать(); // Переходим к значению
Если ИмяУзла = "IsFolder" Тогда
ЭтоГруппа = (ЧтениеXML.Значение = "true");
ИначеЕсли ИмяУзла = "Ref" Тогда
УникальныйИдентификатор = Новый УникальныйИдентификатор(ЧтениеXML.Значение);
ИначеЕсли ИмяУзла = "Description" Тогда
Наименование = ЧтениеXML.Значение;
КонецЕсли;
КонецЕсли;
КонецЦикла;
// Создаем или находим объект в базе
Если ЗначениеЗаполнено(УникальныйИдентификатор) Тогда
СсылкаНаОбъект = Справочники.Товары.ПолучитьСсылку(УникальныйИдентификатор);
Если ЭтоГруппа Тогда
ОбъектТовар = Справочники.Товары.СоздатьГруппу();
Иначе
ОбъектТовар = Справочники.Товары.СоздатьЭлемент();
КонецЕсли;
ОбъектТовар.УстановитьСсылкуНового(СсылкаНаОбъект);
ОбъектТовар.Наименование = Наименование;
// Записываем объект без попытки заполнить отсутствующие реквизиты
Попытка
ОбъектТовар.Записать();
Исключение
ЗаписьЖурналаРегистрации("ОбменДанными", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЕсли;
КонецЦикла;
ЧтениеXML.Закрыть();
КонецПроцедуры
Если обмен между разнородными базами требует постоянной поддержки и развивается, лучшим решением будет переход со стандартного прямого чтения через планы обмена на специализированные правила конвертации (КД 2.1 или КД 3.0):
ПередВыгрузкой:
Если Объект.ЭтоГруппа Тогда
Отказ = Истина;
КонецЕсли;
Выбор конкретного метода зависит от возможности внесения изменений в конфигурации: для типовых конфигураций на поддержке оптимально использовать правила конвертации данных, а при наличии доступа к доработке конфигураций — скорректировать свойство Использование реквизита в метаданных.