Выгрузка данных в формат XML — это базовая задача при организации обмена данными между различными информационными системами. В среде 1С:Предприятие для этих целей предусмотрено несколько механизмов: от низкоуровневой потоковой записи до высокоуровневой сериализации. В данной статье мы подробно разберем, как правильно реализовать выгрузку таблицы в XML, проанализируем типичные ошибки начинающих разработчиков и рассмотрим продвинутые инструменты повышения читаемости и надежности кода.
Для создания XML-файла «с нуля» основным инструментом является объект ЗаписьXML. Он работает по принципу потоковой записи: данные пишутся последовательно, узел за узлом. Это позволяет обрабатывать огромные объемы данных, не перегружая оперативную память сервера.
Рассмотрим классическую структуру кода для инициализации записи. Прежде всего, нам необходимо создать объект, открыть файл и записать стандартное объявление XML (так называемый prolog), которое указывает версию и кодировку документа.
ЗаписьXML = Новый ЗаписьXML;
ПараметрыЗаписи = Новый ПараметрыЗаписиXML("UTF-8", "1.0", Истина);
ЗаписьXML.ОткрытьФайл("C:\Temp\Export.xml", ПараметрыЗаписи);
ЗаписьXML.ЗаписатьОбъявлениеXML();
Обратите внимание на использование объекта ПараметрыЗаписиXML. По умолчанию 1С формирует XML в одну строку без отступов. Использование параметра Истина в третьем аргументе конструктора позволяет создать «красивый» человекочитаемый файл с иерархическими отступами.
Разберем ситуацию, когда нам нужно выгрузить данные из справочника или таблицы вручную, контролируя каждый тег. Проанализируем пример выгрузки списка организаций:
ЗаписьXML.ЗаписатьНачалоЭлемента("Root"); // Корневой элемент должен быть один
Выборка = Справочники.Организации.Выбрать();
Пока Выборка.Следующий() Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента("Item");
// Запись данных через атрибуты
ЗаписьXML.ЗаписатьАтрибут("Code", Строка(Выборка.Код));
// Запись данных через вложенные элементы
ЗаписьXML.ЗаписатьНачалоЭлемента("Name");
ЗаписьXML.ЗаписатьТекст(Строка(Выборка.Наименование));
ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем "Name"
ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем "Item"
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем "Root"
ЗаписьXML.Закрыть();
В этом примере мы видим разницу между атрибутами и текстовыми узлами. Важный момент: метод ЗаписатьКонецЭлемента() не принимает имя тега. Он просто закрывает последний открытый элемент. Поэтому крайне важно соблюдать парность вызовов «Начало» и «Конец», иначе вы получите исключение Ошибочный порядок записи XML.
Часто возникает задача выгрузить произвольную таблицу, где состав колонок заранее неизвестен. Рассмотрим, как правильно организовать вложенный цикл по строкам и колонкам ТаблицаЗначений. Выясним причину популярных ошибок при таком подходе.
&НаСервере
Процедура ВыгрузитьТаблицуВXML(ТЗДляВыгрузки, ПутьКФайлу)
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ПутьКФайлу, "UTF-8");
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("ДанныеТаблицы");
Для Каждого СтрТЗ Из ТЗДляВыгрузки Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента("Строка");
Для Каждого Колонка Из ТЗДляВыгрузки.Колонки Цикл
ИмяТега = Колонка.Имя;
Значение = СтрТЗ[ИмяТега];
// Используем XMLСтрока для правильного форматирования типов данных
ТекстЗначения = XMLСтрока(Значение);
ЗаписьXML.ЗаписатьНачалоЭлемента(ИмяТега);
ЗаписьXML.ЗаписатьТекст(ТекстЗначения);
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем элемент "Строка"
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем корневой элемент
ЗаписьXML.Закрыть(); // Обязательно закрываем файл!
КонецПроцедуры
Анализ кода: Обратите внимание на использование функции XMLСтрока(). В отличие от стандартной функции Строка(), она преобразует типы данных 1С (Даты, Числа, Булево) в стандарт, понятный XML-парсерам. Например, дата будет записана в формате ГГГГ-ММ-ДДTHH:MM:SS, а логическое значение «Истина» превратится в true.
Многие разработчики сталкиваются с ошибкой Ошибочный порядок записи XML. Проанализируем ситуацию: она возникает, когда вы пытаетесь записать текст или атрибут в тот момент, когда контекст записи этого не позволяет. Например:
ЗаписатьКонецЭлемента() больше раз, чем ЗаписатьНачалоЭлемента().ЗаписатьАтрибут() после того, как уже начали записывать вложенный текст или другой вложенный элемент. Правило: атрибуты всегда пишутся сразу после «Начала элемента», до любого другого содержимого.Если ваша задача — просто передать данные из одной базы 1С в другую или сохранить объект (например, целый документ со всеми табличными частями), ручное формирование тегов является избыточным. Для этого существует СериализаторXDTO.
Этот механизм автоматически анализирует метаданные объекта и строит правильную XML-структуру без участия программиста в описании каждого поля. Рассмотрим пример выгрузки ссылки на документ:
// Предположим, у нас есть ссылка на документ
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл("C:\Temp\Doc.xml");
// Используем глобальный контекст для записи
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ДокументОбъект);
ЗаписьXML.Закрыть();
Этот метод экономит время, минимизирует количество ошибок в именах тегов и гарантирует, что структура файла будет соответствовать схеме данных 1С. Однако он менее гибок, если принимающая сторона требует специфический формат XML (например, банковский стандарт или формат государственного ведомства).
Проанализируем важный аспект: имена колонок в ТаблицаЗначений могут содержать символы, недопустимые в именах тегов XML (хотя в 1С это ограничено конфигуратором, программно созданные таблицы могут иметь особенности). XML-тег не может начинаться с цифры и не может содержать пробелы. Если вы выгружаете данные из внешних источников через ТЗ, всегда проверяйте валидность имен или используйте фиксированные имена узлов (например, <Column name="ИмяКолонки">Значение</Column>).
Мы рассмотрели процесс выгрузки данных в XML: от самых простых циклов до использования XDTO. Подведем итоги: для простых и быстрых выгрузок используйте ЗаписьXML в связке с XMLСтрока. Для передачи сложных объектов 1С выбирайте СериализаторXDTO. И никогда не забывайте вызывать метод Закрыть(), чтобы избежать блокировки файлов и потери данных.