Как исправить ошибку «схема должна иметь атрибут targetNamespace» при создании WS-ссылки в 1С?

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

При попытке добавить сторонний веб-сервис в конфигурацию через объект метаданных 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С прерывает процесс импорта и выдает критическую ошибку.

Поскольку веб-сервис является внешним и у нас нет прямого доступа к его исходному коду, рассмотрим альтернативные варианты решения проблемы.

Способ 1. Отправка SOAP-запросов через объект HTTPСоединение

Если нам не требуется поддержка статической типизации XDTO, наиболее быстрым и независимым решением будет работа с SOAP-сервисом как с обычным REST/HTTP-эндпоинтом. Для этого сформируем XML-пакет (SOAP Envelope) вручную и передадим его методом POST.

Разберем по шагам реализацию запроса:

  1. Создадим объект HTTPСоединение с указанием адреса сервера и порта.
  2. Сформируем тело SOAP-запроса в виде XML-строки.
  3. Инициализируем HTTPЗапрос, указав путь к веб-сервису.
  4. Установим обязательные заголовки: Content-Type (для SOAP 1.1 используется text/xml; charset=utf-8) и заголовок SOAPAction (название вызываемой операции).
  5. Отправим запрос методом ОтправитьДляОбработки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") + " " + Ответ.ПолучитьТелоКакСтроку();
КонецЕсли;

Способ 2. Локальное исправление WSDL и динамическое создание WSПрокси

Если мы хотим сохранить удобство работы с типизированными объектами XDTO и вызовами методов через WSПрокси, исправим схемы на стороне клиента.

Рассмотрим порядок действий:

  1. Скачиваем исходный файл WSDL и все связанные с ним схемы XSD (адреса которых указаны в параметрах schemaLocation) на локальный диск.
  2. Открываем скачанные XSD-файлы в текстовом редакторе. Если в корневом узле <xs:schema> отсутствует targetNamespace, дописываем его вручную, например: targetNamespace="http://tempuri.org/".
  3. В основном файле WSDL находим теги <xsd:import>, добавляем недостающие атрибуты namespace="http://tempuri.org/" и перенаправляем ссылки schemaLocation на локальные пути к сохраненным XSD-файлам.
  4. В коде 1С инициализируем сервис динамически через объект WSОпределения, указав путь к локальному WSDL-файлу.

Посмотрим на пример инициализации прокси по исправленному локальному описанию:


ПутьКЛокальномуWSDL = "C:\WSDL\SeldonApiService.wsdl";
URIПространстваИмен = "http://tempuri.org/";
ИмяСервиса = "SeldonApiService";
ИмяТочкиПодключения = "BasicHttpBinding_ISeldonApiService";

// Создаем определения на основе локального исправленного файла
Определения = Новый WSОпределения(ПутьКЛокальномуWSDL);

// Инициализируем прокси для вызова операций
Прокси = Новый WSПрокси(Определения, URIПространстваИмен, ИмяСервиса, ИмяТочкиПодключения);

// Вызываем метод веб-сервиса
Результат = Прокси.GetData(123);

Способ 3. Обращение в техническую поддержку сервиса

Поскольку пропуск атрибута namespace в тегах импорта схем является нарушением спецификации WS-I, рекомендуется уведомить разработчиков сервиса. В обращении укажите точную строку с некорректным тегом импорта. После внесения правок на стороне веб-сервиса вы сможете стандартно добавить статическую WS-ссылку через дерево метаданных конфигуратора.

← На главную