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

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

При реализации обмена данными через планы обмена разработчики часто сталкиваются с тем, что стандартный метод платформы ЗаписатьXML(ЗаписьXML, Данные) выгружает объект целиком. Для справочника Номенклатура это означает, что в XML-файл попадут десятки ненужных реквизитов, табличные части, а также служебные свойства. Это приводит к раздуванию размера файла обмена и замедлению процесса интеграции.

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

Почему стандартный метод выгружает все реквизиты?

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


ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель, ЗаписьСообщения.НомерСообщения);
Пока ВыборкаИзменений.Следующий() Цикл
    Данные = ВыборкаИзменений.Получить();
    // Записать данные в сообщение *** XML-сериализация.
    ЗаписатьXML(ЗаписьXML, Данные);
КонецЦикла;

Когда платформа выполняет функцию ЗаписатьXML, она обращается к метаданным переданного объекта (в данном случае СправочникОбъект.Номенклатура) и автоматически сериализует все его свойства. Чтобы изменить это поведение, нам необходимо вмешаться в процесс записи. Выясним, какими способами это можно сделать.

Решение 1. Программная ручная запись XML (Быстрый способ)

Если обмен разрабатывается без использования сложных правил конвертации и вам нужно быстро решить задачу непосредственно в коде выгрузки, мы можем переписать логику внутри цикла выборки изменений. Проанализируем, как перехватить выгрузку номенклатуры и записать её вручную, тег за тегом.

Заменим стандартный вызов ЗаписатьXML на ветвление по типу объекта:


Пока ВыборкаИзменений.Следующий() Цикл
    Данные = ВыборкаИзменений.Получить();
    
    // Проверяем, является ли объект справочником Номенклатура
    Если ТипЗнч(Данные) = Тип("СправочникОбъект.Номенклатура") Тогда
        
        // Открываем основной узел объекта номенклатуры
        ЗаписьXML.ЗаписатьНачалоЭлемента("CatalogObject.Номенклатура");
        
        // 1. Записываем ссылку (GUID) для однозначной идентификации в приемнике
        ЗаписьXML.ЗаписатьНачалоЭлемента("Ref");
        ЗаписьXML.ЗаписатьТекст(Строка(Данные.Ссылка.УникальныйИдентификатор()));
        ЗаписьXML.ЗаписатьКонецЭлемента();
        
        // 2. Записываем код товара
        ЗаписьXML.ЗаписатьНачалоЭлемента("Code");
        ЗаписьXML.ЗаписатьТекст(Данные.Код);
        ЗаписьXML.ЗаписатьКонецЭлемента();
        
        // 3. Записываем наименование (Description)
        ЗаписьXML.ЗаписатьНачалоЭлемента("Description");
        ЗаписьXML.ЗаписатьТекст(Данные.Наименование);
        ЗаписьXML.ЗаписатьКонецЭлемента();
        
        // 4. Записываем артикул
        ЗаписьXML.ЗаписатьНачалоЭлемента("Артикул");
        ЗаписьXML.ЗаписатьТекст(Данные.Артикул);
        ЗаписьXML.ЗаписатьКонецЭлемента();
        
        // Закрываем основной узел
        ЗаписьXML.ЗаписатьКонецЭлемента(); 
        
    Иначе
        // Все остальные объекты регистрируем стандартным образом
        ЗаписатьXML(ЗаписьXML, Данные);
    КонецЕсли;
КонецЦикла;

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

Недостатки: Жесткое кодирование структуры тегов. При изменении требований к формату придется переписывать код конфигурации.

Решение 2. Использование схемы XDTO (Архитектурно правильный способ)

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

Рассмотрим пошагово, как реализовать этот подход:

  1. В конфигураторе создаем новый XDTO-пакет (например, ОбменДанными).
  2. Внутри пакета создаем тип объекта НоменклатураСокращенная.
  3. Добавляем для этого типа свойства: Ref (тип string), Code (тип string), Description (тип string) и Article (тип string).

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


Пока ВыборкаИзменений.Следующий() Цикл
    Данные = ВыборкаИзменений.Получить();
    
    Если ТипЗнч(Данные) = Тип("СправочникОбъект.Номенклатура") Тогда
        
        // Получаем фабрику и тип из нашего пакета XDTO
        ТипXDTO = ФабрикаXDTO.Тип("http://www.yourcompany.ru/exchange", "НоменклатураСокращенная");
        
        // Создаем экземпляр объекта по схеме
        ОбъектXDTO = ФабрикаXDTO.Создать(ТипXDTO);
        
        // Заполняем свойства данными из справочника 1С
        ОбъектXDTO.Ref = Строка(Данные.Ссылка.УникальныйИдентификатор());
        ОбъектXDTO.Code = Данные.Код;
        ОбъектXDTO.Description = Данные.Наименование;
        ОбъектXDTO.Article = Данные.Артикул;
        
        // Выполняем запись объекта XDTO в XML
        ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ОбъектXDTO, "CatalogObject.Номенклатура");
        
    Иначе
        ЗаписатьXML(ЗаписьXML, Данные);
    КонецЕсли;
КонецЦикла;

Преимущества метода: Автоматический контроль типов данных со стороны платформы, строгое соответствие схеме, красивый и лаконичный код.

Решение 3. Использование правил конвертации данных (КД 2.1 или КД 3.0)

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

Разберем процесс настройки правил конвертации:

  1. Откроем конфигурацию Конвертация данных и загрузим структуру метаданных.
  2. Найдем правило конвертации объектов (ПКО) для справочника Номенклатура.
  3. Перейдем на вкладку Правила конвертации свойств (ПКС).
  4. Снимем флаги активности (отключим выгрузку) для всех реквизитов, кроме ключевых: Ссылка, Код, Наименование, Артикул.
  5. Сохраним новые правила обмена и загрузим их в узел обмена вашей информационной базы.

При использовании КД стандартный механизм выгрузки сам отсечет лишние свойства и запишет в XML только те поля, для которых установлены активные правила.

Важная деталь: Оптимизация регистрации изменений

Ограничение выгружаемых полей на этапе записи XML решает проблему размера итогового файла обмена. Однако остается скрытая проблема производительности: лишние транзакции регистрации изменений.

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

Для оптимизации этого процесса настроим выборочную авторегистрацию:

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

Процедура ПередЗаписьюНоменклатурыРегистрация(Источник, Отказ) Экспорт
    
    // Исключаем работу при загрузке данных
    Если Источник.ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;
    
    // Если это новый элемент - регистрируем его изменения в любом случае
    Если Источник.ЭтоНовый() Тогда
        ПланыОбмена.ЗарегистрироватьИзменения(ПараметрыСеанса.УзлыОбменаНоменклатуры, Источник);
        Возврат;
    КонецЕсли;
    
    // Для существующего элемента проверим изменение ключевых реквизитов
    СсылкаНаОбъект = Источник.Ссылка;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Номенклатура.Код КАК Код,
        |	Номенклатура.Наименование КАК Наименование,
        |	Номенклатура.Артикул КАК Артикул
        |ИЗ
        |	Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |	Номенклатура.Ссылка = &Ссылка";
        
    Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Если Выборка.Следующий() Тогда
        // Сравниваем старые значения из базы данных с новыми значениями объекта
        Если (Выборка.Код <> Источник.Код) 
            Или (Выборка.Наименование <> Источник.Наименование) 
            Или (Выборка.Артикул <> Источник.Артикул) Тогда
            
            // Если изменился хотя бы один из ключевых реквизитов - регистрируем изменения
            ПланыОбмена.ЗарегистрироватьИзменения(ПараметрыСеанса.УзлыОбменаНоменклатуры, Источник);
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Такой подход позволит сэкономить ресурсы сервера 1С на базах с интенсивным обновлением справочников, так как выгружаться будут только те товары, у которых действительно поменялись критически важные для обмена данные.

← На главную