При интеграции систем часто возникает задача выгрузить справочники 1С в XML с нестандартной иерархией тегов. Например, требуется обернуть реквизиты объекта в специальный тег ЗначенияРеквизитов, сделать именами тегов имена реквизитов, а для ссылочных полей рекурсивно выгружать идентификаторы, коды и вложенные реквизиты. При этом состав выгружаемых полей может динамически определяться пользователем в пользовательском интерфейсе.
Разберем, почему встроенный механизм XDTO не предназначен для решения подобных задач и какие инструменты платформы 1С:Предприятие позволяют реализовать такую выгрузку максимально быстро и эффективно.
Проанализируем особенности работы XDTO в платформе 1С:
СериализаторXDTO выгружает объекты в предопределенном платформенном формате и не позволяет внедрять произвольные промежуточные узлы (например, <ЗначенияРеквизитов>) или произвольно менять структуру тегов.anyType или динамическая генерация пакетов через ФабрикаXDTO в программном коде приводят к избыточному усложнению архитектуры и не дают преимуществ по сравнению с прямой генерацией XML.Механизм XDTO ориентирован на строгие контракты обмена (WSDL, SOAP, фиксированные схемы XSD). Для выгрузки данных с произвольной структурой и динамическим составом полей целесообразно использовать потоковую запись через объект ЗаписьXML.
Посмотрим на практическую реализацию задачи с помощью объекта ЗаписьXML. Потоковая запись формирует XML последовательно, не загружая все дерево документа в оперативную память, что гарантирует высокую скорость работы даже на больших объемах данных.
Разберем по шагам ключевые этапы построения алгоритма:
ЗаписьXML, задаем параметры форматирования (отступы) и открываем файл или строку.XMLСтрока(). Она автоматически преобразует даты в формат ISO и исключает системные неразрывные пробелы в числах.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.СоздатьЭлемент() и выстраиваем иерархию методом ДобавитьДочерний().ЗаписьDOM и ЗаписьXML.Этот способ потребляет больше оперативной памяти, чем прямая запись через ЗаписьXML, однако предоставляет полный контроль над структурой дерева документа до момента его сохранения.