Как выгружать и загружать данные через XML между базами 1С с разной структурой метаданных?

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

При работе с механизмами обмена данными в системе 1С:Предприятие часто возникает классическая проблема: базы-участники обмена со временем начинают различаться. В одну базу добавили новый реквизит в документ или справочник, а в другой конфигурация осталась прежней. В такой ситуации стандартная выгрузка и загрузка через План обмена может выдавать ошибки, так как принимающая сторона "не знает", что делать с неизвестным ей тегом в XML-файле.

В этой статье мы подробно разберем, как адаптировать обмен данными под изменяющиеся структуры, рассмотрим программные способы игнорирования лишних данных и изучим архитектурные подходы, которые сделают вашу систему обмена более гибкой.

Метод 1: Использование низкоуровневого чтения XML с проверкой метаданных

Если вы используете самописную обработку или модифицируете существующий механизм обмена, самый надежный способ избежать ошибок — это отказаться от автоматического чтения объекта функцией ПрочитатьXML() в пользу ручного обхода узлов. Мы можем проанализировать каждый тег в файле перед тем, как пытаться записать его значение в объект базы данных.

Проанализируем пример кода, который позволяет загружать данные, пропуская те реквизиты, которых нет в текущей конфигурации:


// Предположим, мы читаем документ из XML
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлу);

Пока Чтение.Прочитать() Цикл
    Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
        ИмяРеквизита = Чтение.Имя;
        
        // Проверяем, существует ли такой реквизит в метаданных текущей базы
        МетаданныеОбъекта = Метаданные.Документы.РеализацияТоваровУслуг;
        Если МетаданныеОбъекта.Реквизиты.Найти(ИмяРеквизита) <> Неопределено Тогда
            // Если реквизит найден, читаем его значение
            Значение = СериализаторXDTO.ПрочитатьXML(Чтение);
            ОбъектОбмена[ИмяРеквизита] = Значение;
        Иначе
            // Если реквизита нет, просто пропускаем этот узел
            Чтение.Пропустить();
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Используя метод Метаданные.Найти() или поиск в коллекции Реквизиты, мы обеспечиваем защиту от "лишних" данных. Если в XML пришел тег "НовыйСверхВажныйРеквизит", которого нет в нашей базе, программа просто пропустит его и перейдет к следующему элементу, не вызывая исключения.

Метод 2: Фильтрация данных на стороне источника через «ПриОтправкеДанных»

Вместо того чтобы учить базу-приемник игнорировать новые поля, мы можем научить базу-источник не отправлять те данные, которые приемник не сможет переварить. Для этого в модуле Плана обмена существуют специальные предопределенные обработчики.

Рассмотрим использование события ПриОтправкеДанныхПодчиненному. Этот метод вызывается перед тем, как объект будет помещен в сообщение обмена. Здесь мы можем модифицировать передаваемые данные или даже полностью заменить объект.


Процедура ПриОтправкеДанныхПодчиненному(ЭлементДанных, ОтправкаЭлемента)
    
    // Если мы отправляем конкретный тип документа
    Если ТипЗнч(ЭлементДанных) = Тип("ДокументОбъект.РеализацияТоваровУслуг") Тогда
        
        // Если мы знаем, что у приемника версия базы ниже, 
        // мы можем очистить новый реквизит или обнулить его, 
        // чтобы он не вызывал конфликтов (в зависимости от логики сериализации)
        // Либо можно программно сформировать структуру без этого поля.
        
    КонецЕсли;
    
КонецПроцедуры

Этот подход хорош тем, что он экономит трафик и уменьшает размер XML-файла, так как лишняя информация вообще не попадает в файл обмена.

Метод 3: Переход на технологию XDTO

Современным стандартом обмена в 1С является использование XDTO (XML Data Transfer Objects). В отличие от жесткой привязки к метаданным, XDTO работает через описание схем данных. Это дает колоссальную гибкость:

  1. Абстракция от структуры базы: Вы можете описать в пакете XDTO только те поля, которые действительно нужны для обмена.
  2. СериализаторXDTO: Вместо ЗаписатьXML() мы используем СериализаторXDTO.ЗаписатьДанные(). При чтении через СериализаторXDTO.ПрочитатьДанные() система сопоставляет XML со схемой XDTO, а не напрямую с объектом 1С.
  3. Динамическое чтение: Если в XML файле присутствуют элементы, не описанные в схеме XDTO, их можно игнорировать на уровне парсера, что предотвращает ошибки загрузки.

Рассмотрим пример чтения через XDTO, который более устойчив к изменениям:


// Чтение данных с использованием типа XDTO
ТипОбъектаXDTO = ФабрикаXDTO.Тип("http://www.my-site.com/exchange", "ДокументПродажа");
ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(Чтение, ТипОбъектаXDTO);

// Теперь мы можем программно перенести данные из XDTO в объект 1С
// проверяя каждое свойство
Для каждого Свойство Из ОбъектXDTO.Тип().Свойства Цикл
    // Логика заполнения...
КонецЦикла;

Метод 4: Использование конфигурации «Конвертация данных» (КД 2.0 и 3.0)

Если различия между базами становятся существенными, ручное написание кода в обработках становится трудозатратным. В этом случае пора переходить к специализированным инструментам.

Конвертация данных 2.0: Это классический инструмент, где вы создаете "Правила обмена данными" (ПВД). В КД 2 вы можете четко указать, какие реквизиты источника соответствуют реквизитам приемника. Если в источнике есть реквизит, а в приемнике нет — вы просто не создаете правило для этого поля, и проблема решается сама собой.

Конвертация данных 3.0: Работает по принципу "универсального формата" (EnterpriseData). База-источник выгружает данные в промежуточный формат, а база-приемник читает только те данные из этого формата, которые она понимает. Это самый продвинутый способ интеграции, так как он позволяет обновлять конфигурации независимо друг от друга.

Метод 5: Использование расширений для "выравнивания" структур

Иногда самым простым решением будет не усложнение кода обмена, а приведение структур баз к единому виду. Если в одной базе добавлен важный реквизит, который скоро появится и в других базах, вы можете добавить этот реквизит в "отстающие" базы с помощью Расширения конфигурации.

Преимущества этого метода:

Подведем итоги

Для решения проблемы обмена между разными версиями баз мы рекомендуем следующий алгоритм действий:

  1. Если различия разовые и минимальные — используйте ручной обход тегов через ЧтениеXML и проверку через Метаданные.Найти().
  2. Если вы планируете долгосрочное развитие обмена — внедряйте XDTO или Конвертацию данных 3.0.
  3. Если базы типовые, но одна из них обновлена раньше — используйте Расширения для временного добавления недостающих полей.
  4. Всегда оборачивайте критические участки загрузки в блок Попытка...Исключение, чтобы один некорректный объект не останавливал весь процесс обмена данными.

Выяснив причину ошибки (несоответствие структуры XML и метаданных), мы можем гибко настроить обмен, сделав его устойчивым к любым изменениям в конфигурациях.

← На главную