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

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

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

В чем ошибка ручного формирования XML-файла

Рассмотрим, почему ручная запись реквизитов через ЗаписьXML.ЗаписатьАтрибут() не работает для переноса данных:

  1. Нарушение структуры объекта: при записи плоского списка тегов теряется привязка реквизитов к конкретным строкам справочника и его табличным частям.
  2. Потеря типов данных: стандартный парсер считывает все атрибуты XML как строки. При обратном чтении строковое значение "55" или "2023-01-01" требует сложного ручного приведения к типу платформы.
  3. Проблемы со ссылочными данными: ссылки на другие элементы справочников или перечислений невозможно перенести простой записью их строкового представления.

Платформа 1С:Предприятие 8 предоставляет встроенный инструмент — СериализаторXDTO, который автоматически сохраняет всю структуру объекта (шапку, типы данных, табличные части, ссылки) в XML и восстанавливает её без ручного разбора каждого тега.

Решение: универсальная выгрузка и загрузка через СериализаторXDTO

Разберем по шагам базовый механизм переноса любого справочника целиком.

Посмотрим на пример процедуры выгрузки данных конкретного справочника в XML-строку и последующего сохранения:


Процедура ВыгрузитьСправочник(ИмяСправочника, ПутьКФайлу)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Спр.Ссылка КАК Ссылка
        |ИЗ
        |   Справочник." + ИмяСправочника + " КАК Спр";
    
    Выборка = Запрос.Выполнить().Выбрать();
    
    ТаблицаДанных = Новый ТаблицаЗначений;
    ТаблицаДанных.Колонки.Добавить("ДанныеXML");
    
    Пока Выборка.Следующий() Цикл
        ОбъектСправочника = Выборка.Ссылка.ПолучитьОбъект();
        
        // Сериализуем объект целиком в XML
        ЗаписьXML = Новый ЗаписьXML;
        ЗаписьXML.УстановитьСтроку();
        СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ОбъектСправочника);
        СтрокаXML = ЗаписьXML.Закрыть();
        
        НоваяСтрока = ТаблицаДанных.Добавить();
        НоваяСтрока.ДанныеXML = СтрокаXML;
    КонецЦикла;
    
    ЗначениеВФайл(ПутьКФайлу, ТаблицаДанных);
    Сообщить("Выгрузка справочника " + ИмяСправочника + " успешно завершена.");
    
КонецПроцедуры

Теперь разберем процедуру обратной загрузки данных из созданного файла:


Процедура ЗагрузитьСправочник(ПутьКФайлу)
    
    ТаблицаДанных = ЗначениеИзФайла(ПутьКФайлу);
    
    Если ТаблицаДанных = Неопределено Тогда
        Сообщить("Не удалось прочитать файл данных!");
        Возврат;
    КонецЕсли;
    
    Для Каждого Стр Из ТаблицаДанных Цикл
        
        ЧтениеXML = Новый ЧтениеXML;
        ЧтениеXML.УстановитьСтроку(Стр.ДанныеXML);
        
        // Десериализуем объект из XML
        Объект = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
        ЧтениеXML.Закрыть();
        
        // Включаем режим загрузки для отключения прикладных проверок
        Объект.ОбменДанными.Загрузка = Истина;
        
        Попытка
            Объект.Записать();
            Сообщить("Записан объект: " + Объект);
        Исключение
            Сообщить("Ошибка при записи объекта: " + ОписаниеОшибки());
        КонецПопытки;
        
    КонецЦикла;
    
    Сообщить("Загрузка успешно завершена.");
    
КонецПроцедуры

Пакетная выгрузка всех справочников конфигурации

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


Процедура ВыгрузитьВсеСправочники(КаталогВыгрузки)
    
    Для Каждого МД_Справочник Из Метаданные.Справочники Цикл
        
        ИмяСпр = МД_Справочник.Имя;
        
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |   Спр.Ссылка КАК Ссылка
            |ИЗ
            |   Справочник." + ИмяСпр + " КАК Спр";
        
        Результат = Запрос.Выполнить();
        
        Если Результат.Пустой() Тогда
            Продолжить;
        КонецЕсли;
        
        Выборка = Результат.Выбрать();
        ТаблицаДанных = Новый ТаблицаЗначений;
        ТаблицаДанных.Колонки.Добавить("ДанныеXML");
        
        Пока Выборка.Следующий() Цикл
            ОбъектСпр = Выборка.Ссылка.ПолучитьОбъект();
            
            ЗаписьXML = Новый ЗаписьXML;
            ЗаписьXML.УстановитьСтроку();
            СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ОбъектСпр);
            
            НоваяСтр = ТаблицаДанных.Добавить();
            НоваяСтр.ДанныеXML = ЗаписьXML.Закрыть();
        КонецЦикла;
        
        ПолныйПуть = КаталогВыгрузки + "\" + ИмяСпр + ".dat";
        ЗначениеВФайл(ПолныйПуть, ТаблицаДанных);
        
    КонецЦикла;
    
КонецПроцедуры

Важные правила и ограничения при работе с СериализаторXDTO

  1. Идентичность метаданных: метод СериализаторXDTO использует схему текущей конфигурации (http://v8.1c.ru/8.1/data/enterprise/current-config). База-источник и база-приемник должны иметь строго одинаковую структуру реквизитов переносимых справочников. Если в приемнике удален или переименован реквизит, возникнет ошибка Ошибка преобразования данных XDTO.
  2. Флаг ОбменДанными.Загрузка: установка свойства Объект.ОбменДанными.Загрузка = Истина перед вызовом метода Записать() обязательна. Это отключает выполнение обработчиков событий ПередЗаписью и ПриЗаписи, позволяя загружать объекты «как есть» без дополнительных проверок бизнес-логики.
  3. Ссылочная целостность: если элемент ссылается на другой объект, которого еще нет в базе-приемнике, сериализатор восстановит ссылку по её уникальному идентификатору (GUID). До момента переноса зависимого объекта ссылка будет отображаться как <Объект не найден>, а после его загрузки автоматически станет корректной.
← На главную