Как прочитать и записать таблицу значений с динамическими колонками в XML

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

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

Анализ ошибки Сериализатора XDTO

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

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

Способ 1. Использование функций БСП (наиболее простой путь)

Если в ваших конфигурациях подключена Библиотека Стандартных Подсистем (БСП), задача решается буквально в две строки. Методы общего назначения позволяют преобразовать любое сериализуемое значение (включая ТаблицаЗначений) в строку XML и обратно, сохраняя при этом структуру колонок и типы данных.

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


// В базе-источнике
СтрокаXML = ОбщегоНазначения.ЗначениеВСтрокуXML(ВашаТаблицаЗначений);
// Далее записываем СтрокаXML в файл или передаем через API

И код для загрузки в базе-приемнике:


// В базе-приемнике
НоваяТЗ = ОбщегоНазначения.ЗначениеИзСтрокиXML(СтрокаXML);

Важный нюанс: Эти функции используют системные методы ЗначениеВXMLСтроку и ЗначениеИзXMLСтроки. Они идеально подходят для обмена между базами 1С, так как автоматически упаковывают метаданные колонок в формат, понятный платформе.

Способ 2. Использование двоичных данных (самый быстрый и компактный)

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

Проанализируем шаги реализации:

  1. Преобразуем таблицу значений в ДвоичныеДанные.
  2. Записываем их в файл или передаем через временное хранилище.
  3. В базе-приемнике восстанавливаем объект.

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


// Выгрузка
ДвоичныеДанныеТЗ = ПолучитьИзВременногоХранилища(Адрес); // Допустим, ТЗ уже там
// Или напрямую:
ДвоичныеДанныеТЗ = ЗначениеВДвоичныеДанные(ВашаТаблицаЗначений);
ДвоичныеДанныеТЗ.Записать(ПутьКФайлу);

// Загрузка
ДвоичныеДанныеСДиска = Новый ДвоичныеДанные(ПутьКФайлу);
ВашаТаблицаЗначений = ЗначениеИзДвоичныхДанных(ДвоичныеДанныеСДиска);

Этот метод полностью сохраняет динамическую структуру колонок и является наиболее современным стандартом платформы для внутреннего обмена.

Способ 3. Передача через внутренний формат 1С (StringInternal)

Если по каким-то причинам использование XML или двоичных данных невозможно, можно воспользоваться "старым", но надежным методом ЗначениеВСтрокуВнутр. Этот метод переводит объект в специфический текстовый формат 1С, который включает в себя описание всех типов и структуру объекта.

Выполним следующие действия:


// Код для преобразования в текст
ТекстДляФайла = ЗначениеВСтрокуВнутр(ТаблицаЗначений);

// Код для восстановления из текста
НоваяТаблица = ЗначениеИзСтрокиВнутр(ТекстДляФайла);

Преимущество: Метод сохраняет абсолютно всё, включая индексы таблицы значений. Недостаток: Полученный текст не предназначен для чтения человеком или сторонними системами, он пригоден только для обмена между 1С-приложениями.

Способ 4. Сериализация в JSON (универсальный формат)

Как отмечалось в обсуждении, JSON может быть легче XML. Платформа 1С поддерживает автоматическую сериализацию коллекций (в том числе ТЗ) в JSON через СериализаторXDTO. Это полезно, если количество колонок "плавает", и вам не хочется описывать их вручную.

Разберем пример записи:


ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
СериализаторXDTO.ЗаписатьJSON(ЗаписьJSON, ВашаТаблицаЗначений);
СтрокаJSON = ЗаписьJSON.Закрыть();

Однако помните: при чтении JSON в другой базе 1С, типы данных колонок должны быть примитивными (строка, число, дата) или ссылками, GUID которых совпадает в обеих базах. Если в колонках содержатся сложные объекты, при чтении может потребоваться дополнительная обработка.

Проблема "битых" ссылок при передаче ТЗ

Важно понимать фундаментальное ограничение всех вышеперечисленных методов (кроме полноценной Конвертации Данных). Если в вашей таблице значений есть колонка с типом СправочникСсылка.Номенклатура, то при сериализации в XML или JSON передается только Уникальный Идентификатор (GUID) ссылки.

Если в базе-приемнике нет справочника с таким же GUID, вы получите значение "Объект не найден". Если ваша задача — не просто передать "плоскую" таблицу, а создать недостающие элементы справочников в приемнике, вам придется использовать Конвертацию данных 2.1 (КД). В КД можно настроить выгрузку ТЗ как входящих данных для алгоритма, и она сама позаботится о создании ссылочных объектов.

Итоговые рекомендации

Подводя итог нашему анализу, выберем оптимальный метод в зависимости от ситуации:

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

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

← На главную