При разработке интеграций и выгрузке электронных документов через Фабрику XDTO разработчики часто сталкиваются с ситуацией, когда метод Фабрика.Тип() не находит тип для корневого или вложенного узла. Разберем по шагам, почему возникает эта сложность и как правильно формировать XML-структуру средствами платформы 1С:Предприятие.
В схемах XSD (например, в форматах ФНС или обмена электронными документами) корневой тег и многие внутренние разделы объявляются напрямую через тег <xs:element> со встроенным анонимным типом <xs:complexType> без атрибута name.
Посмотрим на типовой фрагмент такой схемы:
<xs:element name="Файл">
<xs:complexType>
<xs:sequence>
<xs:element name="СвУчДокОбор">
<xs:complexType>
...
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Метод платформы Фабрика.Тип(URI, ИмяТипа) предназначен исключительно для поиска именованных типов (объявленных как <xs:complexType name="..."> или <xs:simpleType name="...">). Глобальный элемент <xs:element> регистрируется в объекте ПакетXDTO не в коллекции типов, а как СвойствоXDTO. Соответственно, попытка вызвать Фабрика.Тип(URI, "Файл") возвращает значение Неопределено или приводит к ошибке выполнения.
Проанализируем основной и наиболее корректный программный подход. Чтобы создать объект корневого элемента, у которого нет явного имени типа, мы должны извлечь его тип через коллекцию свойств соответствующего пакета XDTO.
Разберем по шагам реализацию этого механизма:
"Файл").Свойство.Тип и передаем его в метод Фабрика.Создать().Свойства родительского типа.Посмотрим на пример кода формирования такой иерархии:
// 1. Инициализация фабрики
ИмяСхемы = КаталогВременныхФайлов() + "scheme_ordersp2.xsd";
МакетСхемы = ЭтотОбъект.ПолучитьМакет("Схема2");
МакетСхемы.Записать(ИмяСхемы);
ФайлыXSD = Новый Массив;
ФайлыXSD.Добавить(ИмяСхемы);
Фабрика = СоздатьФабрикуXDTO(ФайлыXSD);
URI = "http://www.sample-package.org";
// 2. Получение типа корневого элемента "Файл"
Пакет = Фабрика.Пакеты.Получить(URI);
СвойствоФайл = Пакет.Свойства.Получить("Файл");
ТипФайл = СвойствоФайл.Тип;
// 3. Создание корневого объекта XDTO
ОбъектФайл = Фабрика.Создать(ТипФайл);
// 4. Создание вложенного узла "СвУчДокОбор" с анонимным типом
СвойствоСв = ТипФайл.Свойства.Получить("СвУчДокОбор");
ОбъектСв = Фабрика.Создать(СвойствоСв.Тип);
ОбъектФайл.СвУчДокОбор = ОбъектСв;
// 5. Создание следующего уровня вложенности ("Документ")
СвойствоДок = СвойствоСв.Тип.Свойства.Получить("Документ");
ОбъектДок = Фабрика.Создать(СвойствоДок.Тип);
ОбъектСв.Документ = ОбъектДок;
// 6. Заполнение именованных типов и простых свойств
ТипАдрес = Фабрика.Тип(URI, "АдресТип");
ОбъектАдрес = Фабрика.Создать(ТипАдрес);
ОбъектАдрес.АдрИнф = "123";
ОбъектАдрес.АдрРФ = "111";
ОбъектДок.Адрес = ОбъектАдрес;
Рассмотрим подробнее запись сформированных данных в файл. Метод Фабрика.ЗаписатьXML() позволяет автоматически сформировать открывающий и закрывающий тег корневого элемента с необходимым пространством имен без ручной вставки через ЗаписьXML.ЗаписатьНачалоЭлемента().
Синтаксис метода ЗаписатьXML объекта ФабрикаXDTO принимает параметры локального имени узла и его пространства имен:
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\Tmp\ТестФабрикиXDTO.xml", "UTF-8");
Запись.ЗаписатьОбъявлениеXML();
// Передаем ЛокальноеИмя ("Файл") и URI пространства имен третьим и четвертым параметрами
Фабрика.ЗаписатьXML(Запись, ОбъектФайл, "Файл", URI);
Запись.Закрыть();
В ситуациях, когда корневой узел требует специфического набора префиксов или внешнего обрамления, можно использовать пошаговую запись:
ЗаписьXML.ЗаписатьНачалоЭлемента("Файл", URI).Фабрика.ЗаписатьXML().ЗаписьXML.ЗаписатьКонецЭлемента().Посмотрим на пример реализации:
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\Tmp\ТестФабрикиXDTO.xml", "UTF-8");
Запись.ЗаписатьОбъявлениеXML();
Запись.ЗаписатьНачалоЭлемента("Файл", URI);
// Записываем внутренние блоки
Фабрика.ЗаписатьXML(Запись, ОбъектФайл.СвУчДокОбор, "СвУчДокОбор", URI);
Запись.ЗаписатьКонецЭлемента();
Запись.Закрыть();
Перед формированием итогового XML-файла рекомендуется выполнить валидацию заполненного объекта. Для этого у полученного ОбъектXDTO вызывается метод Проверить():
Попытка
ОбъектФайл.Проверить();
Исключение
Сообщить("Ошибка валидации структуры XDTO: " + ОписаниеОшибки());
КонецПопытки;
Метод Проверить() проверяет наличие обязательных полей, ограничения длины строк, форматы дат и чисел согласно правилам подключенной схемы XSD.