Почему СериализаторXDTO не читает XML и ВозможностьЧтенияXML возвращает Ложь

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

При интеграции систем 1С с внешними источниками разработчики часто сталкиваются с механизмами XDTO. Типичный сценарий: у нас есть файл XML и схема XSD, описывающая его структуру. Мы пытаемся прочитать файл через СериализаторXDTO, но метод ВозможностьЧтенияXML(ЧтениеХМЛ) упорно возвращает Ложь, хотя при использовании метода ФабрикаXDTO.ПрочитатьXML() данные считываются без проблем. В этой статье мы подробно разберем, почему возникает такая ситуация, проанализируем разницу в назначении этих механизмов и научимся правильно писать код для импорта данных.

В чем разница между Фабрикой XDTO и Сериализатором XDTO?

Для начала выясним главную архитектурную причину проблемы. Несмотря на то что оба объекта работают с технологией XDTO, они решают абсолютно разные задачи:

  1. Фабрика XDTO (низкий уровень данных). Она работает с абстрактной структурой данных. Её задача — преобразовать текстовый XML-файл в дерево объектов типа ОбъектXDTO на основе предоставленной схемы XSD. Фабрика абсолютно ничего не знает о метаданных вашей информационной базы (справочниках, документах, регистрах). Ей не важно, существуют ли такие объекты в конфигурации 1С.
  2. Сериализатор XDTO (высокий уровень прикладных объектов). Этот инструмент создан специально для того, чтобы превращать XML-данные напрямую в конкретные прикладные объекты 1С:Предприятия (например, ДокументОбъект.РасходТовара или СправочникОбъект.Номенклатура). Он осуществляет двустороннее отображение между типами XDTO и типами встроенного языка 1С.

Если вы создаете изолированную фабрику динамически из файла схемы с помощью метода СоздатьФабрикуXDTO(ПутьКФабрике), то связанный с ней СериализаторXDTO не будет иметь связей с метаданными конфигурации. Он просто «не понимает», в какой именно справочник или документ 1С нужно преобразовать прочитанную ветку XML. Именно поэтому метод ВозможностьЧтенияXML() всегда будет возвращать Ложь.

Анализ программной ошибки: Смешивание фабрик (Factory Mismatch)

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


ФабрикаПолучателя = СоздатьФабрикуXDTO(ПутьКФабрике);
ТекСериализатор = Новый СериализаторXDTO(ФабрикаПолучателя);

ЧтениеХМЛ = Новый ЧтениеXML;
ЧтениеХМЛ.ОткрытьФайл(ИмяФайлаЗагрузки);
ЧтениеХМЛ.Прочитать(); // Чтение корневого узла

Пока ТекСериализатор.ВозможностьЧтенияXML(ЧтениеХМЛ) Цикл
    Тип_РасходТовара = ФабрикаXDTO.Тип("http://www.example.org", "РасходТовара"); 
    ТекОбъект = ТекСериализатор.ПрочитатьXML(ЧтениеХМЛ, Тип_РасходТовара);
КонецЦикла;

В этом коде кроется критическая ошибка совместимости типов. Обратите внимание:

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

Проблема пространств имен (Namespace URI)

Для успешной десериализации объекта в прикладной тип 1С структура XML-файла должна строго соответствовать пространству имен типов платформы 1С. По умолчанию типы конфигурации сопоставляются с пространством имен:

http://v8.1c.ru/8.1/data/enterprise/current-config

Если ваш XML-файл содержит произвольные пространства имен или не содержит их вовсе, то СериализаторXDTO не сможет автоматически сопоставить узел XML с объектом базы данных 1С, поскольку он ищет системные типы вида DocumentObject.РасходТовара. Для произвольных XML-схем использование сериализатора теряет смысл.

---

Вариант А. Правильное чтение через Фабрику XDTO с ручным заполнением

Если вы загружаете данные из сторонней системы, структура которой не совпадает один в один с метаданными 1С, забудьте про СериализаторXDTO. Самым надежным и правильным способом является чтение XML в универсальный ОбъектXDTO с последующим созданием документа вручную.

Рассмотрим по шагам этот алгоритм:


// 1. Инициализируем чтение файла
ЧтениеХМЛ = Новый ЧтениеXML;
ЧтениеХМЛ.ОткрытьФайл(ИмяФайлаЗагрузки);

// 2. Создаем фабрику на основе схемы XSD
ФабрикаПолучателя = СоздатьФабрикуXDTO(ПутьКФабрике);
Тип_РасходТовара = ФабрикаПолучателя.Тип("http://www.example.org", "РасходТовара");

// 3. Читаем данные XML напрямую в объект XDTO
ДанныеXDTO = ФабрикаПолучателя.ПрочитатьXML(ЧтениеХМЛ, Тип_РасходТовара);

// 4. Переносим данные из объекта XDTO в реальный документ 1С
НовыйДокумент = Документы.РасходТовара.СоздатьДокумент();
НовыйДокумент.Дата = ДанныеXDTO.Дата;
НовыйДокумент.Номер = ДанныеXDTO.Номер;

// Если имена реквизитов совпадают, можно использовать автоматическое заполнение:
ЗаполнитьЗначенияСвойств(НовыйДокумент, ДанныеXDTO);

// Заполняем табличную часть, если она есть
Для Каждого СтрокаТовара Из ДанныеXDTO.Товары Цикл
    НоваяСтрока = НовыйДокумент.Товары.Добавить();
    НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию(СтрокаТовара.Наименование);
    НоваяСтрока.Количество = СтрокаТовара.Количество;
    НоваяСтрока.Цена = СтрокаТовара.Цена;
КонецЦикла;

НовыйДокумент.Записать();
ЧтениеХМЛ.Закрыть();

---

Вариант Б. Связывание кастомной фабрики с типами конфигурации

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

Проанализируем, как правильно инициализировать такую фабрику:


// 1. Помещаем путь к вашей схеме в массив
МассивСхем = Новый Массив;
МассивСхем.Добавить(ПутьКФабрике);

// 2. Создаем фабрику, объединяя вашу схему с пакетами глобальной фабрики конфигурации
ФабрикаПолучателя = СоздатьФабрикуXDTO(МассивСхем, ФабрикаXDTO.Пакеты);

// 3. Создаем сериализатор на базе объединенной фабрики
ТекСериализатор = Новый СериализаторXDTO(ФабрикаПолучателя);

ЧтениеХМЛ = Новый ЧтениеXML;
ЧтениеХМЛ.ОткрытьФайл(ИмяФайлаЗагрузки);

// Теперь важно получить тип именно из НАШЕЙ новой соединенной фабрики!
Тип_РасходТовара = ФабрикаПолучателя.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "DocumentObject.РасходТовара");

Если ТекСериализатор.ВозможностьЧтенияXML(ЧтениеХМЛ) Тогда
    // Объект будет создан автоматически с правильным типом ДокументОбъект.РасходТовара
    СозданныйДокумент = ТекСериализатор.ПрочитатьXML(ЧтениеХМЛ, Тип_РасходТовара);
    СозданныйДокумент.Записать();
КонецЕсли;

ЧтениеХМЛ.Закрыть();

Важное примечание: Чтобы этот вариант сработал, ваш XML-файл должен быть сформирован по правилам XML-сериализации 1С. В структуре XML должны присутствовать пространства имен платформы 1С, а имена узлов должны точно соответствовать именам объектов метаданных с префиксами видов объектов (например, DocumentObject.РасходТовара, а не просто РасходТовара).

← На главную