Как исправить ошибку преобразования данных XDTO при использовании xsi:type и правильно передать данные в веб-сервис?

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

При интеграции 1С с внешними системами через веб-сервисы разработчики часто сталкиваются с необходимостью формирования сложных XML-структур. Одной из наиболее коварных ошибок является "Ошибка преобразования данных XDTO: Чтение объекта типа", которая возникает при попытке прочитать вручную сформированный XML-документ, содержащий атрибут xsi:type. Проанализируем, почему это происходит, и разберем наиболее эффективные способы решения этой задачи.

Почему возникает ошибка при добавлении xsi:type?

Рассмотрим ситуацию: разработчик формирует XML-строку вручную с помощью объекта ЗаписьXML. Для того чтобы веб-сервис на стороне получателя корректно распознал тип данных, в XML добавляется атрибут xsi:type="TicketSeats". Однако при попытке преобразовать эту строку в объект XDTO методом ФабрикаXDTO.ПрочитатьXML() система выдает фатальную ошибку.

Выясним причину такого поведения платформы. Когда в XML-узле присутствует атрибут xsi:type, механизм XDTO в 1С перестает воспринимать структуру как произвольный набор данных. Он пытается выполнить строгую валидацию содержимого в соответствии с описанием типа, найденным в пакетах XDTO конфигурации. Если в метаданных вашей базы (или в подключенных WS-ссылках) уже существует пакет, содержащий тип с таким именем, 1С начинает проверять XML на полное соответствие схеме этого пакета.

Любое несовпадение — лишний пробел в пространстве имен, неверный порядок элементов или отсутствие обязательного свойства — приводит к ошибке "Проверка дополнительного свойства: форма: Элемент". Это означает, что парсер нашел в XML данные, которые не описаны в официальной схеме типа TicketSeats.

Конфликт контекстов: Глобальная фабрика против Фабрики WS-ссылки

Важно понимать, что в 1С существует разделение контекстов. Существует Глобальная фабрика XDTO (доступная через свойство ФабрикаXDTO), которая содержит типы всех пакетов, включенных в состав метаданных конфигурации. Также существуют локальные фабрики, создаваемые динамически при подключении к веб-сервису через WS-ссылку.

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

Отказ от ручного формирования XML в пользу Фабрики XDTO

Вместо того чтобы "изобретать велосипед" и вручную записывать теги через ЗаписьXML, рассмотрим правильный и надежный способ создания объектов. Профессиональный подход заключается в использовании методов фабрики для создания экземпляров типов данных. Это гарантирует, что структура XML будет сформирована идеально с точки зрения стандартов XDTO.

Разберем по шагам, как это реализовать, если у вас есть WS-ссылка:

  1. Получим прокси-объект веб-сервиса.
  2. Обратимся к фабрике XDTO, которая встроена в этот прокси-объект. Она содержит именно те типы, которые ожидает сервис.
  3. Создадим объекты нужных типов методом Создать().
  4. Заполним свойства объекта.

Посмотрим на пример правильного кода:


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

// 2. Получаем типы из пакетов, описанных в WSDL
ТипПараметраSeats = Фабрика.Тип("http://www.example.com/namespace", "TicketSeats");
ТипПараметраSeat = Фабрика.Тип("http://www.example.com/namespace", "TicketSeat");

// 3. Создаем объекты XDTO
ОбъектSeats = Фабрика.Создать(ТипПараметраSeats);
ОбъектSeat = Фабрика.Создать(ТипПараметраSeat);

// 4. Заполняем данные
ОбъектSeat.SeatNum = "42";
// Если свойство является списком (maxOccurs > 1), используем метод Добавить()
ОбъектSeats.Elements.Добавить(ОбъектSeat);

// 5. Вызываем метод сервиса, передавая готовый объект
Прокси.AddTickets(ОбъектSeats);

Проблема списковых свойств (MaxOccurs > 1)

Часто при ручном формировании XML возникает ошибка "Несоответствие типов XDTO: Свойство является списковым". Это происходит потому, что в схеме веб-сервиса элемент (например, Elements) помечен как коллекция. При использовании объектов XDTO вы не можете просто присвоить значение такому свойству через знак равенства. Вы обязаны использовать метод Добавить(), так как свойство инициализируется как пустой список (объект СписокXDTO).

Рассмотрим подробнее: если вы напишете ОбъектSeats.Elements = ОбъектSeat, 1С выдаст ошибку. Правильный путь — только добавление в коллекцию, даже если вы передаете всего один элемент. Это автоматически сформирует правильную последовательность одинаковых тегов в итоговом XML-пакете.

Рекомендации по отладке и локализации проблем

Если вы все же вынуждены работать с XML вручную или через глобальную фабрику, проанализируем несколько советов по поиску причин падения кода (поможет инструмент логирования и анализа HTTP-запросов):

  1. Сверка пространств имен (Namespaces): Убедитесь, что URI пространства имен (второй параметр в ЗаписатьНачалоЭлемента) совпадает символ в символ с тем, что ожидается в схеме. Отсутствие слэша в конце или лишний пробел сделают типы абсолютно разными для системы.
  2. Проверка через сериализатор: Чтобы понять, какой именно XML ожидает 1С, попробуйте создать объект через фабрику (даже с пустыми данными) и выгрузить его в файл методом ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ВашОбъект). Сравните полученный результат с вашим ручным кодом. Вы сразу увидите различия в префиксах и атрибутах xsi:type.
  3. Использование явного указания типа: Вместо поиска типа по строковому имени, старайтесь получать тип через пространство имен. Это исключит ситуацию, когда 1С выбирает "похожий" тип из другого пакета. Используйте ФабрикаXDTO.Тип(URIПространстваИмен, ИмяТипа).

Таким образом, использование встроенных механизмов фабрики XDTO не только избавляет от ошибок преобразования данных, но и делает код более устойчивым к изменениям в структуре веб-сервиса. Помните, что атрибут xsi:type — это мощный инструмент строгой типизации, и 1С требует от разработчика безукоризненного следования схеме при его использовании.

← На главную