При интеграции баз данных через веб-сервисы и SOAP-протокол разработчики часто сталкиваются с типовой задачей: метод веб-сервиса возвращает данные, упакованные в ОбъектXDTO. Начинающие программисты нередко сохраняют этот объект на диск в виде отдельного XML-файла через ЗаписьXML, чтобы затем заново прочитать его с помощью ЧтениеXML. Разберем, почему такая операция избыточна и как извлекать информацию напрямую из объекта в оперативной памяти.
Выясним причину, по которой сохранение на диск не требуется. Когда веб-сервис возвращает результат вызова операции, платформа 1С автоматически преобразует полученный SOAP-пакет в древовидную модель объектов XDTO. Переменная, принимающая ответ от WSПрокси, уже содержит в себе десериализованные данные в оперативной памяти.
Объект XDTO ведет себя подобно структуре или объекту платформы: к его элементам можно обращаться через точку по именам, заданным в схеме пакета XDTO. Если схема описывает вложенные массивы элементов (где параметр maxOccurs больше единицы), платформа возвращает коллекцию типа СписокXDTO.
Рассмотрим несколько основных способов извлечения данных из ОбъектXDTO.
Разберем наиболее простой и эффективный способ: прямое обращение к свойствам объекта и использование стандартного цикла для обхода списков. Посмотрим на практический пример обработки ответа веб-сервиса:
Соединение = WSСсылки.ДанныеНоменклатуры.СоздатьWSПрокси(
"http://www.1c.ru/demo/products",
"ДанныеНоменклатуры",
"ДанныеНоменклатурыSoap"
);
Ответ = Соединение.Получить();
// Если Ответ содержит единичные реквизиты, читаем их через точку
Организация = Ответ.Организация;
// Если в ответе содержится коллекция номенклатуры (СписокXDTO), обходим ее циклом
Для Каждого ЭлементНоменклатуры Из Ответ.Номенклатура Цикл
Артикул = ЭлементНоменклатуры.Артикул;
Наименование = ЭлементНоменклатуры.Наименование;
Цена = ЭлементНоменклатуры.Цена;
// Создаем или обновляем элемент справочника в базе данных
СсылкаНаТовар = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", Артикул);
Если СсылкаНаТовар.Пустая() Тогда
НовыйТовар = Справочники.Номенклатура.СоздатьЭлемент();
НовыйТовар.Артикул = Артикул;
НовыйТовар.Наименование = Наименование;
НовыйТовар.Записать();
КонецЕсли;
КонецЦикла;
Для анализа точной структуры объекта воспользуемся точкой останова и окном отладки «Табло» или «Вычислить выражение». Раскрыв свойства переменной Ответ в отладчике, легко увидеть точные наименования всех полей и вложенных списков.
Проанализируем ситуацию, когда веб-сервис передает стандартные ссылочные данные платформы или типы, сериализуемые средствами 1С. В таком случае нет необходимости вручную перебирать каждое свойство. Воспользуемся объектом СериализаторXDTO:
// Восстановление данных 1С из ОбъектаXDTO
Данные1С = СериализаторXDTO.ПрочитатьXDTO(Ответ);
// Если передавался массив структур или таблица значений,
// работаем с ними как со стандартными коллекциями платформы
Для Каждого СтрокаДанных Из Данные1С Цикл
Сообщить(СтрокаДанных.Наименование);
КонецЦикла;
Метод СериализаторXDTO.ПрочитатьXDTO() автоматически транслирует объект схемы XDTO в соответствующий тип платформы 1С: структуру, массив, набор записей или объект информационной базы.
Бывают ситуации, когда данные все же необходимо передать далее в строковом виде или обработать универсальным парсером. Чтобы избежать дисковых операций ввода-вывода, запишем XML напрямую в строковую переменную в оперативной памяти. Для этого используем метод УстановитьСтроку() объекта ЗаписьXML:
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
// Записываем ОбъектXDTO в поток ЗаписьXML
Соединение.ФабрикаXDTO.ЗаписатьXML(Запись, Ответ,,,, НазначениеТипаXML.Явное);
// Получаем готовую XML-строку без сохранения файла на диске
СтрокаXML = Запись.Закрыть();
// При необходимости читаем полученную строку
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрокаXML);
// Дальнейшая потоковая обработка через ЧтениеXML
Разберем по шагам ключевые технические ограничения, о которых следует помнить при реализации обмена:
ОбъектXDTO является мутабельным значением. Его нельзя передавать в качестве параметра между клиентом и сервером в управляемом приложении (например, из процедуры &НаКлиенте в процедуру &НаСервере). Всю цепочку операций — создание прокси, получение данных, обработку свойств и запись в базу — необходимо выполнять строго в серверном контексте (&НаСервере или в общем модуле).