Как правильно импортировать XSD-схему в XDTO-пакет и прочитать XML в 1С?

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

Работа с механизмом XDTO (XML Data Transfer Objects) в 1С часто вызывает трудности у разработчиков, особенно на этапе импорта сторонних XSD-схем. Одной из самых распространенных проблем является ситуация, когда после импорта схемы ФабрикаXDTO.Тип() возвращает Неопределено, а при попытке прочитать XML возникают ошибки соответствия структуры. В этой статье мы подробно разберем, как избежать этих ловушек, правильно настроить пространства имен и обеспечить стабильную работу с данными.

Разбираемся в понятиях: Именованные типы против Глобальных элементов

Первая причина, по которой разработчики получают Неопределено при попытке получить тип, кроется в самой структуре XSD. Рассмотрим типичную ситуацию: в схеме определен элемент message, внутри которого сразу описан xs:complexType без имени. В терминах XSD это называется анонимным типом.

Проанализируем ситуацию: в платформе 1С метод ФабрикаXDTO.Тип(URI, "Имя") ищет именно именованный тип (complexType или simpleType), определенный в корне схемы. Если же в схеме определен только глобальный элемент (element), он попадает в категорию Свойства пакета XDTO, а не в типы.

Чтобы иметь возможность получить тип напрямую через фабрику, схему следует проектировать следующим образом:


<xs:complexType name="MessageType">
    <xs:sequence>
        <xs:element name="order" type="tns:OrderType" maxOccurs="unbounded"/>
    </xs:sequence>
</xs:complexType>

<xs:element name="message" type="tns:MessageType"/>

Если вы не можете изменить входящую схему, необходимо использовать альтернативный способ получения типа через КорневыеСвойства пакета. Рассмотрим это подробнее в разделе реализации.

Критическая важность пространств имен (Namespaces)

Пространства имен — это фундамент XML. Без четкого соответствия targetNamespace в схеме и xmlns в XML-документе, фабрика 1С не сможет сопоставить данные. Разберем ключевые атрибуты тега xs:schema:

  1. targetNamespace — определяет «прописку» всех элементов, описанных в этой схеме.
  2. elementFormDefault="qualified" — это означает, что все дочерние элементы в XML (не только корневой) должны явно или неявно принадлежать этому пространству имен.

Если в вашей схеме указан targetNamespace="http://my-site.ru/import", то во входящем XML-файле корневой тег обязательно должен содержать объявление этого пространства:


<message xmlns="http://my-site.ru/import">
    <order>...</order>
</message>

Если сторонний сервис присылает «голый» XML без xmlns, 1С выдаст ошибку «Структура объекта не соответствует типу». В таких случаях нам придется программно модифицировать строку XML перед чтением.

Пошаговое решение: Импорт и чтение данных

Рассмотрим алгоритм действий, который гарантирует корректное чтение данных даже в сложных случаях.

Шаг 1. Импорт XSD в конфигурацию

Создайте новый Пакет XDTO в дереве конфигурации. Нажмите правой кнопкой мыши и выберите «Импорт схемы XML». Убедитесь, что после импорта заполнилось поле URI пространства имен. Если дерево объектов пакета пустое или содержит только свойства без типов — проверьте синтаксис XSD, особенно наличие префиксов xs: для стандартных типов (string, decimal). Для такой задачи подойдёт инструмент для конвертации схемы XSD в модель XDTO.

Шаг 2. Программное получение типа корневого элемента

Поскольку наш message является свойством (элементом), а не типом, мы не можем вызвать ФабрикаXDTO.Тип(). Нам нужно обратиться к коллекции КорневыеСвойства. Рассмотрим пример кода:


// Определяем URI, который указан в пакете XDTO в конфигурации
ПространствоИмен = "http://losthost.online/plugin/instock";

// Получаем пакет из фабрики
Пакет = ФабрикаXDTO.Пакеты.Получить(ПространствоИмен);

// Находим описание корневого элемента "message"
СвойствоСообщения = Пакет.КорневыеСвойства.Получить("message");

// Из свойства извлекаем его тип (тот самый анонимный complexType)
ТипСообщения = СвойствоСообщения.Тип;

Шаг 3. Подготовка и чтение XML-данных

Если входящий XML не содержит объявлений пространств имен, мы можем добавить их вручную. Самый простой (хотя и «грубый») способ — замена строки. Более надежный — использование ПостроительDOM.

Разберем пример с программной коррекцией XML:


// Входящий текст XML без неймспейсов
ТекстXML = "<message><order>...</order></message>";

// Добавляем xmlns программно, если его нет
Если СтрНайти(ТекстXML, "xmlns") = 0 Тогда
    ТекстXML = СтрЗаменить(ТекстXML, "<message", "<message xmlns=""" + ПространствоИмен + """");
КонецЕсли;

Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(ТекстXML);

Попытка
    // Читаем объект, явно передавая полученный ранее тип
    ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(Чтение, ТипСообщения);
    
    // Теперь мы можем работать с данными
    Для Каждого ТекущийЗаказ Из ОбъектXDTO.order Цикл
        // Обработка заказа
    КонецЦикла;
Исключение
    Сообщить("Ошибка чтения XDTO: " + ОписаниеОшибки());
КонецПопытки;

Обработка списков и проблема «Одиночного элемента»

Часто программисты сталкиваются с тем, что код Для Каждого... падает с ошибкой, если в XML пришел только один элемент (например, один order), и 1С восприняла его как ОбъектXDTO, а не как СписокXDTO.

Важное преимущество использования типов при чтении: Если вы передаете ТипСообщения в метод ПрочитатьXML(), платформа 1С заранее знает структуру из схемы XSD. Если в схеме указано maxOccurs="unbounded", то свойство всегда будет списком, даже если в XML передан всего один тег. Это избавляет от необходимости писать проверки ТипЗнч(Объект.Свойство) = Тип("СписокXDTO").

Рекомендации по работе с ФабрикойXDTO

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

Таким образом, успех импорта XSD зависит от трех факторов: точного указания targetNamespace, правильного извлечения типа из корневых свойств и обеспечения наличия xmlns во входящем XML-документе. Следуя этим правилам, вы сможете интегрировать 1С с любой внешней системой, использующей XML-обмен.

← На главную