При интеграции 1С с внешними системами через веб-сервисы разработчики часто сталкиваются с необходимостью формирования сложных XML-структур. Одной из наиболее коварных ошибок является "Ошибка преобразования данных XDTO: Чтение объекта типа", которая возникает при попытке прочитать вручную сформированный XML-документ, содержащий атрибут xsi:type. Проанализируем, почему это происходит, и разберем наиболее эффективные способы решения этой задачи.
Рассмотрим ситуацию: разработчик формирует XML-строку вручную с помощью объекта ЗаписьXML. Для того чтобы веб-сервис на стороне получателя корректно распознал тип данных, в XML добавляется атрибут xsi:type="TicketSeats". Однако при попытке преобразовать эту строку в объект XDTO методом ФабрикаXDTO.ПрочитатьXML() система выдает фатальную ошибку.
Выясним причину такого поведения платформы. Когда в XML-узле присутствует атрибут xsi:type, механизм XDTO в 1С перестает воспринимать структуру как произвольный набор данных. Он пытается выполнить строгую валидацию содержимого в соответствии с описанием типа, найденным в пакетах XDTO конфигурации. Если в метаданных вашей базы (или в подключенных WS-ссылках) уже существует пакет, содержащий тип с таким именем, 1С начинает проверять XML на полное соответствие схеме этого пакета.
Любое несовпадение — лишний пробел в пространстве имен, неверный порядок элементов или отсутствие обязательного свойства — приводит к ошибке "Проверка дополнительного свойства: форма: Элемент". Это означает, что парсер нашел в XML данные, которые не описаны в официальной схеме типа TicketSeats.
Важно понимать, что в 1С существует разделение контекстов. Существует Глобальная фабрика XDTO (доступная через свойство ФабрикаXDTO), которая содержит типы всех пакетов, включенных в состав метаданных конфигурации. Также существуют локальные фабрики, создаваемые динамически при подключении к веб-сервису через WS-ссылку.
Проанализируем типичную ошибку: если вы используете глобальную фабрику для чтения XML, который предназначен для конкретного веб-сервиса, может возникнуть конфликт имен. Если в конфигурации (например, в отраслевом решении типа "Управление автотранспортом") уже есть тип с именем TicketSeats, 1С принудительно применит его правила валидации, которые могут отличаться от правил внешнего веб-сервиса. Именно поэтому в одних базах код может работать, а в других — выдавать ошибку.
Вместо того чтобы "изобретать велосипед" и вручную записывать теги через ЗаписьXML, рассмотрим правильный и надежный способ создания объектов. Профессиональный подход заключается в использовании методов фабрики для создания экземпляров типов данных. Это гарантирует, что структура XML будет сформирована идеально с точки зрения стандартов XDTO.
Разберем по шагам, как это реализовать, если у вас есть WS-ссылка:
Создать().Посмотрим на пример правильного кода:
// 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);
Часто при ручном формировании XML возникает ошибка "Несоответствие типов XDTO: Свойство является списковым". Это происходит потому, что в схеме веб-сервиса элемент (например, Elements) помечен как коллекция. При использовании объектов XDTO вы не можете просто присвоить значение такому свойству через знак равенства. Вы обязаны использовать метод Добавить(), так как свойство инициализируется как пустой список (объект СписокXDTO).
Рассмотрим подробнее: если вы напишете ОбъектSeats.Elements = ОбъектSeat, 1С выдаст ошибку. Правильный путь — только добавление в коллекцию, даже если вы передаете всего один элемент. Это автоматически сформирует правильную последовательность одинаковых тегов в итоговом XML-пакете.
Если вы все же вынуждены работать с XML вручную или через глобальную фабрику, проанализируем несколько советов по поиску причин падения кода (поможет инструмент логирования и анализа HTTP-запросов):
ЗаписатьНачалоЭлемента) совпадает символ в символ с тем, что ожидается в схеме. Отсутствие слэша в конце или лишний пробел сделают типы абсолютно разными для системы.ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ВашОбъект). Сравните полученный результат с вашим ручным кодом. Вы сразу увидите различия в префиксах и атрибутах xsi:type.ФабрикаXDTO.Тип(URIПространстваИмен, ИмяТипа).Таким образом, использование встроенных механизмов фабрики XDTO не только избавляет от ошибок преобразования данных, но и делает код более устойчивым к изменениям в структуре веб-сервиса. Помните, что атрибут xsi:type — это мощный инструмент строгой типизации, и 1С требует от разработчика безукоризненного следования схеме при его использовании.