В процессе разработки часто возникает задача передачи структурированных данных между базами 1С или внешними системами. Когда данных много и они распределены по разным таблицам, программисты сталкиваются с вопросом: как объединить несколько таблиц значений в один XML-файл так, чтобы его было удобно не только записать, но и корректно прочитать в обратную сторону? Разберем по шагам наиболее эффективные методы решения этой задачи, начиная от простых универсальных контейнеров и заканчивая оптимизированными способами для больших объемов данных.
Самый простой и элегантный способ — это упаковать все ваши таблицы в один объект-контейнер, который платформа 1С умеет сериализовать автоматически. Рассмотрим ситуацию, когда у нас есть пакетный запрос, возвращающий несколько результатов. Вместо того чтобы пытаться записать каждую таблицу отдельно, мы создадим единый объект.
Почему лучше использовать Структуру, а не Массив? Хотя оба варианта работоспособны, Структура позволяет назначать ключи (имена) для каждой таблицы. Это значительно упрощает последующее чтение: вам не нужно помнить, что в индексе 0 лежит таблица товаров, а в индексе 1 — таблица контрагентов. Вы просто обращаетесь к полю по имени.
Рассмотрим пример реализации через Структура:
// 1. Получаем данные из запроса
РезультатыПакетногоЗапроса = Запрос.ВыполнитьПакет();
// 2. Формируем контейнер для выгрузки
ДанныеДляЭкспорта = Новый Структура;
ДанныеДляЭкспорта.Вставить("ТаблицаТовары", РезультатыПакетногоЗапроса[0].Выгрузить());
ДанныеДляЭкспорта.Вставить("ТаблицаСклады", РезультатыПакетногоЗапроса[1].Выгрузить());
// 3. Подготавливаем механизмы записи
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл("C:\temp\DataExport.xml", "UTF-8");
// 4. Используем СериализаторXDTO для записи всего контейнера целиком
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ДанныеДляЭкспорта, НазначениеТипаXML.Явное);
ЗаписьXML.Закрыть();
В данном примере использование НазначениеТипаXML.Явное гарантирует, что в XML будут сохранены описания типов данных каждой колонки. Это критически важно, если в таблицах присутствуют типы Число, Дата или ссылки на объекты, которые должны корректно восстановиться при загрузке.
Проанализируем ситуацию, когда таблицы содержат сотни тысяч строк. Использование автоматической сериализации через контейнер может привести к ошибке «Нехватка памяти», так как 1С пытается построить полное дерево объектов в оперативной памяти перед физической записью на диск. В таких случаях нам поможет метод ручного управления узлами XML.
Выясним, как правильно организовать структуру файла в ручном режиме:
СериализаторXDTO для записи объекта ТаблицаЗначений внутри нашего корневого узла.Разберем программный код:
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл("C:\temp\BigDataExport.xml", "UTF-8");
// Записываем начало общего корня
ЗаписьXML.ЗаписатьНачалоЭлемента("ДанныеЭкспорта");
// Записываем первую таблицу
Таблица1 = РезультатыПакетногоЗапроса[0].Выгрузить();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Таблица1, "TableInfo1", "http://v8.1c.ru/8.1/data/core");
// Записываем вторую таблицу
Таблица2 = РезультатыПакетногоЗапроса[1].Выгрузить();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Таблица2, "TableInfo2", "http://v8.1c.ru/8.1/data/core");
// Закрываем корень
ЗаписьXML.ЗаписатьКонецЭлемента();
ЗаписьXML.Закрыть();
Этот подход позволяет комбинировать автоматическую мощь СериализаторXDTO и ручной контроль над структурой файла, что более бережно относится к ресурсам сервера.
Посмотрим на процесс восстановления данных. Если мы использовали Структура при записи (Метод 1), то чтение превращается в простую операцию в одну строку. Платформа сама распознает типы объектов внутри файла и восстановит их в соответствующие коллекции 1С.
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл("C:\temp\DataExport.xml");
// Десериализация всего контейнера обратно в структуру
ДанныеИзФайла = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
// Теперь мы можем обращаться к таблицам по именам ключей
Если ТипЗнч(ДанныеИзФайла) = Тип("Структура") Тогда
ТаблицаТовары = ДанныеИзФайла.ТаблицаТовары;
ТаблицаСклады = ДанныеИзФайла.ТаблицаСклады;
КонецЕсли;
ЧтениеXML.Закрыть();
Проанализируем дополнительные возможности, которые помогут сделать вашу выгрузку более надежной:
1. Использование XDTO-пакетов для интеграции. Если ваш XML файл предназначен для сторонней системы (например, написанной на Java или Python), стандартные теги 1С (ValueTable, row, column) могут быть неудобны. В этом случае рекомендуется создать в конфигурации собственный XDTO-пакет. Это позволит вам строго описать схему данных (XSD), задать понятные имена тегов для каждой колонки таблицы и валидировать файл перед отправкой.
2. Метод XMLСтрока(). Помните, что встроенная функция XMLСтрока(ВашаТаблицаЗначений) не работает. Она предназначена только для простых типов. Для коллекций использование СериализаторXDTO является безальтернативным штатным средством.
3. Потоки в памяти. Если данные не нужно сохранять в файл, а нужно передать, например, в HTTP-запрос, рассмотрите использование объекта ПотокВПамяти. Это ускорит работу, так как исключит медленные дисковые операции:
Поток = Новый ПотокВПамяти();
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьПоток(Поток);
// ... запись данных ...
РезультатБайты = Поток.ЗакрытьИПолучитьДвоичныеДанные();
Таким образом, мы выяснили, что наиболее универсальным способом выгрузки нескольких таблиц является использование объекта Структура в связке с СериализаторXDTO. Это обеспечивает автоматическую типизацию колонок, простоту обратного чтения и высокую скорость разработки.