Как выгрузить XML-элемент без именованного типа с помощью Фабрики XDTO в 1С?

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

При разработке интеграций и выгрузке электронных документов через Фабрику 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, "Файл") возвращает значение Неопределено или приводит к ошибке выполнения.

Способ 1. Получение анонимных типов через свойства пакета XDTO

Проанализируем основной и наиболее корректный программный подход. Чтобы создать объект корневого элемента, у которого нет явного имени типа, мы должны извлечь его тип через коллекцию свойств соответствующего пакета XDTO.

Разберем по шагам реализацию этого механизма:

  1. Получаем объект пакета XDTO по целевому пространству имен (URI).
  2. Находим глобальное свойство схемы с нужным именем тега (например, "Файл").
  3. Берем тип этого свойства через Свойство.Тип и передаем его в метод Фабрика.Создать().
  4. Аналогичным образом для вложенных неименованных узлов получаем типы из коллекции Свойства родительского типа.

Посмотрим на пример кода формирования такой иерархии:


// 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";
ОбъектДок.Адрес = ОбъектАдрес;

Способ 2. Корректная запись XML с указанием имени корневого тега

Рассмотрим подробнее запись сформированных данных в файл. Метод Фабрика.ЗаписатьXML() позволяет автоматически сформировать открывающий и закрывающий тег корневого элемента с необходимым пространством имен без ручной вставки через ЗаписьXML.ЗаписатьНачалоЭлемента().

Синтаксис метода ЗаписатьXML объекта ФабрикаXDTO принимает параметры локального имени узла и его пространства имен:


Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\Tmp\ТестФабрикиXDTO.xml", "UTF-8");
Запись.ЗаписатьОбъявлениеXML();

// Передаем ЛокальноеИмя ("Файл") и URI пространства имен третьим и четвертым параметрами
Фабрика.ЗаписатьXML(Запись, ОбъектФайл, "Файл", URI);

Запись.Закрыть();

Способ 3. Комбинированная ручная запись корневого узла

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

  1. Открываем корневой тег вручную через ЗаписьXML.ЗаписатьНачалоЭлемента("Файл", URI).
  2. Записываем все вложенные структуры через Фабрика.ЗаписатьXML().
  3. Закрываем узел методом ЗаписьXML.ЗаписатьКонецЭлемента().

Посмотрим на пример реализации:


Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\Tmp\ТестФабрикиXDTO.xml", "UTF-8");
Запись.ЗаписатьОбъявлениеXML();

Запись.ЗаписатьНачалоЭлемента("Файл", URI);

// Записываем внутренние блоки
Фабрика.ЗаписатьXML(Запись, ОбъектФайл.СвУчДокОбор, "СвУчДокОбор", URI);

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

Проверка корректности структуры перед выгрузкой

Перед формированием итогового XML-файла рекомендуется выполнить валидацию заполненного объекта. Для этого у полученного ОбъектXDTO вызывается метод Проверить():


Попытка
    ОбъектФайл.Проверить();
Исключение
    Сообщить("Ошибка валидации структуры XDTO: " + ОписаниеОшибки());
КонецПопытки;

Метод Проверить() проверяет наличие обязательных полей, ограничения длины строк, форматы дат и чисел согласно правилам подключенной схемы XSD.

← На главную