При попытке добавить сторонний веб-сервис в конфигурацию через объект метаданных WS-ссылка или при программном создании объекта WSОпределения разработчики часто сталкиваются с ошибкой: «Схема должна иметь атрибут targetNamespace». Разберем причины возникновения этой ситуации и рассмотрим проверенные способы интеграции со сторонним сервисом.
Платформа 1С:Предприятие при разборе WSDL-описаний и связанных с ними XSD-схем строго следует спецификациям стандарта WS-I Basic Profile. В соответствии с этими требованиями, каждая схема данных должна иметь явно заданное целевое пространство имен (атрибут targetNamespace).
Проанализируем структуру проблемного WSDL-описания. В сервисах, разработанных на платформах .NET (WCF) или Java, часто встречаются директивы импорта схем следующего вида:
<xsd:import schemaLocation="http://адрес_сервиса/Service.svc?xsd=xsd5"/>
В приведенном примере в теге xsd:import указан только адрес загрузки schemaLocation, но отсутствует обязательный для 1С атрибут namespace, либо сама загружаемая по ссылке схема не содержит атрибута targetNamespace в корневом узле xs:schema. Другие клиенты могут автоматически наследовать пространство имен родительского документа, однако встроенный парсер 1С прерывает процесс импорта и выдает критическую ошибку.
Поскольку веб-сервис является внешним и у нас нет прямого доступа к его исходному коду, рассмотрим альтернативные варианты решения проблемы.
Если нам не требуется поддержка статической типизации XDTO, наиболее быстрым и независимым решением будет работа с SOAP-сервисом как с обычным REST/HTTP-эндпоинтом. Для этого сформируем XML-пакет (SOAP Envelope) вручную и передадим его методом POST.
Разберем по шагам реализацию запроса:
HTTPСоединение с указанием адреса сервера и порта.HTTPЗапрос, указав путь к веб-сервису.Content-Type (для SOAP 1.1 используется text/xml; charset=utf-8) и заголовок SOAPAction (название вызываемой операции).ОтправитьДляОбработкиAsync или ОтправитьДляОбработки и выполним разбор XML-ответа.Посмотрим на пример программного кода:
// 1. Указываем параметры подключения
Сервер = "new1.seldon2010.ru";
Порт = 8083;
Ресурс = "/SeldonApiService.svc";
Соединение = Новый HTTPСоединение(Сервер, Порт, , , , 30);
// 2. Формируем тело SOAP-конверта
ТекстSOAP =
"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:tem=""http://tempuri.org/"">
| <soapenv:Header/>
| <soapenv:Body>
| <tem:GetData>
| <tem:value>123</tem:value>
| </tem:GetData>
| </soapenv:Body>
|</soapenv:Envelope>";
// 3. Настраиваем заголовки HTTP-запроса
Запрос = Новый HTTPЗапрос(Ресурс);
Запрос.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
Запрос.Заголовки.Вставить("SOAPAction", "http://tempuri.org/ISeldonApiService/GetData");
Запрос.УстановитьТелоИзСтроки(ТекстSOAP, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// 4. Отправляем запрос и получаем ответ
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния = 200 Тогда
СтрокаОтвета = Ответ.ПолучитьТелоКакСтроку();
// 5. Разбираем результат с помощью ЧтениеXML
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрокаОтвета);
Построитель = Новый ПостроительDOM;
ДокументDOM = Построитель.Прочитать(Чтение);
// Получаем нужные узлы через DOM или XPath
Элементы = ДокументDOM.ПолучитьЭлементыПоИмени("GetDataResult");
Если Элементы.Количество() > 0 Тогда
ЗначениеРезультата = Элементы[0].ТекстовоеСодержимое;
КонецЕсли;
Иначе
ВызватьИсключение "Ошибка сервиса: " + Формат(Ответ.КодСостояния, "ЧГ=0") + " " + Ответ.ПолучитьТелоКакСтроку();
КонецЕсли;
Если мы хотим сохранить удобство работы с типизированными объектами XDTO и вызовами методов через WSПрокси, исправим схемы на стороне клиента.
Рассмотрим порядок действий:
schemaLocation) на локальный диск.<xs:schema> отсутствует targetNamespace, дописываем его вручную, например: targetNamespace="http://tempuri.org/".<xsd:import>, добавляем недостающие атрибуты namespace="http://tempuri.org/" и перенаправляем ссылки schemaLocation на локальные пути к сохраненным XSD-файлам.WSОпределения, указав путь к локальному WSDL-файлу.Посмотрим на пример инициализации прокси по исправленному локальному описанию:
ПутьКЛокальномуWSDL = "C:\WSDL\SeldonApiService.wsdl";
URIПространстваИмен = "http://tempuri.org/";
ИмяСервиса = "SeldonApiService";
ИмяТочкиПодключения = "BasicHttpBinding_ISeldonApiService";
// Создаем определения на основе локального исправленного файла
Определения = Новый WSОпределения(ПутьКЛокальномуWSDL);
// Инициализируем прокси для вызова операций
Прокси = Новый WSПрокси(Определения, URIПространстваИмен, ИмяСервиса, ИмяТочкиПодключения);
// Вызываем метод веб-сервиса
Результат = Прокси.GetData(123);
Поскольку пропуск атрибута namespace в тегах импорта схем является нарушением спецификации WS-I, рекомендуется уведомить разработчиков сервиса. В обращении укажите точную строку с некорректным тегом импорта. После внесения правок на стороне веб-сервиса вы сможете стандартно добавить статическую WS-ссылку через дерево метаданных конфигуратора.