Введение в SOAP и WSDL

10 февраля 2014
SOAP (Simple Object Access Protocol) — это протокол для обмена данными в формате XML-сообщений.

Существуют две версии протокола:
* версия 1.1 от 2000 года, https://www.w3.org/TR/soap11/
* версия 1.2 от 2003 года, https://www.w3.org/TR/soap12/

Формат сообщений

Данные передаются в виде XML-сообщений, которые состоят из следующих частей:
  • Envelope (конверт) — корневой элемент, обязательный элемент;
  • Header (заголовок) — содержит параметры (атрибуты) для обработки сообщения, необязательный элемент;
  • Body (тело) — содержит сообщение, обязательный элемент;
  • Fault (ошибка) — содержит информацию об ошибках, необязательный элемент.

Структура сообщения:
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope/" 
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
	<soap:Header>
	...
	</soap:Header>
	<soap:Body>
		...
		<soap:Fault>
		...
		</soap:Fault>
	</soap:Body>
</soap:Envelope>

Пространства имён

Пространство имён — это конструкция, группирующая в себе элементы и параметры (атрибуты) с целью реализации структурной модели и обеспечения уникальности элемента и атрибута, что позволяет избежать конфликта имён.

Для объявления пространства имён используется запись в формате:
<тег xmlns:приставка="URI пространства имён">

Приставку (он же префикс) можно указывать любой, так как она действует локально внутри текущего документа. Но есть общепринятые символьные коды приставок, соотвествующие определённому пространству имён (см. таблицу ниже).

Если не указывать приставку, тогда заданное пространство будет считаться стандартным для всех элементов, где оно (пространство имён) принудительно не указано.

Пример объявления:
<корневой-тег xmlns:tns=" http://test.ru/vb_chat.wsdl" <!-- подключаем пространство tns -->
xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" <!-- подключаем пространство xsd -->
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" <!-- подключаем пространство soap -->
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" <!-- подключаем пространство soapenc -->
xmlns="http://schemas.xmlsoap.org/wsdl/"> <!-- пространство имён по-умолчанию -->

Пространства имён, используемые в документах SOAP 1.1:
Приставка Адрес Описание
SOAP-ENV http://schemas.xmlsoap.org/soap/envelope/ Схема для SOAP-конверта
SOAP-ENC http://schemas.xmlsoap.org/soap/encoding/ Схема с правилами сериализации SOAP
xsi http://www.w3.org/1999/XMLSchema-instance Схема для прямого использования нескольких специфичных атрибутов XML-схем: xsi:type, xsi:nil, xsi:schemaLocation, xsi:noNamespaceSchemaLocation
xsd (иногда указывается xs) http://www.w3.org/1999/XMLSchema Схема с определением правил и типов для описания элементов и атрибутов в XML-документе.
tns Пользовательский адрес tns - от "this namespace". Используется в качестве условного обозначения для ссылки на текущий документ.

Пространства имён, используемые в документах SOAP 1.2:
Приставка Адрес Описание
env http://www.w3.org/2003/05/soap-envelope Схема для SOAP-конверта
xsd (иногда указывается xs) http://www.w3.org/2001/XMLSchema Схема с определением правил и типов для описания элементов и атрибутов в XML-документе.

Типы данных

В полях SOAP-сообщений указываются типы данных. Спецификации XML https://www.w3.org/TR/xmlschema-2/ допускают использование двух видов типов данных: простых и составных.

Иерархия типов:


К простым типам относятся:
  • string - строка;
  • boolean - логический тип, может содержать следующие значения: true, false, 1, 0;
  • decimal - десятичное число, которое может быть представлено как целочисленно, так и с запятой.
    Примеры значений: -1.23, 12678967.543233, +100000.00, 210
  • float - число с плавающей запятой ёмкостью 32 бита. Кроме числа тип может содержать значения: INF (положительная бесконечность), -INF (отрицательная бесконечность), NaN (не число, Not-A-Number);
  • double - аналогично типу float за ёмкости, которой тут отводится 64 бита.
  • duration - продолжительность времени, задаваемая в формате PnYnMnDTnHnMnS.

    В формате символы обозначают следующее:
    P - статичный символ.
    n - целое число, в котором указывается количество (лет, месяцев, дней, часов, минут, секунд).
    YMDHMS - символы, характеризующие целое число n. Соответственно Y - годы, M - месяцы, D - дни, H - часы, M - минуты, S - секунды.

    Пример записи: P1Y2MT123S (1 год, 2 месяца и 123 секунды)
  • dateTime - дата и время в формате YYYY-MM-DDThh:mm:ss (Год-месяц-деньTчасы:минуты:секунды). После даты можно указать флаг Z, что будет указывать на часовой пояс UTC, либо указать смещение часового пояса относительно UTC в формате hh:mm.

    Примеры значений:
    2013-04-03T05:10:59
    2013-04-03T05:10:59Z
    2013-04-03T05:10:59-3:30
    2013-04-03T05:10:59+4:00
  • time - время в формате hh:mm:ss (часы:минуты:секунды).
    Пример значения: 06:10:01;
  • date - дата в формате YYYY-MM-DD (год-месяц-день).
    Пример значения: 2014-10-01;
  • gYearMonth - год и месяц в формате YYYY-MM (год-месяц).
    Пример значения: 2015-12;
  • gYear - год в формате YYYY.
    Пример значения: 2015;
  • gMonthDay - месяц и день в формате MM-DD.
    Пример значения: 11-30;
  • gDay - день в формате DD.
    Пример значения: 30;
  • gMonth - месяц в формате MM.
    Пример значения: 10;
  • hexBinary - двоичные данные, закодированные в шестнадцатеричной кодировке;
  • base64Binary - двоичные данные, закодированные по стандарту base64;
  • anyURI - ссылка на сайт, директорию, файл. Значение anyURI может быть как абсолютным, так и относительным.
    Пример значения: https://yandex.ru/search
  • QName - описывает имя элемента, атрибута или идентификатора в XML-документе.
    Формат использования в тегах: <QName [атрибуты]>...</QName>;
  • NOTATION - набор QName, определённых в текущем XML-документе;

Составные типы

Элементы составных типов могут содержать в себе другие элементы и атрибуты. Пример объявления элемента составного типа:
<xs:element name="address">
	<xs:complexType>
		<xs:sequence>
			<xs:element name="zip" type="xs:string"/>
			<xs:element name="country" type="xs:string"/>
			<xs:element name="region" type="xs:string"/>
			<xs:element name="city" type="xs:string"/>
			<xs:element name="street" type="xs:string"/>
			<xs:element name="house" type="xs:string"/>
			<xs:element name="apartment" type="xs:string"/>
		</xs:sequence>
	</xs:complexType>
</xs:element>

WSDL

WSDL (Web Services Description Language) — язык на базе XML, служащий для описания работы веб-сервисов (адреса, запросы, ответы, параметры). SOAP связан с WSDL по той части, что SOAP обеспечивает транспорт, а WSDL обеспечивает объявление веб-сервиса.

Существуют две версии языка:
* версия 1.1 от 2001 года, https://www.w3.org/TR/wsdl.html
* версия 2.0 от 2007 года, https://www.w3.org/TR/wsdl/

Документы WSDL состоят из следующих разделов:
Раздел Версия 1.1 Версия 2.0
<definitions> Задает пространства имен для документа WSDL, XML-схемы и SOAP Отсутствует.
Вместо него существует раздел <description>
<description> Отсутствует.
Вместо него существует раздел <definitions>
Задает пространства имен для документов WSDL, XML и SOAP
<types> Элементы (данные), с которыми работает веб-сервис Аналогично
<message> Сообщения, с которыми работает веб-сервис Отсутствует
<portType> Операции, которые могут проводиться с сообщениями из раздела <message> Отсутствует. Вместо него существует раздел <interface>
<interface> Отсутствует.
См. раздел <portType>
Операции, которые могут проводиться с элементами (данными) из раздела <types>
<binding> Определение сетевого протокола и формат данных, используемых для операций из раздела <portType> Аналогично
<operation> Абстрактное определение операции (функции), в которой указываются входящее и исходящее сообщения, а так же сообщение об ошибке. Аналогично
<service> Объединяет конечные точки (адреса), реализующие общий интерфейс веб-сервиса. В разделе указывается общий адрес веб-сервиса Аналогично
<port> Протоколы и адреса, по которым выполняются запросы к веб-сервису Отсутствует
<endpoint> Отсутствует.
Вместо него существует раздел <port>
Протоколы и адреса, по которым выполняются запросы к веб-сервису

Схема документов в версиях WDSL 1.1 и 2.0 (картинка сделана на основе схемы от Оракла, https://docs.oracle.com/en/):


Структура вложенности разделов для WSDL 1.1:
/definitions

/definitions/types

/definitions/message
/definitions/message/part

/definitions/portType
/definitions/portType/operation
/definitions/portType/operation/fault
/definitions/portType/operation/input
/definitions/portType/operation/output

/definitions/binding
/definitions/binding/operation
/definitions/binding/operation/fault
/definitions/binding/operation/input
/definitions/binding/operation/output

/definitions/service
/definitions/service/port

Пространства имён для WSDL

По аналогии с предыдущим описанием, пространства имён подключаются через параметр xmlns.

Пример подключения:
<definitions name="vb_chat" 
targetNamespace="http://test.ru/vb_chat.wsdl" <!-- указываем адрес собственного пространства имён, к которому относится текущий файл -->
xmlns:tns=" http://test.ru/vb_chat.wsdl" <!-- подключаем пространство tns -->
xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" <!-- подключаем пространство xsd -->
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" <!-- подключаем пространство soap -->
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" <!-- подключаем пространство soapenc -->
xmlns="http://schemas.xmlsoap.org/wsdl/"> <!-- пространство имён по-умолчанию -->

В примере есть новый параметр targetNamespace, который служит для указания URI адреса пространства имён, к которому относится текущий документ. Важно не путать назначение targetNamespace и xmlns - первый относит файл к пространству имён, а второй (xmlns) служит для работы с пространствами имён внутри файла.

Пространства имён для WSDL 1.1:
Приставка Адрес Описание
wsdl http://schemas.xmlsoap.org/wsdl/ Схема с разделами WSDL 1.1 документа (definitions, types, message, portType и др.)
soap http://schemas.xmlsoap.org/wsdl/soap/ Схема для связки WSDL с SOAP
http http://schemas.xmlsoap.org/wsdl/http/ Схема для связки WSDL с HTTP запросами POST и GET
mime http://schemas.xmlsoap.org/wsdl/mime/ Схема для наделения WSDL возможностью работать с различными типами файлов. Используется, например, если нужно в ответе передать картинку или музыкальный файл, что делается через элемент <mime:multipartRelated>
soapenc http://schemas.xmlsoap.org/soap/encoding/ Схема с правилами сериализации SOAP
soapenv http://schemas.xmlsoap.org/soap/envelope/ Схема для SOAP-конверта
xsi http://www.w3.org/2000/10/XMLSchema-instance Схема для прямого использования нескольких специфичных атрибутов XML-схем: xsi:type, xsi:nil, xsi:schemaLocation, xsi:noNamespaceSchemaLocation
xsd (иногда указывается xs) http://www.w3.org/2001/XMLSchema Схема с определением правил и типов для описания элементов и атрибутов в XML-документе.
tns Пользовательский адрес tns - от "this namespace". Используется в качестве условного обозначения для ссылки на текущий документ.

Пространства имён для WSDL 2.0:
Приставка Адрес Описание
wsdl http://www.w3.org/ns/wsdl Схема с разделами WSDL 2.0 документа (description, types, interface, binding и др.)
wsdli http://www.w3.org/ns/wsdl-instance Схема для использования глобального атрибута wsdli:wsdlLocation
wsdlx http://www.w3.org/ns/wsdl-extensions Схема расширенного WSDL., позволяющая использовать атрибуты: wsdlx:safe, wsdlx:interface и wsdlx:binding
xsd (иногда указывается xs) http://www.w3.org/2001/XMLSchema Схема с определением правил и типов для описания элементов и атрибутов в XML-документе.
xsi http://www.w3.org/2001/XMLSchema-instance Схема для прямого использования нескольких специфичных атрибутов XML-схем: xsi:type, xsi:nil, xsi:schemaLocation, xsi:noNamespaceSchemaLocation

Пример файла с описанием веб-сервиса в формате WDSL 1.1:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions

	xmlns:tns="http://test-site.ru/my_calculator/scheme.wsdl"
	xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"

	name="my_calculator"
	targetNamespace="http://test-site.ru/my_calculator/scheme.wsdl">


	<!-- Описание файла -->
	<wsdl:documentation>
		Определение веб-сервиса "Мой калькулятор", который может выполнять
		сложение, вычитание, умножение, деление двух целых чисел и возвращать
		приближённое значение числа Пи
	</wsdl:documentation>


	<!-- Объявляем виды xml-элементов (xml-теги), которые будут использоваться в сервисе -->
	<wsdl:types>
    	<xsd:schema targetNamespace="http://test-site.ru/my_calculator/scheme.wsdl">
    		<!-- Элемент "Математическое действие" с параметрами: переменная "a", перебенная "b", действие ('+', '-', '*', '/') -->
			<xsd:element name="math_action">
	        	<xsd:complexType>
	          		<xsd:sequence>
	          			<!--
	          			В атрибуте "minOccurs" указывается минимальное количество таких элементов,
	          			а в атрибуте "maxOccurs" указывается соотвественно максимальное количество
	          			таких элементов. Значениие 'unbounded' будет означать неограниченное количество
	          			-->
	            		<xsd:element name="a" type="xsd:decimal" minOccurs="1" maxOccurs="1"/>
	            		<xsd:element name="b" type="xsd:decimal" minOccurs="1" maxOccurs="1"/>
	            		<xsd:element name="action" type="xsd:string" minOccurs="1" maxOccurs="1"/>
	          		</xsd:sequence>
				</xsd:complexType>
			</xsd:element>

			<!-- Элемент для получения числа Пи -->
			<xsd:element name="get_pi">
				<xsd:complexType/>
			</xsd:element>

    		<!-- Элемент "Результат" -->
			<xsd:element name="result">
	        	<xsd:complexType>
	          		<xsd:sequence>
	            		<xsd:element name="value" type="xsd:string" minOccurs="0" maxOccurs="1"/>
	            		<xsd:element name="message_error" type="xsd:string" minOccurs="0" maxOccurs="1"/>
	          		</xsd:sequence>
				</xsd:complexType>
			</xsd:element>

		</xsd:schema>
	</wsdl:types>


	<!-- Объявляем сообщения, которыми будет обмениваться веб-сервис внутри себя -->

	<!-- Сообщение "Математическое действие. Запрос" -->
	<wsdl:message name="math_action_request">
		<wsdl:part element="tns:math_action" name="parameters"/>
	</wsdl:message>

	<!-- Сообщение "Математическое действие. Ответ" -->
	<wsdl:message name="math_action_response">
    	<wsdl:part element="tns:result" name="parameters"/>
	</wsdl:message>

	<!-- Сообщение "Получить число Пи. Запрос" -->
	<wsdl:message name="get_pi_request">
		<wsdl:part element="tns:get_pi" name="parameters"/>
	</wsdl:message>

	<!-- Сообщение "Получить число Пи. Ответ" -->
	<wsdl:message name="get_pi_response">
    	<wsdl:part element="tns:result" name="parameters"/>
	</wsdl:message>


	<!-- Cвязываем операции (функции) и сообщения веб-сервиса  -->
	<wsdl:portType name="my_calculator_port_type">

		<!-- Операция "Математическое действие" -->
		<wsdl:operation name="math_action">
			<wsdl:input message="tns:math_action_request"/>
			<wsdl:output message="tns:math_action_response"/>
		</wsdl:operation>

		<!-- Операция "Получить число Пи" -->
		<wsdl:operation name="get_pi">
			<wsdl:input message="tns:get_pi_request"/>
			<wsdl:output message="tns:get_pi_response"/>
		</wsdl:operation>

	</wsdl:portType>


	<!-- Привязываем операции к сетевым протоколам (в данном случае к SOAP) -->
	<wsdl:binding name="my_calculator_binding" type="tns:my_calculator_port_type">
		<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>

		<!-- Привязка операции "Математичесоке действие" -->
		<wsdl:operation name="math_action">
      		<soap:operation soapAction=""/>
			<wsdl:input>
				<soap:body use="literal"/>
			</wsdl:input>
			<wsdl:output>
				<soap:body use="literal"/>
			</wsdl:output>
			<wsdl:fault>
				<soap:body use="literal"/>
			</wsdl:fault>
		</wsdl:operation>

		<!-- Привязка операции "Получить число Пи" -->
		<wsdl:operation name="get_pi">
      		<soap:operation soapAction=""/>
			<wsdl:input>
				<!--
				В обязательном атрибуте "use" указывается, должны ли части сообщения быть закодированы.
				Если установлено значение 'encoded', то части сообщения кодируются по правилам из
				атрибута "encodingStyle". Если в атрибуте "use" указано значение 'literal', то части сообщения не
				кодируются и определяются типами схемы, на которую ссылаются
				-->
				<soap:body use="literal"/>
			</wsdl:input>
			<wsdl:output>
				<soap:body use="literal"/>
			</wsdl:output>
		</wsdl:operation>

	</wsdl:binding>


	<!-- Указываем адрес доступа к веб-сервису -->
	<wsdl:service name="my_calculator">
		<wsdl:port binding="tns:my_calculator_binding" name="my_calculator_soap">
			<soap:address location="http://test-site.ru/my_calculator/server.php"/>
		</wsdl:port>
	</wsdl:service>

</wsdl:definitions>