Как записать несколько объектов в один XML-файл в 1С?

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

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

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

Способ 1. Использование массива как единого контейнера

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

Рассмотрим пример кода:


МассивОбъектов = Новый Массив;
МассивОбъектов.Добавить(Справочники.Номенклатура.НайтиПоКоду("001"));
МассивОбъектов.Добавить(Справочники.Контрагенты.НайтиПоКоду("002"));
МассивОбъектов.Добавить(Документы.РеализацияТоваровУслуг.НайтиПоНомеру("123", ТекущаяДата()));

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

Преимущества этого метода:

  1. Минимальное количество строк кода.
  2. Автоматическая обработка типов платформой 1С.

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

Способ 2. Ручное формирование структуры (Потоковая запись)

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

Проанализируем алгоритм потоковой записи:


ЗаписьXML = Новый ЗаписьXML;
// Настраиваем параметры записи для красивого форматирования
ПараметрыЗаписи = Новый ПараметрыЗаписиXML("UTF-8", "1.0", Истина);
ЗаписьXML.ОткрытьФайл("C:\data.xml", ПараметрыЗаписи);

// Записываем заголовок документа
ЗаписьXML.ЗаписатьОбъявлениеXML();

// Создаем наш собственный корневой элемент
ЗаписьXML.ЗаписатьНачалоЭлемента("RootElement");

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

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

// Закрываем файл
ЗаписьXML.Закрыть();

В этом примере мы использовали объект ПараметрыЗаписиXML. Установка свойства Отступ = Истина делает файл читаемым для человека, добавляя переносы строк и табуляцию. Метод ЗаписатьОбъявлениеXML() добавляет стандартную строку заголовка с указанием кодировки, что является хорошим тоном при работе с XML.

Способ 3. Использование Сериализатора XDTO

Для более сложных задач обмена данными, особенно когда требуется передать информацию о типах объектов или работать в рамках определенных схем, рекомендуется использовать СериализаторXDTO. Он предоставляет более гибкие инструменты управления процессом сериализации.

Посмотрим на пример записи через XDTO:


ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл("C:\data_xdto.xml");
ЗаписьXML.ЗаписатьНачалоЭлемента("DataExport");

// Используем глобальный СериализаторXDTO
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Объект1);
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Объект2);

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

Использование СериализаторXDTO позволяет корректно сохранять ссылки на объекты, учитывая их пространства имен (URI), что критически важно при обмене данными между разными информационными базами.

Как правильно прочитать записанные объекты?

Записать данные — это только половина задачи. Важно правильно их извлечь. Типичная ошибка при чтении нескольких объектов заключается в неправильном позиционировании курсора чтения. Рассмотрим правильный подход к чтению файла, созданного в Способе №2.


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл("C:\data.xml");

// Переходим к корневому элементу
ЧтениеXML.Прочитать(); 

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

ЧтениеXML.Закрыть();

Важный нюанс: Обратите внимание, что внутри цикла мы используем проверку ТипУзла. Это необходимо, потому что метод ПрочитатьXML() после завершения своей работы позиционирует чтение на следующем узле. Если просто вызывать ЧтениеXML.Прочитать() в заголовке цикла без проверок, можно случайно пропустить ("перепрыгнуть") через один объект в файле.

Рекомендации по оптимизации

Разберем несколько важных моментов, которые помогут избежать ошибок при работе с большими XML-файлами:

  1. Отказ от ЗаписиТекста: В исходном вопросе автор использовал ЗаписьТекста совместно с ЗаписьXML.УстановитьСтроку(). Это избыточно. Используйте метод ОткрытьФайл непосредственно у объекта ЗаписьXML. Это работает быстрее и эффективнее расходует ресурсы.
  2. Кодировка: Всегда явно указывайте кодировку (рекомендуется UTF-8). Это предотвратит проблемы с чтением кириллицы в других системах.
  3. Проверка типов при чтении: При использовании ПрочитатьXML или СериализаторXDTO.ПрочитатьXML всегда проверяйте тип полученного значения через ТипЗнч(). В файле могут оказаться неожиданные данные или пустые ссылки.

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

← На главную