Почему при записи XML через XDTO в цикле 1С дублируются значения и как это исправить

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

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

Рассмотрим, почему возникает эта проблема, проанализируем механизмы работы платформы с объектами XDTO и разберем правильные способы заполнения коллекций в цикле.

Причина возникновения проблемы

Выясним, почему вызов метода добавления элемента в коллекцию приводит к перезаписи предыдущих данных. В платформе 1С объекты типа ОбъектXDTO представляют собой ссылочные типы данных.

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

Пример некорректного кода, приводящего к дублированию:


// Неправильный подход: XML_Row создан один раз вне цикла
Для Каждого СтрТЧ Из ТЧ Цикл
    XML_Row.Code = СтрТЧ.Code;
    XML_Document.SupplierInfo.Merchandises.Row.Добавить(XML_Row);
КонецЦикла;

Правильное решение: создание нового экземпляра в цикле

Чтобы каждая строка XML содержала собственные уникальные данные, необходимо на каждой итерации цикла инстанцировать новый экземпляр объекта XDTO. При этом пересоздавать весь родительский XML-документ не требуется.

Разберем, как правильно реализовать заполнение коллекции через фабрику XDTO:


// 1. Получаем тип создаваемого узла из фабрики XDTO или метаданных
ТипСтроки = ФабрикаXDTO.Тип("http://www.example.com/supplier", "RowType");

Для Каждого СтрТЧ Из ТЧ Цикл
    // 2. Внутри цикла создаем НОВЫЙ экземпляр объекта
    НоваяСтрока = ФабрикаXDTO.Создать(ТипСтроки);
    НоваяСтрока.Code = СтрТЧ.Code;
    
    // 3. Добавляем новый объект в коллекцию родителя
    XML_Document.SupplierInfo.Merchandises.Row.Добавить(НоваяСтрока);
КонецЦикла;

Также тип вложенного элемента можно получить непосредственно из метаданных свойства родительского объекта, если exact-имя типа в пространстве имен неизвестно:


СвойствоRow = XML_Document.SupplierInfo.Merchandises.Свойства().Получить("Row");
ТипЭлементаRow = СвойствоRow.Тип;

Для Каждого СтрТЧ Из ТЧ Цикл
    НоваяСтрока = ФабрикаXDTO.Создать(ТипЭлементаRow);
    НоваяСтрока.Code = СтрТЧ.Code;
    XML_Document.SupplierInfo.Merchandises.Row.Добавить(НоваяСтрока);
КонецЦикла;

Особенности и ограничения платформы при работе с XDTO

Проанализируем важные нюансы работы с объектами XDTO, о которых необходимо помнить при проектировании интеграций:

  1. Отсутствие штатного клонирования: У объектов XDTO нет встроенного метода глубокого копирования. Функция ЗаполнитьЗначенияСвойств() копирует только простые (атомарные) свойства, но не создаст дубликаты для вложенных списков или сложных структур.
  2. Потребление оперативной памяти: Создание выгрузок через объектную модель XDTO формирует полное дерево XML в RAM. Если требуется выгрузить сотни тысяч строк, этот подход может привести к переполнению памяти.
  3. Альтернатива — потоковая запись через ЗаписьXML: Для большеобъемных файлов рекомендуется отказаться от формирования XDTO-дерева в пользу последовательной записи через объект ЗаписьXML (методы ЗаписатьНачалоЭлемента, ЗаписатьАтрибут, ЗаписатьКонецЭлемента). Это позволяет генерировать гигабайтные файлы с минимальным расходом памяти.
  4. Использование СериализаторXDTO: Если выгружаемые данные соответствуют стандартным объектам платформы 1С, их можно записывать прямо в поток ЗаписьXML с помощью сериализатора, избегая ручного конструирования каждого узла.
← На главную