Механизм XDTO (XML Data Transfer Objects) является одним из самых мощных и гибких инструментов в системе 1С:Предприятие для работы с данными в формате XML и JSON. В отличие от последовательной записи XML, использование XDTO позволяет работать с данными как с полноценными объектами, что значительно упрощает контроль структуры и типов данных. В данной статье мы подробно разберем, как реализовать выгрузку данных с нуля, даже если вам запрещено вносить изменения в конфигурацию.
Когда перед разработчиком встает задача выгрузить сложную структуру (например, контрагенты, номенклатура, остатки и документы для сайта), ручное формирование тегов через ЗаписьXML становится трудоемким и чреватым ошибками. XDTO позволяет:
Для начала нам необходимо определить структуру будущего XML-файла. Рассмотрим ситуацию, когда вам нужно создать собственный пакет. Если у вас есть возможность менять конфигурацию, создайте новый объект XDTO-пакет в ветке "Общие".
В пакете укажите уникальный URI пространства имен (например, http://www.mysite.ru/exchange). Это критически важно для того, чтобы принимающая сторона (сайт) могла идентифицировать ваши данные. Внутри пакета создаются Типы объектов (например, "Номенклатура") и их Свойства (Наименование, Артикул, Цена).
Проанализируем важную настройку свойства — Форма:
<Наименование>Товар 1</Наименование>).<Товар Наименование="Товар 1" />).Именно с этим параметром часто связаны ошибки записи свойств, когда 1С не может сопоставить программное обращение к объекту с его описанием в схеме.
Если проект требует реализации выгрузки во внешней обработке без внесения изменений в основную базу, мы можем воспользоваться внешней XSD-схемой. Разберем по шагам, как это сделать:
.xsd.Рассмотрим пример кода для инициализации фабрики из макета:
ИмяФайлаСхемы = ПолучитьИмяВременногоФайла("xsd");
МакетСхемы = ПолучитьМакет("МояСхемаXSD");
МакетСхемы.Записать(ИмяФайлаСхемы);
// Создаем фабрику на основании внешней схемы
МояФабрика = СоздатьФабрикуXDTO(ИмяФайлаСхемы);
Теперь рассмотрим основной алгоритм выгрузки. Выясним причину, по которой часто возникают сложности при заполнении объектов. Нам нужно создать объект на основании типа из нашей фабрики, заполнить его данными из запроса и записать в файл.
Проанализируем пример кода для выгрузки номенклатуры:
ПараметрыЗаписиXML = Новый ПараметрыЗаписиXML("UTF-8", "1.0", Ложь);
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ПутьКФайлу, ПараметрыЗаписиXML);
// Получаем тип объекта из нашего пакета
// "http://www.mysite.ru/exchange" - это URI вашего пакета
ТипОбъекта = ФабрикаXDTO.Тип("http://www.mysite.ru/exchange", "Товар");
Запрос = Новый Запрос("ВЫБРАТЬ ТОП 10 Наименование, Артикул ИЗ Справочник.Номенклатура");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Создаем экземпляр объекта XDTO
НовыйТовар = ФабрикаXDTO.Создать(ТипОбъекта);
НовыйТовар.Наименование = Выборка.Наименование;
НовыйТовар.Артикул = Выборка.Артикул;
// Записываем объект в XML
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, НовыйТовар);
КонецЦикла;
ЗаписьXML.Закрыть();
Эта ошибка часто встречается у начинающих разработчиков (как в сообщении №26). Она возникает по двум основным причинам:
1. Несоответствие имен свойств: Вы пытаетесь обратиться к ОбъектXDTO.Наименование, а в пакете свойство называется Name. Всегда проверяйте регистр и точность написания.
2. Работа со списками (коллекциями): Если свойство в пакете имеет параметр Максимальное количество = -1, оно является списком. Вы не можете просто присвоить ему значение. Вместо этого нужно использовать метод Добавить().
Посмотрим на пример правильной работы со списком:
// Предположим, у нас есть корневой объект "Выгрузка", содержащий список "Товары"
ТипКорня = ФабрикаXDTO.Тип("http://www.mysite.ru/exchange", "Выгрузка");
ОбъектВыгрузка = ФабрикаXDTO.Создать(ТипКорня);
// Находим тип элемента списка
ТипТовара = ФабрикаXDTO.Тип("http://www.mysite.ru/exchange", "Товар");
Пока Выборка.Следующий() Цикл
ЭлементТовар = ФабрикаXDTO.Создать(ТипТовара);
ЭлементТовар.Наименование = Выборка.Наименование;
// Добавляем созданный элемент в список корневого объекта
ОбъектВыгрузка.Товары.Добавить(ЭлементТовар);
КонецЦикла;
Если вам необходимо выгрузить десятки тысяч позиций номенклатуры, создание одного гигантского объекта XDTO в памяти приведет к ошибке Out of Memory. Рассмотрим подробнее, как правильно организовать потоковую запись.
Вместо того чтобы собирать все товары в один массив внутри XDTO-объекта, записывайте их по одному. Откройте ЗаписьXML, вручную запишите корневой тег через ЗаписатьНачалоЭлемента, затем в цикле создавайте маленький объект XDTO для одного товара, записывайте его через ФабрикаXDTO.ЗаписатьXML и в конце закройте корневой тег.
ЗаписьXML.ЗаписатьНачалоЭлемента("Root"); // Корневой тег вручную
Пока Выборка.Следующий() Цикл
ТоварXDTO = ФабрикаXDTO.Создать(ТипТовара);
// Заполнение...
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ТоварXDTO, , , , НазначениеТипаXML.Явное);
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем Root
СериализаторXDTO.ЗаписатьXDTO(ЗаписьXML, СсылкаНаОбъект). Это самый быстрый способ выгрузки "как есть".ОбъектXDTO.Проверить(). Если объект не соответствует схеме, метод выдаст подробное описание ошибки.Namespace в коде при вызове Тип() совпадал с тем, что указано в свойствах пакета XDTO.Таким образом, использование XDTO превращает рутинную работу с текстовыми строками XML в структурированное объектное программирование, что делает код надежнее и легче в поддержке.