Как устранить ошибку Отсутствует отображение для типа ОбъектXDTO при выгрузке в XML

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

Работа с механизмами XDTO и XML в платформе «1С:Предприятие 8» является базовым навыком для реализации интеграций. Однако новички часто сталкиваются с неочевидными ошибками, такими как «Отсутствует отображение для типа "ОбъектXDTO"» или «Ошибочный порядок записи XML». В этой статье мы подробно разберем, почему возникают эти проблемы, в чем разница между СериализаторXDTO и ФабрикаXDTO, и как правильно выгружать данные справочников со всеми реквизитами.

Разберем основную причину ошибки отображения типа

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

СериализаторXDTO — это «высокоуровневый» инструмент. Его главная задача — автоматически преобразовывать внутренние объекты 1С (такие как СправочникОбъект, ДокументОбъект, Массив или Структура) в XML на основе метаданных конфигурации. Он ожидает на вход именно «родные» типы платформы.

ФабрикаXDTO — это инструмент для работы с самой моделью данных XDTO. Когда мы программно создаем ОбъектXDTO по определенной схеме (пакету XDTO), мы уже работаем в пространстве типов XDTO. Пытаться передать ОбъектXDTO в СериализаторXDTO — это все равно что пытаться перевести с английского на русский текст, который уже написан на русском. Сериализатор просто не понимает, как сопоставить технический объект XDTO с типами метаданных, так как он ищет именно объекты 1С.

Решение: Если у вас уже есть ОбъектXDTO, его нужно записывать напрямую через фабрику:

ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ПродуктXDTO);

Проанализируем проблему выгрузки только идентификатора

Часто программисты замечают, что после успешного выполнения кода в XML-файле вместо заполненных реквизитов (наименование, артикул, цена) оказывается только UUID (уникальный идентификатор). Давайте выясним, почему так происходит.

В 1С существует разница между Ссылкой и Объектом.

Когда мы передаем в метод СериализаторXDTO.ЗаписатьXML() ссылку (полученную, например, через НайтиПоНаименованию() или НайтиПоКоду()), сериализатор логично записывает только то, что есть в ссылке — идентификатор. Чтобы выгрузить все данные, нам необходимо получить объект.

Рассмотрим правильный пример получения данных:


// Неправильно (выгрузит только ссылку):
ПродуктСсылка = Справочники.Продукт.НайтиПоНаименованию("Апельсин");
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ПродуктСсылка);

// Правильно (выгрузит все реквизиты):
ПродуктОбъект = Справочники.Продукт.НайтиПоНаименованию("Апельсин").ПолучитьОбъект();
Если ПродуктОбъект <> Неопределено Тогда
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ПродуктОбъект);
КонецЕсли;

Выясним причину ошибки Ошибочный порядок записи XML

Эта ошибка часто возникает при работе с пространствами имен (Namespaces). В 1С объект ЗаписьXML строго следит за соблюдением спецификации XML. Мы не можем записывать соответствия пространств имен «в пустоту».

Посмотрим на правильную последовательность действий, которую необходимо соблюдать:

  1. Инициализация объекта ЗаписьXML и открытие файла или строки.
  2. Запись объявления XML (ЗаписатьОбъявлениеXML()).
  3. Запись начала корневого элемента (ЗаписатьНачалоЭлемента()).
  4. Только теперь запись пространств имен через ЗаписатьСоответствиеПространстваИмен().
  5. Запись вложенных элементов или сериализация объектов.
  6. Запись конца корневого элемента и закрытие файла.

Если вы попытаетесь вызвать ЗаписатьСоответствиеПространстваИмен() до того, как открыли хотя бы один тег (элемент), система выдаст исключение. Это связано с тем, что пространства имен в XML всегда привязаны к конкретному узлу.

Рассмотрим пошагово правильный код выгрузки через СериализаторXDTO

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


Процедура ВыгрузитьДанныеЧерезСериализатор()
    ИмяФайла = "C:\Обмен\Export.xml";
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.ОткрытьФайл(ИмяФайла, "UTF-8");
    
    // 1. Пишем заголовок файла
    ЗаписьXML.ЗаписатьОбъявлениеXML();
    
    // 2. Открываем корневой узел
    ЗаписьXML.ЗаписатьНачалоЭлемента("ДанныеОбмена");
    
    // 3. Указываем стандартные пространства имен (необязательно, но полезно для типизации)
    ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xsd", "http://www.w3.org/2001/XMLSchema");
    ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xsi", "http://www.w3.org/2001/XMLSchema-instance");
    
    Сериализатор = Новый СериализаторXDTO(ФабрикаXDTO);
    
    // 4. Выбираем данные
    Выборка = Справочники.Продукт.Выбрать();
    Пока Выборка.Следующий() Цикл
        // Важно: Получаем объект, а не ссылку!
        ОбъектДанных = Выборка.ПолучитьОбъект();
        // Записываем объект в XML
        Сериализатор.ЗаписатьXML(ЗаписьXML, ОбъектДанных, НазначениеТипаXML.Явное);
    КонецЦикла;
    
    // 5. Закрываем теги и файл
    ЗаписьXML.ЗаписатьКонецЭлемента();
    ЗаписьXML.Закрыть();
    
    Сообщить("Выгрузка завершена успешно!");
КонецПроцедуры

Разберем альтернативный вариант через ФабрикуXDTO и собственный пакет

Если же ваша задача — выгрузить данные во внешнюю систему (например, на сайт или в банк), которая требует строго определенной структуры XML, отличающейся от внутренней структуры 1С, вам придется использовать ОбъектXDTO.

В этом случае последовательность действий будет следующей:


Процедура ВыгрузитьЧерезФабрику()
    // Предположим, в конфигурации создан Пакет XDTO с именем "МойОбмен" 
    // и типом объекта "Товар", у которого есть свойства "Код", "Имя", "Цена".
    
    ИмяФайла = "C:\Обмен\CustomExport.xml";
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.ОткрытьФайл(ИмяФайла);
    
    ЗаписьXML.ЗаписатьОбъявлениеXML();
    ЗаписьXML.ЗаписатьНачалоЭлемента("Catalog");
    
    ПродуктСсылка = Справочники.Продукт.НайтиПоНаименованию("Апельсин");
    
    Если Не ПродуктСсылка.Пустая() Тогда
        // Создаем объект XDTO на основании типа из пакета
        ТипТовара = ФабрикаXDTO.Тип("http://www.mycompany.ru/exchange", "Товар");
        ТоварXDTO = ФабрикаXDTO.Создать(ТипТовара);
        
        // Заполняем свойства вручную
        ТоварXDTO.Код = ПродуктСсылка.Код;
        ТоварXDTO.Имя = ПродуктСсылка.Наименование;
        ТоварXDTO.Цена = ПродуктСсылка.Цена; // Допустим, такой реквизит есть
        
        // ВАЖНО: Используем Фабрику для записи, а не Сериализатор!
        ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ТоварXDTO);
    КонецЕсли;
    
    ЗаписьXML.ЗаписатьКонецЭлемента();
    ЗаписьXML.Закрыть();
КонецПроцедуры

Подведем итоги и дадим рекомендации

Для того чтобы ваша выгрузка в XML работала стабильно и без ошибок, придерживайтесь следующих правил:

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

← На главную