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

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

Выгрузка документов и справочников в формат XML — одна из самых частых задач при интеграции 1С с внешними информационными системами. Начинающие разработчики часто сталкиваются с техническими трудностями на этом пути: нарушается иерархия элементов, XML-файл записывается некорректно, либо возникают сложные ошибки отображения типов данных (особенно ссылочных, таких как СправочникСсылка). В этой статье мы подробно разберем типичные ошибки при ручном формировании XML и использовании фабрики XDTO, а также представим готовые шаблоны кода для правильного решения этих задач.

Почему нарушается очередность записи XML при обходе табличных частей?

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

Для создания правильной иерархической структуры выгрузка должна происходить строго в рамках одного единого цикла по документам. Внутри этого цикла мы последовательно открываем тег документа, записываем его шапку, запускаем вложенный цикл по его же табличной части, закрываем тег табличной части и только потом закрываем тег самого документа. Давайте разберем правильный алгоритм на примере:


ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл("D:\126.xml", "UTF-8");
ЗаписьXML.ЗаписатьОбъявлениеXML();

// Открываем корневой элемент всего документа выгрузки
ЗаписьXML.ЗаписатьНачалоЭлемента("Документы");

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

// Закрываем корневой элемент
ЗаписьXML.ЗаписатьКонецЭлемента(); // Документы
ЗаписьXML.Закрыть();

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

Устранение конфликтов имен с метаданными 1С

Вторая частая ошибка новичков — попытка назвать локальную переменную именем системной коллекции. Например, объявление переменной с именем Документы приводит к ошибке "Поле объекта недоступно для записи".

Это происходит потому, что идентификатор Документы зарезервирован платформой 1С на глобальном уровне для доступа к менеджерам всех документов конфигурации. Данный объект доступен только для чтения, и попытка переопределить его (например, написать Документы = ФабрикаXDTO.Создать(...)) вызывает сбой на этапе выполнения кода. Решается эта проблема очень просто: всегда используйте префиксы или альтернативные имена для ваших переменных. Вместо названия Документы назовите переменную мДокументы, МассивДокументов или ВыгружаемыеДокументы.

Решение проблемы отображения типов при работе с фабрикой XDTO

При использовании фабрики XDTO для генерации XML-файлов по схеме часто возникает ошибка: "Ошибка отображения типов: Отображение типа 'СправочникСсылка.Номенклатура' в тип...". Причина кроется в том, что в структуре вашей схемы XDTO для свойства (например, Номенклатура) указан простой тип данных (например, xs:string или anySimpleType), а код 1С пытается напрямую присвоить этому свойству объект типа СправочникСсылка.

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

Вариант А. Передача ссылки строковым представлением (простой путь)

Если принимающей стороне не нужно знать внутренний тип ссылки 1С, а требуется получить лишь текстовую информацию о товаре, передавайте строковое значение свойства. Мы можем извлечь уникальный идентификатор (GUID), код или наименование справочника. Посмотрим на примере кода:


// Вместо прямой передачи ссылки: СписокНоменклатуры.Номенклатура = стр.Номенклатура;
// Используйте передачу строкового представления:

// Вариант 1: Передаем наименование
СписокНоменклатуры.Номенклатура = Строка(стр.Номенклатура.Наименование);

// Вариант 2: Передаем уникальный идентификатор (GUID) для последующего поиска
СписокНоменклатуры.Номенклатура = Строка(стр.Номенклатура.УникальныйИдентификатор());

Вариант Б. Использование стандартных пространств имен типов 1С в XDTO (сложный путь)

Если XML-схема сторонней системы строго требует передачи объектов в формате типов данных 1С, необходимо правильно инициализировать XDTO-объект ссылки, используя фабрику и соответствующее пространство имен предприятия:


// Получаем тип ссылки из метаданных схемы XDTO
ТипСсылка = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "CatalogRef.Номенклатура");

// Создаем объект ссылки XDTO, инициализируя его через уникальный идентификатор
СсылкаXDTO = ФабрикаXDTO.Создать(ТипСсылка, Строка(стр.Номенклатура.УникальныйИдентификатор()));

// Теперь объект XDTO успешно примет типизированное значение
СписокНоменклатуры.Номенклатура = СсылкаXDTO;

Использование Сериализатора XDTO для быстрой выгрузки

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

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


ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл("C:\Обмен\ВыгрузкаДокументов.xml", "UTF-8");
ЗаписьXML.ЗаписатьОбъявлениеXML();

// Записываем корневой элемент-контейнер
ЗаписьXML.ЗаписатьНачалоЭлемента("ВсеДокументы");

// Прописываем системные пространства имен для корректного распознавания типов 1С
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("V8Exch", "http://v8.1c.ru/8.1/edi/exch/type");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xsi", "http://www.w3.org/2001/XMLSchema-instance");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("v8", "http://v8.1c.ru/8.1/data/enterprise");

Сериализатор = СериализаторXDTO;
Выборка = Документы.ПриходнаяНакладная.Выбрать();

Пока Выборка.Следующий() Цикл
    // Получаем непосредственно объект документа (не ссылку!)
    ОбъектДокумента = Выборка.ПолучитьОбъект();
    
    // Сериализатор автоматически соберет XML-структуру всего документа
    Сериализатор.ЗаписатьXML(ЗаписьXML, ОбъектДокумента);
КонецЦикла;

ЗаписьXML.ЗаписатьКонецЭлемента(); // ВсеДокументы
ЗаписьXML.Закрыть();

Преимущества использования Сериализатора XDTO:

  1. Минимум кода. Вам не нужно описывать перебор строк табличной части, платформа сделает это самостоятельно.
  2. Надежность. Риск допустить опечатку в названиях реквизитов или нарушить вложенность узлов равен нулю.
  3. Автоматическая поддержка типов. Все ссылки (на номенклатуру, контрагентов, склады) запишутся в стандартном формате 1С с сохранением их GUID.

Используйте ручную сборку через ЗаписьXML или кастомные пакеты XDTO, когда требуется сопряжение со сторонними API и внешними сервисами, имеющими жесткий регламент структуры файлов. Если же обмен происходит между конфигурациями на платформе 1С — всегда отдавайте предпочтение СериализаторXDTO, так как это значительно сократит время разработки и повысит отказоустойчивость вашей интеграции.

← На главную