Как выгрузить и загрузить данные через XML между базами 1С 8.2 и 8.3?

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

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

Проблема автоматической сериализации XDTO

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

Проанализируем ситуацию: при автоматической записи 1С добавляет технические описания типов и пространств имен. Чтобы корректно прочитать такой файл, на стороне приемника необходимо использовать СериализаторXDTO.ПрочитатьXML() с обязательным указанием ожидаемого типа. Если же структура данных «нетиповая», лучшим решением будет ручное формирование XML-структуры.

Решение 1: Ручное формирование XML через атрибуты

Рассмотрим наиболее гибкий способ, который позволяет полностью контролировать структуру файла. Мы будем перебирать строки таблицы значений и записывать каждую колонку как атрибут узла XML. Это обеспечит высокую скорость работы и простоту отладки.

Пример кода выгрузки на стороне источника (БП 2.0):


// Создаем временный файл для записи
ВременныйФайл = ПолучитьИмяВременногоФайла("xml");
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ВременныйФайл, "UTF-8");
ЗаписьXML.ЗаписатьОбъявлениеXML();

ЗаписьXML.ЗаписатьНачалоЭлемента("Root"); // Корневой элемент

i = 1;
Для Каждого Стр Из ТаблицаРезультата Цикл
    // Формируем имя узла для строки
    ЗаписьXML.ЗаписатьНачалоЭлемента("row" + Формат(i, "ЧГ=0"));
    
    // Записываем данные через атрибуты
    ЗаписьXML.ЗаписатьАтрибут("Сотрудник", Строка(Стр.Сотрудник));
    ЗаписьXML.ЗаписатьАтрибут("Подразделение", Строка(Стр.Подразделение));
    ЗаписьXML.ЗаписатьАтрибут("Сумма", Строка(Стр.Сумма));
    
    // Если нужно передать ссылку, лучше передавать её УникальныйИдентификатор
    ЗаписьXML.ЗаписатьАтрибут("Сотрудник_GUID", Строка(Стр.Сотрудник.УникальныйИдентификатор()));
    
    ЗаписьXML.ЗаписатьКонецЭлемента(); // Закрываем узел строки
    i = i + 1;
КонецЦикла;

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

Обратим внимание на важный момент: использование ЗаписьXML.ЗаписатьАтрибут позволяет получить очень компактный файл, который легко читается парсером. Мы рекомендуем передавать не только строковое представление ссылочных типов, но и их УникальныйИдентификатор для точного поиска в базе-приемнике.

Решение 2: Чтение и парсинг XML на стороне приемника (БП 3.0)

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

Алгоритм загрузки данных:


&НаСервере
Процедура ЗагрузитьДанныеИзXML(ПутьКФайлу)
    Парсер = Новый ЧтениеXML;
    Парсер.ОткрытьФайл(ПутьКФайлу);
    
    Пока Парсер.Прочитать() Цикл
        // Ищем начало элемента, имя которого содержит "row"
        Если Парсер.ТипУзла = ТипУзлаXML.НачалоЭлемента И СтрНайти(Парсер.Имя, "row") > 0 Тогда
            
            // Получаем данные из атрибутов текущего узла
            ТекСотрудникНаименование = Парсер.ЗначениеАтрибута("Сотрудник");
            ТекСумма = Число(Парсер.ЗначениеАтрибута("Сумма"));
            ТекGUID = Парсер.ЗначениеАтрибута("Сотрудник_GUID");
            
            // Здесь выполняем логику поиска объекта в базе 3.0
            // Например, поиск по GUID:
            СсылкаСотрудник = Справочники.Сотрудники.ПолучитьСсылку(Новый УникальныйИдентификатор(ТекGUID));
            
            Если СсылкаСотрудник.ПолучитьОбъект() = Неопределено Тогда
                 // Если по GUID не нашли, ищем по наименованию
                 СсылкаСотрудник = Справочники.Сотрудники.НайтиПоНаименованию(ТекСотрудникНаименование);
            КонецЕсли;
            
            // Далее создаем или заполняем документ
            // ...
        КонецЕсли;
    КонецЦикла;
    
    Парсер.Закрыть();
КонецПроцедуры

Выясним причину, почему в примере используется СтрНайти(Парсер.Имя, "row"). Это позволяет игнорировать корневые элементы и технические узлы, фокусируясь только на строках данных. Метод ЗначениеАтрибута является наиболее эффективным способом извлечения данных при такой структуре XML.

Важные нюансы работы со ссылочными данными

При обмене между разными конфигурациями (2.0 и 3.0) критически важно понимать, что ссылки в одной базе не равны ссылкам в другой. Передавая просто «Наименование», вы рискуете создать дубли или не найти объект, если в новой базе он называется иначе.

Сформулируем правила надежного обмена:

  1. Всегда выгружайте УникальныйИдентификатор (GUID).
  2. Для объектов учета (Контрагенты, Номенклатура) передавайте дополнительные поля поиска: ИНН, КПП, Артикул или Код.
  3. На стороне приемника реализуйте каскадный поиск: сначала по GUID, затем по ключевым реквизитам.
  4. Используйте ЧтениеXML.ИгнорироватьПустыеУзлы = Истина, чтобы лишние переносы строк не замедляли работу парсера.

Альтернативный подход: Конвертация данных 2.0

Если задача переноса данных регулярная или объектов много, программисту стоит рассмотреть использование конфигурации «Конвертация данных 2.0». Этот инструмент позволяет:

Хотя для одного документа написание правил в КД может показаться избыточным, для комплексного переноса это единственный надежный промышленный стандарт.

Использование формата JSON как современной альтернативы

Проанализируем ситуацию: если вы работаете на платформе 8.3 (а БП 3.0 работает именно на ней), формат JSON зачастую предпочтительнее XML. Он более компактен и нативно поддерживает структуры 1С. Функции ЗаписатьJSON и ПрочитатьJSON позволяют передать таблицу значений практически одной командой, при этом работа с типами данных там реализована проще.

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

← На главную