Как выгрузить справочник в произвольную структуру XML и почему для этого не подходит XDTO?

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

При интеграции систем часто возникает задача выгрузить справочники 1С в XML с нестандартной иерархией тегов. Например, требуется обернуть реквизиты объекта в специальный тег ЗначенияРеквизитов, сделать именами тегов имена реквизитов, а для ссылочных полей рекурсивно выгружать идентификаторы, коды и вложенные реквизиты. При этом состав выгружаемых полей может динамически определяться пользователем в пользовательском интерфейсе.

Разберем, почему встроенный механизм XDTO не предназначен для решения подобных задач и какие инструменты платформы 1С:Предприятие позволяют реализовать такую выгрузку максимально быстро и эффективно.

Ограничения механизма XDTO при динамической структуре данных

Проанализируем особенности работы XDTO в платформе 1С:

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

Механизм XDTO ориентирован на строгие контракты обмена (WSDL, SOAP, фиксированные схемы XSD). Для выгрузки данных с произвольной структурой и динамическим составом полей целесообразно использовать потоковую запись через объект ЗаписьXML.

Оптимальное решение: Потоковая генерация через «ЗаписьXML»

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

Разберем по шагам ключевые этапы построения алгоритма:

  1. Инициализация записи: Создаем объект ЗаписьXML, задаем параметры форматирования (отступы) и открываем файл или строку.
  2. Преобразование простых типов: Для приведения чисел, дат и булевых значений к корректному строковому представлению стандарта XML используем функцию XMLСтрока(). Она автоматически преобразует даты в формат ISO и исключает системные неразрывные пробелы в числах.
  3. Определение типа данных: Проверяем тип текущего значения. Если это простой тип — записываем конечное значение. Если ссылочный — открываем узел с реквизитами идентификации (ID, Код, Наименование) и рекурсивно обрабатываем его реквизиты.

Рассмотрим пример кода процедуры, выполняющей рекурсивную выгрузку объекта:


Процедура ВыгрузитьЗначениеРеквизита(ЗаписьXML, ИмяРеквизита, Значение)
    ЗаписьXML.ЗаписатьНачалоЭлемента(ИмяРеквизита);
    
    Если ЗначениеЗаполнено(Значение) И Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
        // Для ссылочного типа формируем идентификаторы и вложенные реквизиты
        ЗаписьXML.ЗаписатьНачалоЭлемента("ID");
        ЗаписьXML.ЗаписатьТекст(XMLСтрока(Значение.УникальныйИдентификатор()));
        ЗаписьXML.ЗаписатьКонецЭлемента();
        
        ЗаписьXML.ЗаписатьНачалоЭлемента("ЗначенияРеквизитов");
        
        // Пример выгрузки базовых реквизитов ссылки
        ЗаписьXML.ЗаписатьНачалоЭлемента("Наименование");
        ЗаписьXML.ЗаписатьТекст(XMLСтрока(Значение.Наименование));
        ЗаписьXML.ЗаписатьКонецЭлемента();
        
        ЗаписьXML.ЗаписатьКонецЭлемента(); // ЗначенияРеквизитов
    Иначе
        // Простой тип данных преобразуем стандартной функцией
        ЗаписьXML.ЗаписатьТекст(XMLСтрока(Значение));
    КонецЕсли;
    
    ЗаписьXML.ЗаписатьКонецЭлемента(); // ИмяРеквизита
КонецПроцедуры

Посмотрим на пример вызова этой процедуры при выгрузке основного объекта справочника:


ЗаписьXML = Новый ЗаписьXML;
ПараметрыЗаписи = Новый ПараметрыЗаписиXML("UTF-8", "1.0", Ложь, Ложь, "  ");
ЗаписьXML.ОткрытьФайл("C:\export\data.xml", ПараметрыЗаписи);

ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("Номенклатура");

ЗаписьXML.ЗаписатьНачалоЭлемента("ID");
ЗаписьXML.ЗаписатьТекст(XMLСтрока(СсылкаНоменклатура.УникальныйИдентификатор()));
ЗаписьXML.ЗаписатьКонецЭлемента();

ЗаписьXML.ЗаписатьНачалоЭлемента("ЗначенияРеквизитов");

// Выгрузка выбранных пользователем реквизитов
ВыгрузитьЗначениеРеквизита(ЗаписьXML, "Артикул", СсылкаНоменклатура.Артикул);
ВыгрузитьЗначениеРеквизита(ЗаписьXML, "Код", СсылкаНоменклатура.Код);
ВыгрузитьЗначениеРеквизита(ЗаписьXML, "ТипЦены", СсылкаНоменклатура.ТипЦен);

ЗаписьXML.ЗаписатьКонецЭлемента(); // ЗначенияРеквизитов
ЗаписьXML.ЗаписатьКонецЭлемента(); // Номенклатура

ЗаписьXML.Закрыть();

Альтернативный вариант: Использование объектной модели DOM

Если перед выгрузкой в файл требуется программно модифицировать узлы, менять их порядок или проверять целостность дерева в памяти, можно использовать объектную модель документа (DOM):

  1. Создаем объект ДокументDOM.
  2. Формируем узлы через метод СоздатьЭлемент() и выстраиваем иерархию методом ДобавитьДочерний().
  3. Записываем готовое дерево в файл с помощью связки объектов ЗаписьDOM и ЗаписьXML.

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

← На главную