Web服务描述语言(WSDL) 1.02000年9月25日
作者(按字母排序)
Erik Christensen, Microsoft
Francisco Curbera, IBM
Greg Meredith, Microsoft
Sanjiva Weerawarana, IBM
版权所有2000 Ariba, International Business Machines Corporation, Microsoft
翻译:
何杭军,中国XML联盟
张亚,中国XML联盟
--------------------------------------------------------------------------------
摘要
WSDL是一种描述网络服务(network service)的XML格式,网络服务是能对面向文档类型的信息和面向过程的信息进行操作的端点(endpoint)的集合。对操作和消息的描述是抽象性的,并在定义端点时,将消息和操作绑定到具体的网络协议和消息格式上。相关的具体的端点集构成抽象的端点集(服务)。WSDL是可扩展的,它允许对端点和端点间的消息进行描述,同时不去考虑具体的消息格式或者双方用于通讯的网络协议,尽管如此,本文还是描述了怎样在WSDL中绑定SOAP 1.1, HTTP GET/POST, 和 MIME。
这个版本仅仅是WSDL语言的第一步,他不包含描述端点的构成(composition)和端点控制(orchestration)的框架。一个用于描述上述要求的完整的框架必需包含服务怎样组成和服务行为怎样表达,即消息接受和发送的排队规则等方面的内容。服务的构成必需是类型安全的(type safe),同时还应允许引用(reference)可以传递在运行时(run-time)交互和捆绑的服务引用,后者对于运行时的会话机制和俘获引用的服务和中间服务的行为甚为关键。
WSDL规范的作者打算及时的发布WSDL的修订版本和(或)补充文档,届时将包括:1)服务构成的框架2)用于描述服务行为的框架。
状态
这个草案代表了Ariba, IBM 和Microsoft关于服务描述的最新思想。它的概念可以从 NASSL, SCL, 和SDL (服务描述领域的早期提案)中找到思想的源头。
目录
1 简介
1.1 WSDL文档实例
1.2 符号约定
2 服务定义
2.1文档结构
2.1.1文档命名和链接
2.1.2 编写体例
2.1.3 语言扩展性和绑定
2.1.4注释文档
2.2 类型
2.3 消息
2.3.1消息块
2.3.2 抽象消息和具体消息
2.4 端口类型
2.4.1单向操作
2.4.2 请求-应答操作
2.4.3 被叫-应答操作
2.4.4 通知操作
2.4.5 操作内元素的命名
2.4.6 操作内参数顺序
2.5 绑定
2.6 端口
2.7 服务
3 绑定
3.1 SOAP例子
3.2 SOAP绑定怎样扩展
3.3 soap:binding元素
3.4 soap:operation元素
3.5 soap:body元素
3.6 soap:fault元素
3.7 soap:header元素
3.8 soap:address元素
4 HTTP GET & POST 绑定
4.1 HTTP GET/POST 例子
4.2 HTTP GET/POST如何扩展WSDL
4.3 http:address元素
4.4 http:binding元素
4.5 http:operation元素
4.6 http:urlEncoded元素
4.7 http:urlReplacement元素
5 MIME绑定
5.1 MIME 绑定例子
5.2 MIME绑定如何扩展WSDL
5.3 mime:content元素
5.4 mime:multipartRelated元素
5.5 soap:body元素
5.6 mime:mimeXml元素
6 参考文献
A 1 关于URI的注释
A 1.1 XML名域和schema定位
A 1.2 相对URI
A 1.3 产生URI
A 2 Wire format for WSDL examples
A 2.1 例1
A 3 扩展性元素的位置
A 4 Schemas
A 4.1 WSDL Schema
A 4.2 SOAP Binding Schema
A 4.3 HTTP Binding Schema
A 4.4 MIME Binding Schema
1. 简介
随着通讯协议和消息格式在WEB中的标准化,以某种格式化的方法描述通讯变得越来越重要并且其实现的可能性也越来越大。WSDL通过定义一套XML的语法来描述网络服务的方式满足了这种需求。WSDL把网络服务定义成一个能交换消息的通讯端点集(communication collection)。WSDL服务为分布式系统提供了帮助文档,同时该服务也可作为自动实现应用间通讯的解决方案。
一个WSDL文档将服务定义为一个网络端点的集合,或者说端口的集合。在WSDL里面,端点及消息的抽象定义与它们具体的网络实现和数据格式绑定是分离的。这样就可以重用这些抽象定义:消息,需要交换的数据的抽象描述;端口类型,操作的抽象集合。针对一个特定端口类型的具体协议和数据格式规范构成一个可重用的绑定。一个端口定义成网络地址和可重用的绑定的联接,端口的集合定义为服务。因此一个WSDL文档在定义网络服务的时候使用如下的元素:
类型–使用某种的类型系统(比如XSD)定义数据类型的容器
消息–通讯数据抽象的有类型的定义
操作– 服务支持的动作的抽象描述
端口类型–一个操作的抽象集合,该操作由一个或多个端点支持
绑定– 针对一个特定端口类型的具体的协议规范和数据格式规范
端口– 一个单一的端点,定义成一个绑定和一个网络地址的联接
服务– 相关的端点的集合
这些元素将在第二节详细描述。注意到WSDL并没有引入一种新的类型语言,这一点非常重要。为了描述消息的结构,需要具有丰富类型的系统,WSDL意识到了这种需求,因此它支持XML的schema规范[11]作为它的规范的类型系统。但是仅使用一种类型语言来描述现在和将来的所有消息格式显然是不可能的,因此WSDL可以扩展使用其他的类型定义语言。
另外,WSDL定义了一个通用的绑定机制。它用来将一个协议、数据格式、或者结构附加到一个抽象的消息、操作或者端点。它允许抽象定义的重用。
除了核心的服务定义框架,本规范为以下的协议和数据格式引入特殊的绑定扩展:
SOAP 1.1 (见第三节)
HTTP GET / POST (见第四节)
MIME (见第五节)
尽管上述语言扩展在本文档范围内定义,但它们都是构建在核心的服务定义框架之上的,因而不排除使用其他的绑定扩展。
1.2WSDL文档实例
以下的实例是一个用WSDL定义的简单的股票价格咨询服务。服务支持唯一一个操作称为GetLastTradePrice,该服务使用基于HTTP的SOAP协议来实现。请求带有一个字符串类型的交易标记(ticker symbol),同时返回一个浮点数类型的价格。关于该例子中出现的所有元素将在第二节(核心语言)和第三节(SOAP绑定)中详细解释。
范例11 通过HTTP实现的SOAP 1.1 Request/Response
<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<schema targetNamespace="http://example.com/stockquote.xsd"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="TradePriceRequest">
<complexType>
<all>
<element name="tickerSymbol" type="string"/>
</all>
</complexType>
</element>
<element name="TradePriceResult">
<complexType>
<all>
<element name="price" type="float"/>
</all>
</complexType>
</element>
</schema>
</types>
<message name="GetLastTradePriceInput">
<part name="body" element="xsd1:TradePriceRequest"/>
</message>
<message name="GetLastTradePriceOutput">
<part name="body" element="xsd1:TradePriceResult"/>
</message>
<portType name="StockQuotePortType">
<operation name="GetLastTradePrice">
<input message="tns:GetLastTradePriceInput"/>
<output message="tns:GetLastTradePriceOutput"/>
</operation>
</portType>
<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetLastTradePrice">
<soap:operation soapAction="http://example.com/GetLastTradePrice"/>
<input>
<soap:body use="literal" namespace="http://example.com/stockquote.xsd"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="literal" namespace="http://example.com/stockquote.xsd"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="StockQuoteService">
<documentation>My first service</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://example.com/stockquote"/>
</port>
</service>
</definitions>
1.2 符号约定
1.本文档中出现的关键字"MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",和"OPTIONAL" 的解释与RFC-2119 [2]中的描述一致
2. 以下是全文中使用的名域前缀:
前缀 名域URI 定义
wsdl schemas.xmlsoap.org/wsdl/soap / WSDL框架下的WSDL名域
http schemas.xmlsoap.org/wsdl/http / HTTP GET & POST绑定的WSDL前缀
mime schemas.xmlsoap.org/wsdl/mime / MIME绑定的WSDL前缀
xsi www.w3.org/1999/XMLSchema-instance 根据XSD[11]定义的文档实例的名域.
xsd www.w3.org/1999/XMLSchema 根据XSD [11]中定义的Schema名域
tns (任意) 当前文档的名域
(其他) (任意) 其他用作范例的名域
3. 本规范使用一种非正规的语法来描述WSDL文档的XML语法:
语法以XML文档实例的形式出现,但文档的值表示的是数据类型而不是值。
在文档和属性后可能出现的字符为"?" (0次或者1次), "*" (0次或者多次), "+" (1次或者多次)
元素名以“...”结束(比如: <element…/> or <element…>)表示与上下文无关的元素或者属性被省略。
粗体表示的语法或者是以前的文档中没有出现过的内容或者是需要特别关注的内容。
<-- extensibility element --> 是为其他名域元素保留的占位符(如XSD中的##other)
XML名域前缀(定义如上)用于表示所定义的元素的名域。
只有以 <?xml 开始的例子是和符合本规范的例子,其他的例子都不是完全的。
XSD schemas 用于正式定义WSDL语法:
2. Service Definition服务定义
这一节描述WSDL语言的核心元素。对SOAP HTTP MIME的扩展将在第三、四、五节中论述。
2.1 WSDL Document Structure WSDL文档结构
一个WSDL文档可以简单的认为是一个定义集。definitions元素作为根元素,服务定义在文档内部。WSDL文档的语法如下:
<wsdl:definitions name="nmtoken"? targetNamespace="uri"?>
<import namespace="uri" location="uri"/>*
<wsdl:documentation…/> ?
<wsdl:types> ?
<wsdl:documentation…/>?
<xsd:schema…/>*
<-- extensibility element --> *
</wsdl:types>
<wsdl:message name="nmtoken> *
<wsdl:documentation…/>?
<part name="nmtoken" element="qname"? type="qname"?/> *
</wsdl:message>
<wsdl:portType name="nmtoken">*
<wsdl:documentation…/>?
<wsdl:operation name="nmtoken">*
<wsdl:documentation…/> ?
<wsdl:input name="nmtoken"? message="qname">?
<wsdl:documentation…/> ?
</wsdl:input>
<wsdl:output name="nmtoken"? message="qname">?
<wsdl:documentation…/> ?
</wsdl:output>
<wsdl:fault name="nmtoken" message="qname"> *
<wsdl:documentation…/> ?
</wsdl:fault>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="nmtoken" type="qname">*
<wsdl:documentation…/>?
<-- extensibility element --> *
<wsdl:operation name="nmtoken">*
<wsdl:documentation…/> ?
<-- extensibility element --> *
<wsdl:input name="nmtoken"?> ?
<wsdl:documentation…/> ?
<-- extensibility element -->
</wsdl:input>
<wsdl:output name="nmtoken"?> ?
<wsdl:documentation…/> ?
<-- extensibility element --> *
</wsdl:output>
<wsdl:fault name="nmtoken"> *
<wsdl:documentation…/> ?
<-- extensibility element --> *
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="nmtoken"> *
<wsdl:documentation…/>?
<wsdl:port name="nmtoken" binding="qname"> *
<wsdl:documentation…/> ?
<-- extensibility element -->
</wsdl:port>
<-- extensibility element -->
</wsdl:service>
<-- extensibility element --> *
</wsdl:definitions>
服务主要使用以下5个元素:
types, 消息的数据类型定义通常用来描述所交换的消息。
message, 代表待传输数据的抽象定义。一条message(消息)由逻辑上的消息构件(part)组成,每一个构件(part)使用某种类型系统来定义。
portType,是一个抽象的操作(operation)的集合。每一个operation 指向一条输入消息(message)和输出消息(message).
binding, 它表述operation和message的具体的协议和数据格式规范。如前所述,operation 和message由porttype定义。
port,它指定一个用于绑定的地址,由此定义一个通讯端点(endpoint)
service, 用于表示由相关的port集成的服务
这些元素将在2.2-2.7节中详细论述。本节的剩余部分我们着重论述WSDL中命名文档、引用文档定义、使用语言扩展和增加辅助性文档的规则。
2.1.1 文档的命名和连接
WSDL文档可以赋给一个类型是NCNAME的name属性,该属性是可选的,可以作为一个轻量级的注解文档(documentation)。同样,也可以指定类型URI的targetNamespace属性。这个URI不能是相对URI。
WSDL allows associating a namespace with a document location using an import statement:
WSDL允许通过import语句,关联一个有文档位置的名域。(译者注:这里的描述我们认为是不恰当的,我们理解的描述应该是:WSDL可以通过import元素将其它的文档导入)。
<definitions…>
<import namespace="uri" location="uri"/> *
</definitions>
在WSDL中对QName的解析和在XML schema规范中论述的QName解析是类似的。[11]
可以通过使用一个QName来产生对WSDL定义的一个引用。在WSDL文档中如下的类型定义是可以被引用的:
WSDL 定义: service, port, message, bindings, 和 portType
其他定义:如果其他的定义是通过扩展性定义的,他们必需使用QName链接。
每一个WSDL定义类型都有自己的名辖域范围(即端口名和消息名永远不会冲突)。在同一个名辖域范围内的名必需是唯一的。
2.1.2 编写风格
使用import元素可以将不同的服务定义元素分别定义到不同的文档中。这有助于将服务按照抽象层次的不同分别定义,从而使服务定义更加清晰。另外这也使得各种服务定义能够最大程度被重用。因此WSDL文档可以更好地使用和维护。范例2是范例1的翻版,但是在定义服务的过程中使用了上述的编写风格。这里将服务定义文档分成三个文档:数据类型定义,抽象定义和特定服务绑定。当然使用上述机制定义服务文档不必按部就班于范例2的方式,在例2中仅仅使用了在WSDL规范中出现的元素,对于基于语言扩展定义的其他类型同样可以用这种体例编码和重用。
Example 2. Example 1的另一种编写风格.
example.com/stockquote/stockquote.xsd
<?xml version="1.0"?>
<schema targetNamespace="http://example.com/stockquote/schemas"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="GetLastTradePrice">
<complexType>
<all>
<element name="tickerSymbol" type="string"/>
</all>
</complexType>
</element>
<element name="GetLastTradePriceResult">
<complexType>
<all>
<element name="result" type="float"/>
</all>
</complexType>
</element>
</schema>
example.com/stockquote/stockquote.wsdl
<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote/definitions"
xmlns:tns="http://example.com/stockquote/definitions"
xmlns:xsd1="http://example.com/stockquote/schemas"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<import namespace="http://example.com/stockquote/schemas"
location="http://example.com/stockquote/stockquote.xsd"/>
<message name="GetLastTradePriceRequest">
<part name="body"element="xsd1:GetLastTradePrice"/>
</message>
<message name="GetLastTradePriceResponse">
<part name="body"element="xsd1:GetLastTradePriceResult"/>
</message>
<portType name="StockQuotePortType">
<operation name="GetLastTradePrice">
<input message="tns:GetLastTradePriceRequest"/>
<output message="tns:GetLastTradePriceResponse"/>
</operation>
</portType>
</definitions>
example.com/stockquote/stockquoteservice.wsdl
<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote/service"
xmlns:tns="http://example.com/stockquote/service"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<import namespace="http://example.com/stockquote/definitions"
location="http://example.com/stockquote/stockquote.wsdl"/>
<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="document"/>
<operation name="GetLastTradePrice">
<soap:operation soapAction="http://my.org/GetLastTradePrice"/>
</operation>>
</binding>
<service name="StockQuoteService">
<documentation>My first service</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://my.org/stockquote"/>
</port>
</service>
</definitions>
2.1.3 语言的可扩展性和绑定
在WSDL中,绑定(binding)表示将特定的协议或者数据格式信息与抽象的实体比如消息,操作或者端口类型关联的过程。通过WSDL定义的不同的元素,WSDL允许用元素代表某种特定的技术(这里所指的元素是指扩展元素)。这种扩展方式比较典型的应用场合就是为特定协议或者消息格式指定绑定信息,当然还有别的应用场合。扩展元素必需使用和WSDL不同的名域。在附录A3中还说明了扩展元素在WSDL文档中允许出现的位置是什么。
扩展元素经常用于指定某种特定的绑定技术。为了在通讯中区分绑定技术的语义是不是必需的,扩展元素可以使用一个布尔类型属性wsdl:required来表明。该属性默认值为false。该属性具体在名域"http://schemas.xmlsoap.org/wsdl/soap/"中定义。
扩展元素的例子见3,4,5节。
2.1.4 Documentation注释文档
WSDL使用一个可选的wsdl:document元素用于容纳对人提供帮助信息的注释文档。该元素的内容是任意的文本或者元素(即在XSD中的混合类型)。该元素允许在任何WSDL语言的元素中出现。
2.2 Types类型
type元素封装了与被交换消息相关的数据类型的定义。出于最大化互操作性和平台独立的考虑,WSDL偏向于使用XSD作为规范的类型系统,并将它看作固有的类型系统。
<definitions…>
<types>
<xsd:schema…/>*
</types>
</definitions>
XSD类型系统可以用于定义消息中的类型而不关心最终实现的数据格式是否为XML形式,以及是否对最终的数据用XSD schema校验。使用XSD类型系统在某些场合下是非常必要的,比如对同一条消息需要多种绑定或者对同一消息只有一种绑定但这种绑定类型还没有一个广为流传的类型系统。在这些情况下,使用XSD对抽象类型编码的最佳方式是:
仅使用元素(不使用属性)
不包括仅在特殊的协议和数据格式中使用的元素或者属性(也就是说与消息的抽象内容无关的属性和元素)。
对数组类型使用Soap:Array 类型。(不管结果形式是否使用第5节SOAP1.1所叙述的编码)。使用ArrayOfXXX作为数组类型的名(这里表示数组项的类型)
然而,不能指望单单一个类型系统语法来描述所有现在和将来的抽象类型,因此WSDL允许通过扩展元素增加其他类型系统。type元素可以有一个扩展子元素用于表示需要使用的类型系统定义和作为类型定义的XML容器元素。这个元素的作用类似与在schema中出现的schema元素。
<definitions…>
<types>
<-- type-system extensibility element --> *
</types>
</definitions>
2.3 消息
消息由一个或者多个的逻辑构件(part)构成。每一构件都与某一类型系统中的类型相关联,构件通过消息类型属性(message-typing attributes)来指定类型。消息类型属性集是可扩展的。WSDL使用XSD定义了一些消息类型属性:
element元素. 指使用合格名的一个XSD元素
type类型. 指一个使用合格名标识XSD简单类型或者复杂类型
(译者注:这里的元素和类型都是属性,具体地说都是part元素的属性,该属性可以用于指定part元素的数据类型)。
其它消息类型属性同样可以定义,只要它们使用不同于WSDL的名域。绑定扩展元素同样可以使用消息类型属性。
以下表示定义一条消息的语法。消息类型属性(视类型系统的不同而有可能不同)用粗体表示。
<definitions…>
<message name="nmtoken"> *
<part name="nmtoken"? element="qname" type="qname"?/> *
</message>
</definitions>
在WSDL文档内消息通过name属性区分。
在同一条消息内,消息构件通过name属性区分。
2.3.1消息构件
构件是一种用于描述消息的抽象逻辑内容的灵活机制。一个绑定有可能引用消息构件的名以便指明这个构件的与绑定相关的信息。例如,如果定义一条用于RPC的消息,一个消息构件可能表示消息中的一个参数。然而,要了解这个部分的真实含义却必须对绑定进行检查。
如果消息具有多个逻辑单位,则需要使用多个part元素。例如下列的消息就是由一个订单构件和顾客构件组成。
<definitions…>
<types>
<schema…>
<element name="PO" type="tns:POType"/>
<complexType name="POType">
<element name="id" type="string/>
<element name="name" type="string"/>
<element name="items">
<complexType>
<element name="item" type="tns:Item" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
</element>
</complexType>
<complexType name="Item">
<element name="quantity" type="int"/>
<element name="product" type="string"/>
</complexType>
<element name="Customer" type="tns:CustomerType"/>
<complexType name="CustomerType">
<element name="name" type="string"/>
</complexType>
</schema>
</types>
<message name="PO">
<part name="po" element="tns:PO"/>
<part name="customer" element="tns:Customer"/>
</message>
</definitions>
但是,若消息内容非常复杂,则可以使用另一种语法即直接使用类型系统定义的方法来表述消息的复合结构。下面的例子中,体是一个订单或者一系列的顾客。
<definitions…>
<types>
<schema…>
<complexType name="POType">
<element name="id" type="string/>
<element name="name" type="string"/>
<element name="items">
<complexType>
<element name="item" type="tns:Item" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
</element>
</complexType>
<complexType name="Item">
<element name="quantity" type="int"/>
<element name="product" type="string"/>
</complexType>
<complexType name="CustomerType">
<element name="name" type="string"/>
</complexType>
<complexType name="Composite">
<choice>
<element name="PO" minOccurs="1" maxOccurs="1" type="tns:POType"/>
<element name="Customer" minOccurs="0" maxOccurs="unbounded" type="tns:CustomerType"/>
</choice>
</complexType>
</schema>
</types>
<message name="PO">
<part name="composite" type="tns:Composite"/>
</message>
</definitions>
2.3.2 抽象消息和具体消息
消息定义通常认为是消息内容的抽象定义。一个消息绑定描述了抽象消息内容到具体消息格式的映射。对某种或某些绑定而言,在有些情况下抽象定义与具体消息表示非常接近,这样的绑定不提供或很少提供映射的信息。而另外一些对同样消息的绑定却需要更多的映射信息。正是这个原因,抽象消息只有在具体对绑定检查的时候才知道消息“到底有多抽象”。
2.4 Port Types端口类型
一个端口类型是一个由抽象操作和抽象消息构成的有名称的集合。
<wsdl:definitions…>
<wsdl:portType name="nmtoken">
<wsdl:operation name="nmtoken"…/> *
</wsdl:portType>
</wsdl:definitions>
在WSDL中,端口类型由它的name属性值区分。
操作通过name属性命名。
WSDL具有端点(endpoint)支持的4种原子传输方式
One-way单向.端点接收一条消息
Request-response请求-应答.端点接收一条消息,并发送一条相关消息。
Solicit-response要求-应答. 端点发送一条消息并接收一条相关消息。
Notification通知.端点发送一点消息
WSDL将这些原子操作看作operation.尽管请求/应答 要求/应答模式可以使用两个单向消息来替代,但仍将它们看作原子操作类型是因为:
它们非常普遍
不引入更复杂的流信息就可以将消息序列相互联系。
有些端点只能接收同步请求的回应消息。
从算法的角度上看如果有必要定义简单流,则它可以从这些原子操作中衍生出来。
尽管请求应答或者要求应答模式在WSDL文档中都是逻辑相关的,但具体的相关信息需在给定的绑定中描述。例如,请求和应答的消息可以作为一个或者两个实际的网络通讯的消息构件而进行交换。
操作中引用到的消息通过message属性指定。该属性服从WSDL定义的链接规则(见 2.1.2节)。
2.4.1 单向操作
单向操作的语法是:
<wsdl:definitions…> <wsdl:portType…> *
<wsdl:operation name="nmtoken">
<wsdl:input name="nmtoken"? message="qname"/>
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>
input元素指定用于单向操作的抽象消息格式。
2.4.2 请求应答操作
请求应答操作的语法是:
<wsdl:definitions…>
<wsdl:portType…> *
<wsdl:operation name="nmtoken" parameterOrder="nmtokens">
<wsdl:input name="nmtoken"? message="qname"/>
<wsdl:output name="nmtoken"? message="qname"/>
<wsdl:fault name="nmtoken" message="qname"/>*
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>
input和output元素分别指定请求和应答的抽象消息格式。可选的fault元素指定可能的任何错误消息,该消息可能作为操作的结果输出(抽象的错误消息,与协议和具体细节无关)。
注意请求应答操作是一个抽象的标记,一个特定的绑定必须明确怎样真正地发送消息:在同一个通讯连接中发送(比如HTTP的请求/应答)还是在两个独立的通讯连接中发送(比如两个独立的HTTP请求)。
2.4.3 要求-应答操作
要求-应答操作的语法是:
<wsdl:definitions…>
<wsdl:portType…> *
<wsdl:operation name="nmtoken" parameterOrder="nmtokens">
<wsdl:output name="nmtoken"? message="qname"/>
<wsdl:input name="nmtoken"? message="qname"/>
<wsdl:fault name="nmtoken" message="qname"/>*
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>
input和output 元素指定分别用于要求和应答的抽象消息格式。可选的fault元素指定可能的任何错误消息,该消息可能作为操作的结果输出(抽象的错误消息,与协议和具体细节无关)。
注意要求应答操作是一个抽象的标记,一个特定的绑定必须明确怎样真正发送消息:在同一个通讯连接中发送(比如HTTP的请求/应答)还是在两个独立的通讯连接中发送(比如两个独立的HTTP请求)。
2.4.4 通知操作
通知操作的语法是:
<wsdl:definitions…>
<wsdl:portType…> *
<wsdl:operation name="nmtoken">
<wsdl:output name="nmtoken"? message="qname"/>
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>
output元素指定用于通知操作的抽象消息格式。
2.4.5 操作内元素的名
在同一个端口类型范围内,所有的input和output元素各自通过元素名区分。
为了避免必须给操作内的每一个input和 output元素命名,WSDL提供了基于操作名的默认元素名.在单向传输或者是在通知方式的消息中,操作内元素的默认名是操作名,在另外两种方式下,input output元素的默认名是操作名分别加上 "Request"/"Solicit" 或者"Response"。
错误信息元素命名时必须允许一个绑定来指定错误信息的具体格式。在同一个操作内,出错信息元素名是唯一的。
2.4.6 操作内参数的顺序
操作并不明确规定它们是否能够应用到类似RPC的绑定中。但如果要在RPC绑定中使用操作,需要有一种方式能够表达RPC原来的结构。出于这个原因,请求应答和要求应答操作可以通过parameterOrder(nmtokens类型)指定一个参数名列表。该属性的值是一个用空格分开的消息构件名序列 。消息构件名必须满足以下的规则:
消息构件的序列必须反映RPC中参数的顺序
返回值消息构件在列表中不出现T
如果构件名同时在input和output消息中同时出现,它是一个in/out参数I
如果构件名只在in消息中出现,则它是一个传入参数I
如果构件名在output消息中出现,则它是一个传出参数
注意这些信息只作为“提示”,不关心RPC结构的应用完全可以忽略这些信息。同时,这些信息也不是必须的,甚至在类似RPC的绑定中,也可以不出现。
2.5 绑定
绑定定义了操作的消息格式和协议细节以及由端口类型定义的消息。对一个给定的端口类型,可以有任意数量的绑定。绑定的语法如下:
<wsdl:definitions…>
<wsdl:binding name="nmtoken" type="qname"> *
<-- extensibility element (1) --> *
<wsdl:operation name="nmtoken"> *
<-- extensibility element (2) --> *
<wsdl:input name="nmtoken"?> ?
<-- extensibility element (3) -->
</wsdl:input>
<wsdl:output name="nmtoken"?> ?
<-- extensibility element (4) --> *
</wsdl:output>
<wsdl:fault name="nmtoken"> *
<-- extensibility element (5) --> *
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
</wsdl:definitions>
WSDL文档内绑定通过name属性区分。
绑定通过type属性引用一个它绑定的端口类型。绑定的值服从在WSDL中定义的连接规则。(见2.1.2节)
绑定中出现的operation,input,output和fault元素与端口类型定义中的相应的元素关联,关联通过每个元素的name属性完成,在绑定中出现的这些元素具有和端口类型中定义的元素同样的行为。(见2.4.5节)
绑定扩展元素用于指定相应元素的具体语法,如input(3),output(4)和fault信息(5)。同时也可指定每个操作绑定信息(2)和绑定信息(1)。
绑定必需指定恰好一个协议。
绑定不可以指定地址信息。
2.6 端口
端口通过为绑定指定唯一地址的形式定义一个端点。
<wsdl:definitions…>
<wsdl:service…> *
<wsdl:port name="nmtoken" binding="qname"> *
<-- extensibility element (1) -->
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
在WSDL文档范围内,所有的端口使用name属性区别。
binding属性(类型)指向特定的绑定,在指向的关连规则在WSDL中定义(见 2.1.2节)
绑定扩展元素用于指定端口的地址信息。
端口不可以指定多个地址。
端口不可以指定处理地址信息以外的人很绑定信息。
2.7 服务
一个service将相关的端口组织在一起:
<wsdl:definitions…>
<wsdl:service name="nmtoken"> *
<wsdl:port…/>*
</wsdl:service>
</wsdl:definitions>
在WSDL范围内服务的name属性值是唯一的。
在一个服务内的端口具有如下的关系:
端口之间不相互通讯(即一个端口的输出不会是另一个端口的输入)
如果服务具有多个端口类型相同的端口,但他们对应不同的绑定或者地址,则这些端口是可替换的。每一个端口在语义上是等价的(在绑定施加给传输和消息格式的限制范围内)。这样就允许WSDL文档的用户可以根据一些选择标准(协议、距离等)选择特定的通讯端口。
通过检查服务的端口,我们可以确定服务的端口类型。这样就允许WSDL文档的使用者能够根据它支持的端口类型决定是否和一个特定的服务通讯。这在有些时候是非常有用的,比如在端口类型的操作之间有一些内在的联系,并且为了完成一个特定的任务所有的端口类型必需出现的情况下。
3. SOAP绑定
WSDL包括对SOAP1.1端点的绑定,它支持对与协议相关的信息作如下的设定:
表明绑定到SOAP1.1的标记
给SOAP端点指定地址
SOAP绑定到HTTP时需要指定SOAPAction HTTP头,该头是一个URI类型的值
对SOAP头的定义列表,该SOAP头将转化为SOAP封装(SOAP Envelope)
一个在XSD中指定SOAP根的方式
这里的绑定语法并不是一个最终的规范,因为SOAP绑定集还处在发展之中。相反额外的SOAP绑定可以从原来的语法部分中无限制的衍生出来,例如:
通过替换soap:address元素(在 section 3.8定义),不使用URI定位模式的SOAP绑定可以使用其他的定位模式
不需要SOAPAction的SOAP绑定可以忽略在3.4节中定义的soapaction属性。
3.1 SOAP 范例
在下列例子中,一个 SubscribeToQuotes SOAP 1.1单向(one-way)消息通过SMTP绑定发送到StockQuote服务中。请求带一个字符串类型的交易标记,同时还包括一个头,该头定义了发送者的URI
范例 3. 在SMTP之上的单向(one-way)操作的SOAP绑定,使用SOAP头
<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<message name="SubscribeToQuotes">
<part name="body" element="xsd1:SubscribeToQuotes"/>
</message>
<portType name="StockQuotePortType">
<operation name="SubscribeToQuotes">
<input message="tns:SubscribeToQuotes"/>
</operation>
</portType>
<binding name="StockQuoteSoap" type="tns:StockQuotePortType">
<soap:binding style="document" transport="http://example.com/smtp"/>
<operation name="SubscribeToQuotes">
<input message="tns:SubscribeToQuotes">
<soap:header element="xsd1:SubscriptionHeader"/>
</input>
</operation>
</binding>
<service name="StockQuoteService">
<port name="StockQuotePort" binding="tns:StockQuoteSoap">
<soap:address location="mailto://subscribe@example.com"/>
</port>
</service>
<types>
<schema targetNamespace="http://example.com/stockquote.xsd"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="SubscribeToQuotes">
<complexType>
<all>
<element name="tickerSymbol" type="string"/>
</all>
</complexType>
</element>
<element name="SubscriptionHeader" type="uriReference"/>
</schema>
</types>
</definitions>
这个例子描述了一个 GetLastTradePrice SOAP 1.1 请求,该请求可能通过SOAP 1.1 HTTP绑定发送到StockQuote服务。请求带一个字符串类型交易标记,一个时间实例(timeInstant)类型的时间,请求在SOAP应答中返回一个浮点数的价格。
范例 4. 在HTTP之上的请求应答RPC操作的SOAP绑定
<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<message name="GetLastTradePriceRequest">
<part name="tickerSymbol" element="xsd:string"/>
<part name="time" element="xsd:timeInstant"/>
</message>
<message name="GetLastTradePriceResponse">
<part name="result" type="xsd:float"/>
</message>
<portType name="StockQuotePortType">
<operation name="GetLastTradePrice">
<input message="tns:GetLastTradePriceRequest"/>
<output message="tns:GetLastTradePriceResponse"/>
</operation>
</portType>
<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetLastTradePrice">
<soap:operation soapAction="http://example.com/GetLastTradePrice"/>
<input>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>>
</binding>
<service name="StockQuoteService">
<documentation>My first service</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://example.com/stockquote"/>
</port>
</service>
</definitions>
3.2 SOAP绑定如何扩展WSDL
SOAP绑定扩展WSDL表现在以下新增的元素:
<definitions…>
<binding…>
<soap:binding style="rpc|document" transport="uri">
<operation…>
<soap:operation soapAction="uri"? style="rpc|document"?>?
<input>
<soap:body parts="nmtokens"? use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>
<soap:header element="qname" fault="qname"?>*
</input>
<output>
<soap:body parts="nmtokens"? use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>
<soap:header element="qname" fault="qname"?>*
</output>
<fault>*
<soap:fault name="nmtoken" use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>
</fault>
</operation>
</binding>
<port…>
<soap:address location="uri"/>
</port>
</definitions>
所有的SOAP绑定扩展元素在后续的章节中都会涉及。
3.3 soap:binding元素
SOAP binding 元素表明WSDL文档绑定到SOAP协议格式:封装,头,体等元素。这个元素没有声明消息的编码或者格式(举例来说,消息的编码和格式根据SOAP1.1规范的要求是必需的)。
该元素在使用SOAP绑定时是必需的。
<definitions…>
<binding…>
<soap:binding transport="uri"? style="rpc|document"?>
</binding>
</definitions>
sosp:binding 元素的style属性的值同时是它所包含的操作子元素的style属性的默认值。如果该属性省略,默认为"document"。关于style属性的语义的更多信息,见 3.4节。
transport属性是必需的,它的值表示绑定的传输方式与SOAP的何种传输方式一致。URI值http://schemas.xmlsoap.org/soap/http 表示传输方式和SOAP规范的HTTP绑定相一致。
3.4 soap:operation元素
该元素提供关于操作元素的整体信息。
<definitions…>
<binding…>
<operation…>
<soap:operation soapAction="uri"? style="rpc|document"?>
</operation>
</binding>
</definitions>
style属性表示操作是面向RPC(RPC-oriented 消息中包含参数和返回值)还是面向文档(document-oriented消息中包含文档)的。这些信息对选择一个合适的编程模型是由帮助的。如果该属性值没有指定,则默认与soap:binding元素的style值一致,如果在soap:binding中没有指定该属性值,则默认值是document。
soapAction属性指定SOAPAction头的值。该URI直接用作SOAPAciton头的值,不允许使用相对URI。对于SOAP的HTTP绑定,该属性值是必需的。对于SOAP的其他协议绑定,可以不指定,甚至soap:operation元素也可以省略。
3.5 soap:body元素
soap:body 元素指定消息构件在SOAP体元素中怎样出现。
消息构件有可能是抽象类型定义的也有可能是具体schema定义的。如果是抽象定义,则将根据编码风格定义的规则序列化这些类型。就象在SOAP规范中的一样,每一个编码风格用URI的列表区分。在某些编码风格比如SOAP的编码风格(http://schemas.xmlsoap.org/soap/encoding/)下,给定抽象类型集的消息格式允许一定的自由度,因此理解所有不同格式消息的任务就落到了读者的头上,这可以称之为:读者决定方式(读者读到所有的格式,并决定他能理解的格式,译者注)。为了避免需要支持所有的格式类型,消息可能具体地定义,并同时指定它的原始编码风格。在这种情况下,消息的写者必需确保消息与他指定的消息格式一致,这可以称之为:写者决定方式(写着决定选用那种编码风格,一旦决定选用某种方式,则需要在消息中指明这种方式,并严格按照这种格式写消息)。
soap:body元素可同时用于定义面向RPC和面向文档的消息。如果包含它的操作元素的style属性值是“rpc”,则所有的消息构件都是rpc的参数或者返回值,并且这些参数包裹在一个元素内出现在SOAP体中(见SOAP规范的7.1节)。如果style属性值是“document”,每一个消息构建是一个文档并直接出现在体元素中。上述的机制同时适用于这两个元素(体元素和包裹元素)的子元素。
<definitions…>
<binding…>
<operation…>
<input>
<soap:body parts="nmtokens"? use="literal|encoded"?
encodingStyle="uri-list"? namespace="uri"?>
</input>
<output>
<soap:body parts="nmtokens"? use="literal|encoded"?
encodingStyle="uri-list"? namespace="uri"?>
</output>
</operation>
</binding>
</definitions>
可选的nmtokens 类型的属性parts表示消息的哪些构件出现在SOAP体元素的消息部分中(其它的消息构件可能出现在其他消息部分中,比如SOAP绑定与MIME绑定合用的时候)。如果该part属性缺省,则默认所有在消息中定义的消息构件都出现在SOAP体元素部分中。
soap:body元素的必要属性use表示消息构件是使用某种编码方式编码,还是使用某种具体的消息类型。(该类型在本文档中定义,译者注)
如果use的值是encoded,则每一个消息构件通过类型属性引用抽象(消息)类型。encodingStyle属性的应用可以使抽象类型转变成具体的消息。构件的name types 属性以及namespace属性的都传入(消息构件的)编码中,这里namespace属性只应用到在构件内容没有被显式定义的抽象类型中。如果被引用的编码风格允许格式上的自由变化(例如SOAP的编码风格),则格式所有的可能形式都要被支持(读者决定方式)。
如果use属性值为lieteral,则每一个构件引用一个具体的schema,对简单的构件通过element属性引用,对复合的构件,则通过type属性引用。encodingstyle属性的值用于表示具体的格式可以衍生自一个特定的编码方式(比如SOAP编码),但这时只支持被指定的衍生方式(写者决定方式)。
属性encodingStyle的值是一个用空格分开的URI列表。URI表示的编码风格在该消息内被应用。列表顺序表明了对应编码风格的严格程度(与SOAP规范中定义的encodingStyle非常类似)。
3.6 soap:fault元素
soap:fault元素指定需要在SOAP 出错细节信息(SOAP Fault Details)元素的内容中出现的内容。该元素必需在soap:body元素之后出现(见 3.5节)。
<definitions…>
<binding…>
<operation…>
<fault>*
<soap:fault name="nmtoken" use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>
</fault>
</operation>
</binding>
</definitions>
name属性将soap:fault元素和wsdl:fault元素关联。
fault消息必需有唯一一个消息构件。use,encodingStyle namespace属性同soap:body(见section 3.5 )。
3.7 soap:header元素
soap:header定义了在SOAP的头元素中出现的内容。在本节详尽地列出所有的头是没有必要的,因为在WSDL的其它规范中将头元素加入实际传输文档中是很正常的,显然没有必要将这些元素也列进来。
<definitions…>
<binding…>
<operation…>
<input>
<soap:header element="qname" fault="qname"?>*
</input>
<output>
<soap:header element="qname" fault="qname"?>*
</output>
</operation>
</binding>
</definitions>
element属性指向头元素具体的schema。头的schema可以不包括soap:actor soap:mustUnderstand属性的定义。
可选的fault属性(与element属性类似)可以为 header元素的出错信息指定具体的schema。SOAP规范规定头元素的出错信息必需在头元素中返回,fault属性允许为这些头元素规定schema.
3.8 soap:address
SOAP地址绑定用于给端口指定一个地址(URI)。使用SOAP绑定的端口必需指定且仅指定一个地址。
<definitions…>
<port…>
<binding…>
<soap:address location="uri"/>
</binding>
</port>
</definitions>
4. HTTP GET & POST 绑定
为了描述WEB浏览器和WEB服务器之间的交互。WSDL包含了一个对HTTP的GET和POST动词的绑定。该绑定同样允许非浏览器的应用与WEB 服务器之间的交互。在HTTP绑定中需要说明如下的与协议相关的信息:
一个HTTP绑定的标记
A 一个端口的地址
每个操作相对于端口地址的相对地址
4.1 HTTP GET/POST 范例
以下的范例表示将一个给定的端口类型绑定到不同的3个端口。
如果传递的值是part1=1, part2=2, part3=3,每一个端口请求格式将会是如下形式
port1: GET, URL="http://example.com/o1/A1B2/3"
port2: GET, URL="http://example.com/o1?p1=1&p2=2&p3=3
port3: POST, URL="http://example.com/o1", PAYLOAD="p1=1&p2=2&p3=3"
对于每一个端口,应答是一个GIF或者JPG
范例5. GET和FORM POST,返回一个GIF或JPG
<definitions…>
<message name="m1">
<part name="part1" type="xsd:string"/>
<part name="part2" type="xsd:int"/>
<part name="part3" type="xsd:string"/>
</message>
<message name="m2">
<part name="image" type="xsd:binary"/>
</message>
<portType name="pt1">
<operation name="o1">
<input message="tns:m1"/>
<output message="tns:m2"/>
</operation>
</portType>
<service name="service1">
<port name="port1" binding="tns:b1">
<http:address location="http://example.com/"/>
</port>
<port name="port2" binding="tns:b1">
<http:address location="http://example.com/"/>
</port>
<port name="port3" binding="tns:b1">
<http:address location="http://example.com/"/>
</port>
</service>
<binding name="b1" type="pt1">
<http:binding verb="GET"/>
<operation name="o1">
<http:operation location="o1/A(part1)B(part2)/(part3)"/>
<input>
<http:urlReplacement/>
</input>
<output>
<mime:content type="image/gif"/>
<mime:content type="image/jpeg"/>
</output>
</operation>
</binding>
<binding name="b2" type="pt1">
<http:binding verb="GET"/>
<operation name="o1">
<http:operation location="o1"/>
<input>
<http:urlEncoded/>
</input>
<output>
<mime:content type="image/gif"/>
<mime:content type="image/jpeg"/>
</output>
</operation>
</binding>
<binding name="b3" type="pt1">
<http:binding verb="POST"/>
<operation name="o1">
<http:operation location="o1"/>
<input>
<mime:content type="application/x-www-form-urlencoded"/>
</input>
<output>
<mime:content type="image/gif"/>
<mime:content type="image/jpeg"/>
</output>
</operation>
</binding>
</definitions>
4.2 HTTP GET/POST 如何扩展WSDL
HTTP GET/POST绑定通过如下的扩展元素扩展WSDL:
<definitions…>
<binding…>
<http:binding verb="nmtoken"/>
<operation…>
<http:operation location="uri"/>
<input…>
<-- mime elements -->
</input>
<output…>
<-- mime elements -->
</output>
</operation>
</binding>
<port…>
<http:address location="uri"/>
</port>
</definitions>
在后续章节中将会涉及这些元素。
4.3 http:address元素
location属性指定端口的基URI。该属性值和http:operation元素的location属性值结合。详情参见4.5节。
4.4 http:binding元素
http:binding元素表示绑定使用HTTP协议。
<definitions…>
<binding…>
<http:binding verb="nmtoken"/>
</binding>
</definitions>
verb属性是必需的,它的值对应HTTP的动词。通常情况下,值为GET和POST,但其它的动词也可能使用。注意HTTP动词是大小写敏感的。
4.5 http:operation元素
location属性指定该操作的相对URI,它和http:address元素的location属性结合表示完整的HTTP请求的URI。该属性值必需是相对URI.
<definitions…>
<binding…>
<operation…>
<http:operation location="uri"/>
</operation>
</binding>
</definitions>
4.6 http:urlEncoded
urlEncoded元素表示所有的消息构件使用标准的URI编码规则(name1=value&name2=value…)编入HTTP请求的URI。参数的名和消息构件的名一致。构成消息构件的每一个值都用name=value对的形式编码。这些值可以和GET一起使用用于指定URL编码,或者和POST一起表示一个FORM-POST。对于GET而言,如果有必要"?"字符会自动添加。
<http:urlEncoded/>
欲了解URI编码参数的更多的信息,见[5], [6], and [7]。
4.7 http:urlReplacement元素
http:urlReplacement元素表示所有的消息构件编码成HTTP请求的URI时使用替换算法。
根据一个搜索模式集合搜索http:operation的相对URI值
搜索的时机是在http:operation和http:address的location属性连接之前
所有消息构件都有一个统一的搜索模式 。表示搜索模式的字符串是括号括住的消息构件名(比如<http:operation location="o1/A(part1)B(part2)/(part3)"/>中的part1等,译者注)
匹配在任何值被替换以前执行(即替换的值不触发额外的匹配)
对每个匹配,对应的消息构件的值在该匹配所在的位置被替换
消息构件值不能重复。
<http:urlReplacement/>(为了更好的理解http:urlReplacement http:encoded,请仔细体会http绑定的例子,译者注)
5. MIME 绑定
WSDL还支持MIME格式的消息绑定。绑定为如下的MIME类型给出了定义:
multipart/related
text/xml
application/x-www-form-urlencoded (用于提交HTML表单的格式t)
Others (通过指定MIME类型)
MIME中定义的类型集合不但很大而且不够稳定,在必要的情况下可以补充额外的定义额外的MIME类型和为定义该类型而增加的语法。因此WSDL的目的并不在于为每一个MIME类型定义相应的XML语法。如果一个MIME类型串有足够的能力描述内容,则以下定义的mime元素可以得到应用。
5.1 MIME 绑定范例
范例 7. 在SOAP中使用 multipart/related with SOAP
这个例子描述了一个SOAP1.1的GetCompanyInfo请求,该请求通过SOAP1.1的HTTP绑定发送到StockQuote服务。请求附带一个字符串类型的交易标记。应答包含多个使用MIME格式 multipart/related编码的消息构件:即一个SOAP封装包含浮点类型的股票价格,零个或多个营销性质的HTML文档,甚至一个可选的公司的LOGO,该LOGO可能是GIF或者是JPEG。
<definitions…>
<types>
<schema…>
<element name="GetCompanyInfo">
<complexType>
<all>
<element name="tickerSymbol " type="string"/>
</all>
</complexType>
</element>
<element name="GetCompanyInfoResult">
<complexType>
<all>
<element name="result" type="float"/>
</all>
</complexType>
</element>
<complexType name="ArrayOfBinary" base="soap:Array">
<all>
<element name="value" type="xsd:binary"/>
</all>
</complexType>
</schema>
</types>
<message name="m1">
<part name="body" element="tns:GetCompanyInfo"/>
</message>
<message name="m2">
<part name="body" element="tns:GetCompanyInfoResult"/>
<part name="docs" type="xsd:string"/>
<part name="logo" type="tns:ArrayOfBinary"/>
</message>
<portType name="pt1">
<operation name="GetCompanyInfo">
<input message="m1"/>
<output message="m2"/>
</operation>
</portType>
<binding name="b1" type="tns:pt1">
<operation name="GetCompanyInfo">
<soap:operation soapAction="http://example.com/GetCompanyInfo"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<mime:multipartRelated>
<mime:part>
<soap:body parts="body" use="literal"/>
</mime:part>
<mime:part>
<mime:content part="docs" type="text/html"/>
</mime:part>
<mime:part>
<mime:content part="logo" type="image/gif"/>
<mime:content part="logo" type="image/jpeg"/>
</mime:part>
</mime:multipartRelated>
</output>
</operation>
</binding>
<service name="CompanyInfoService">
<port name="CompanyInfoPort"binding="tns:b1">
<soap:address location="http://example.com/companyinfo"/>
</port>
</service>
</definitions>
5.2 MIME如何扩展WSDL
MIME绑定对WSDL的扩展通过如下的扩展元素表现:
<mime:content part="nmtoken"? type="string"?/>
<mime:multipartRelated>
<mime:part> *
<-- mime element -->
</mime:part>
</mime:multipartRelated>
<mime:mimeXml part="nmtoken"?/>
他们出现在WSDL文档中的如下位置:
<definitions…>
<binding…>
<operation…>
<input…>
<-- mime elements -->
</input>
<output…>
<-- mime elements -->
</output>
</operation>
</binding>
</definitions>
MIME元素在input和output元素中出现。如果多次出现,则可以替换(例如上例定义的LOGO就出现了两个可选MIME元素,这时发送的数据可以是GIF或者是JPEG,译者注)。
5.3 mime:content元素
为了避免为每一个MIME格式定义一个新的元素,在没有额外的关于格式(MIME类型串除外)的信息需要发送时,可以使用mimi:element元素。
<mime:content part="nmtoken"? type="string"?/>
part属性用于指定消息构件。如果消息只有一个构件(例如单向操作的场合,译者注),则该属性可选。type属性包含MIME类型串。一个类型值有两个部分,中间用“/”分开,两个部分都可能是*。如果没有指定type属性值,则所有的MIME类型都允许。
如果返回格式是XML文档,但返回文档的schema在事先不知道(即文档是无法事先校验的,译者注)则可以使用通用的mime元素,它表示类型值为text/xml:
<mime:content type="text/xml"/>
*用于表示一个mime类型族,例如所有的文本类型可以这样表示:
<mime:content type="text/*"/>
The following two examples both specify all mime types:
下面的两个例子都指定了所有的mime类型
<mime:content type="*/*"/>
<mime:content/>
5.4 mime:multipartRelated元素
multipart/related MIME类型将任意的MIME格式化的消息构件并成一个消息。mime:multipartRelated 元素描述了类似消息的具体的格式。
<mime:multipartRelated>
<mime:part> *
<-- mime element -->
</mime:part>
</mime:multipartRelated>
mime:part元素描述了 multipart/related消息的每个构件。MIME元素出现在mime:part元素内,用于指定指定消息构件的具体的MIME类型。如果在一个mimi:part元素内出现多个MIME元素,则这些元素是可以相互替换的。
5.5 soap:body元素
在SOAP请求中使用MIME绑定的情况下,将soap:element元素用作一个MIME元素是合法的。它还表示内容的类型是“text/xml”并且有一个SOAP封装元素。
5.6 mime:mimeXml元素
mime:mimeXml元素在这样的场合下使用:需要使用XML的格式,并且有一个特殊的schema但不必兼容SOAP(即没有一个SOAP封装)。part属性指向一个消息构件,该消息构件定义了XML根元素的具体的schema。如果消息只有一个构件的话,该属性可以忽略。对简单类型的构件part通过element属性引用一个具体的schema,对复杂类型构件则通过type属性引用schema。
<绑定可以理解为文档的转化,即抽象定义服务的WSDL文档,转化为复合特定协议规范的字符串序列,如果转化以后的文档是XML文档,则甚至可以用XSLT实现,译者注>
<mime:mimeXml part="nmtoken"?/>
6. 参考文献
[2] S. Bradner, "Key words for use in RFCs to Indicate Requirement Levels", RFC 2119, Harvard University, March 1997
[4] T. Berners-Lee, R. Fielding, L. Masinter, "Uniform Resource Identifiers (URI): Generic Syntax", RFC 2396, MIT/LCS, U.C. Irvine, Xerox Corporation, August 1998.
[5] www.w3.org/TR/html401/interact/forms.html#submit-format
[6] www.w3.org/TR/html401/appendix/notes.html#ampersands-in-uris
[7] www.w3.org/TR/html401/interact/forms.html#h-17.13.4
[10] W3C Working Draft "XML Schema Part 1: Structures". This is work in progress.
[11] W3C Working Draft "XML Schema Part 2: Datatypes". This is work in progress.
A 1. Notes on URIs关于URI的解释
本节仅提供在实现本规范有益的一些背景,不对规范有任何实际的作用。
A 1.1 XML名域&schema定位
将XML schema的targetNamespace或者XML文档实例的xmlns属性值与相应的schema的定位等同起来是一个常见的误区。既然名域实际上是URI,而URI可能是定位,并且从该定位中获取schema也是可行的,但这并不意味着只有一个schema与该名域关联。有可能同时有多个schema与同一个特定的名域关联,并且在特定的处理场景中决定使用哪一个schema是XML处理器的职责。WSDL通过import机制提供处理这种场景,它来源于XMLschema的语法中的类似概念。
A 1.2 相对URI
在整个文档中,可以看到WSDL XSD文档中使用了完全合格的URI。使用完全合格的URI仅仅为了方便解释引用的概念。使用相对URI在很多情况下不但是允许的并且是合理的。欲知更多处理相对URI的信息,请参见http://www.normos.org/ietf/rfc/rfc2396.txt
A 1.3 产生URI
在WSDL中,有时候给实体虚构一个URI是非常需要的,但不用在所有时间都保证该URI全局唯一也不用保证它所有时候都有意义。有一个保留的URI基可以满足这样的需要。URI基http://tempuri.org/可用于构建一个没有唯一实体关联的URI。例如,两个用户或者程序可以同时使用URI tempuri.org/myschema 引用完全不同的schema,只要使用该URI的辖域不重叠,它们就认为是充分唯一的。这样作还有一个潜在的好处是被URI引用的实体可以版本化但不用产生更多的URI,只要在处理场景下可以理解。不推荐http://tempuri.org/作为一个稳定和固定的实体的URI引用基。
A 2. Wire format for WSDL examples
A 2.1. Example 1
SOAP Message Embedded in HTTP Request
POST /StockQuote HTTP/1.1
Host: www.stockquoteserver.com
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "Some-URI"
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<m:GetLastTradePrice xmlns:m="Some-URI">
<symbol>DIS</symbol>
</m:GetLastTradePrice>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
SOAP Message Embedded in HTTP Response
HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<SOAP-ENV:Body>
<m:GetLastTradePriceResponse xmlns:m="Some-URI">
<Price>34.5</Price>
</m:GetLastTradePriceResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
A 3.扩展性元素的位置
在WSDL文档中,扩展性元素可以出现在如下的位置
位置 含义 可能的用法
definitions 扩展性元素作为一个整体应用于这个WSDL文档 ? 作为一个整体介绍这个WSDL文档的附加信息和定义
definitions/types 扩展性元素是一个类型系统 ? 在XSD之外的类型系统中指定消息的格式
definitions/service 扩展性元素应用于一个服务 ? 介绍服务的附加信息或定义
definitions/service/port 扩展性元素应用于端口 ? 指定端口的地址
definitions/binding 扩展性元素作为一个整体应用于绑定 ? 为被绑定的端口类型中的所有操作提供特定协议的信息
definitions/binding/ operation 扩展性元素作为一个整体应用于操作 ? 提供应用于input消息和output消息的特定协议的信息
definitions/binding/ operation/input 扩展性元素应用于操作的input消息 ? 提供绑定时抽象消息构件映射到具体的协议和数据格式的细节
? 为input消息提供附加的特定协议信息
definitions/binding/ operation/output 扩展性元素应用于操作的output消息 ? 提供绑定时抽象消息构件映射到具体的协议和数据格式的细节
? 为output消息提供附加的特定协议信息
definitions/binding/ operation/fault 扩展性元素应用于操作的fault消息 ? 提供绑定时抽象消息构件映射到具体的协议和数据格式的细节
? 为fault消息提供附加的特定协议信息
--------------------------------------------------------------------------------
A 4. Schemas
A 4.1 WSDL Schema
<schema targetNamespace="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://www.w3.org/1999/XMLSchema"
elementFormDefault="qualified">
<element name="documentation" >
<complexType content="mixed">
<any minOccurs="0" maxOccurs="unbounded"/>
<anyAttribute/>
</complexType>
</element>
<complexType name="documented" abstract="true" content="elementOnly">
<element ref="wsdl:documentation"/>
</complexType>
<complexType name="openAtts" abstract="true" content="elementOnly">
<annotation>
<documentation>
This type is extended by component types
to allow attributes from other namespaces to be added.
</documentation>
</annotation>
<element ref="wsdl:documentation"/>
<anyAttribute namespace="##other"/>
</complexType>
<element name="definitions" type="wsdl:definitionsType">
<key name="message">
<selector>message</selector>
<field>@name</field>
</key>
<key name="portType">
<selector>portType</selector>
<field>@name</field>
</key>
<key name="binding">
<selector>binding</selector>
<field>@name</field>
</key>
<key name="service">
<selector>service</selector>
<field>@name</field>
</key>
<key name="import">
<!-- Is it too restrictive?-->
<selector>import</selector>
<field>@namespace</field>
</key>
<key name="port">
<selector>service/port</selector>
<field>@name</field>
</key>
</element>
<complexType name="definitionsType" base="wsdl:documented" derivedBy="extension">
<element ref="wsdl:import" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:types" minOccurs="0" maxOccurs="1"/>
<element ref="wsdl:message" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:portType" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:binding" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:service" minOccurs="0" maxOccurs="unbounded"/>
<any namespace="##other" minOccurs="0" maxOccurs="unbounded">
<annotation>
<documentation>to support extensibility elements </documentation>
</annotation>
</any>
<attribute name="targetNamespace" type="uriReference" use="optional"/>
<attribute name="name" type="NMTOKEN" use="optional"/>
</complexType>
<element name="import" type="wsdl:importType" />
<complexType name="importType" base="wsdl:documented" derivedBy="extension" >
<attribute name="namespace" type="uriReference" use="required"/>
<attribute name="location" type="uriReference" use="required"/>
</complexType>
<element name="types" type="wsdl:typesType"/>
<complexType name="typesType" base="wsdl:documented" derivedBy="extension" >
<any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
<element name="message" type="wsdl:messageType">
<unique name="part">
<selector>part</selector>
<field>@name</field>
</unique>
</element>
<complexType name="messageType" base="wsdl:documented" derivedBy="extension">
<element ref="wsdl:part" minOccurs="0" maxOccurs="unbounded"/>
<attribute name="name" type="NCName" use="required"/>
</complexType>
<element name="part" type="wsdl:partType"/>
<complexType name="partType" base="wsdl:openAtts" derivedBy="extension">
<attribute name="name" type="NMTOKEN" use="optional"/>
<attribute name="type" type="QName" use="optional"/>
<attribute name="element" type="QName" use="optional"/>
</complexType>
<element name="portType" type="wsdl:portTypeType">
<key name="operation">
<selector>operation</selector>
<field>@name</field>
</key>
</element>
<complexType name="portTypeType" base="wsdl:documented" derivedBy="extension" content="elementOnly" >
<element ref="wsdl:operation" minOccurs="0" maxOccurs="unbounded"/>
<attribute name="name" type="NCName" use="required"/>
</complexType>
<element name="operation" type="wsdl:operationType">
<unique name="paramName">
<selector>input| output| fault</selector>
<field>@name</field>
</unique>
</element>
<complexType name="operationType" base="wsdl:documented" derivedBy="extension" >
<choice minOccurs="1" maxOccurs="1">
<group ref="wsdl:one-way-operation"/>
<group ref="wsdl:request-response-operation"/>
<group ref="wsdl:solicit-response-operation"/>
<group ref="wsdl:notification-operation"/>
</choice>
<attribute name="name" type="NCName" use="required"/>
</complexType>
<group name="one-way-operation">
<sequence>
<element ref="wsdl:input" />
</sequence>
</group>
<group name="request-response-operation">
<sequence>
<element ref="wsdl:input"/>
<element ref="wsdl:output"/>
<element ref="wsdl:fault" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</group>
<group name="solicit-response-operation">
<sequence>
<element ref="wsdl:output"/>
<element ref="wsdl:input" />
<element ref="wsdl:fault" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</group>
<group name="notification-operation">
<sequence>
<element ref="wsdl:output"/>
</sequence>
</group>
<element name="input" type="wsdl:paramType"/>
<element name="output" type="wsdl:paramType"/>
<element name="fault" type="wsdl:faultType"/>
<complexType name="paramType" base="wsdl:documented" derivedBy="extension" >
<attribute name="name" type="NMTOKEN" use="optional"/>
<attribute name="message" type="QName" use="required"/>
</complexType>
<complexType name="faultType" base="wsdl:documented" derivedBy="extension" >
<attribute name="name" type="NMTOKEN" use="required"/>
<attribute name="message" type="QName" use="required"/>
</complexType>
<complexType name="startWithExtensionsType" base="wsdl:documented" derivedBy="extension"
content="elementOnly" abstract="true">
<any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
<element name="binding" type="wsdl:bindingType"/>
<complexType name="bindingType" base="wsdl:startWithExtensionsType" derivedBy="extension"
content="elementOnly">
<element name="operation" type="wsdl:binding_operationType" minOccurs="0" maxOccurs="unbounded"/>
<attribute name="name" type="NCName" use="required"/>
<attribute name="type" type="QName" use="required"/>
</complexType>
<complexType name="binding_operationType" base="wsdl:startWithExtensionsType"
derivedBy="extension" content="elementOnly">
<element name="input" type="wsdl:startWithExtensionsType" minOccurs="0" maxOccurs="1"/>
<element name="output" type="wsdl:startWithExtensionsType" minOccurs="0" maxOccurs="1"/>
<element name="fault" minOccurs="0" maxOccurs="unbounded">
<complexType base="wsdl:startWithExtensionsType" derivedBy="extension">
<attribute name="name" type="NMTOKEN" use="required"/>
</complexType>
</element>
<attribute name="name" type="NCName" use="required"/>
</complexType>
<element name="service" type="wsdl:serviceType"/>
<complexType name="serviceType" base="wsdl:documented" derivedBy="extension" >
<element ref="wsdl:port" minOccurs="0" maxOccurs="unbounded"/>
<any namespace="##other" minOccurs="0" maxOccurs="1"/>
<attribute name="name" type="NCName" use="required"/>
</complexType>
<element name="port" type="wsdl:portType"/>
<complexType name="portType" base="wsdl:documented" derivedBy="extension">
<any namespace="##other" minOccurs="0" maxOccurs="1"/>
<attribute name="name" type="NCName" use="required"/>
<attribute name="binding" type="QName" use="required"/>
</complexType>
</schema>
A 4.2 SOAP Binding Schema
<schema targetNamespace="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="binding" type="soap:bindingType"/>
<complexType name="bindingType" content="empty">
<attribute name="transport" type="uriReference" use="optional"/>
<attribute name="style" type="soap:styleChoice" use="optional"/>
</complexType>
<simpleType name="styleChoice" base="string" derivedBy="restriction">
<enumeration value="rpc"/>
<enumeration value="document"/>
</simpleType>
<element name="operation" type="soap:operationType"/>
<complexType name="operationType" content="empty">
<attribute name="soapAction" type="uriReference" use="optional"/>
<attribute name="style" type="soap:styleChoice" use="optional"/>
</complexType>
<element name="body" type="soap:bodyType"/>
<complexType name="bodyType" content="empty">
<attribute name="encodingStyle" type="uriReference" use="optional"/>
<attribute name="parts" type="NMTOKENS" use="optional"/>
<attribute name="use" type="soap:useChoice" use="optional"/>
<attribute name="namespace" type="uriReference" use="optional"/>
</complexType>
<simpleType name="useChoice" base="string">
<enumeration value="literal"/>
<enumeration value="encoded"/>
</simpleType>
<element name="fault" type="soap:faultType"/>
<complexType name="faultType" base="soap:bodyType" derivedBy="restriction">
<attribute name="parts" type="NMTOKENS" use="prohibited"/>
</complexType>
<element name="header" type="soap:headerType"/>
<complexType name="headerType" content="empty">
<attribute name="element" type="QName" use="required"/>
<attribute name="fault" type="QName" use="optional"/>
</complexType>
<element name="address" type="soap:addressType"/>
<complexType name="addressType" content="empty">
<attribute name="location" type="uriReference" use="required"/>
</complexType>
</schema>
A 4.3 HTTP Binding Schema
<schema targetNamespace="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="address" type="http:addressType"/>
<complexType name="addressType" content="empty">
<attribute name="location" type="uriReference" use="required"/>
</complexType>
<element name="binding" type="http:bindingType"/>
<complexType name="bindingType" content="empty">
<attribute name="verb" type="NMTOKEN" use="required"/>
</complexType>
<element name="operation" type="http:operationType"/>
<complexType name="operationType" content="empty">
<attribute name="location" type="uriReference" use="required"/>
</complexType>
<element name="urlEncoded">
<complexType content="empty"/>
</element>
<element name="urlReplacement">
<complexType content="empty"/>
</element>
</schema>
A 4.4 MIME Binding Schema
<schema targetNamespace="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="content" type="mime:contentType"/>
<complexType name="contentType" content="empty">
<attribute name="type" type="string" use="optional"/>
<attribute name="part" type="NMTOKEN" use="optional"/>
</complexType>
<element name="multipartRelated" type="mime:multipartRelatedType"/>
<complexType name="multipartRelatedType" content="elementOnly">
<element ref="mime:part" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
<element name="part" type="mime:partType"/>
<complexType name="partType" content="elementOnly">
<any namespace="targetNamespace" minOccurs="0" maxOccurs="unbounded"/>
<attribute name="name" type="NMTOKEN" use="required"/>
</complexType>
<element name="mimeXml" type="mime:mimeXmlType"/>
<complexType name="mimeXmlType" content="empty">
<attribute name="part" type="NMTOKEN" use="optional"/>
</complexType>
</schema>
作者(按字母排序)
Erik Christensen, Microsoft
Francisco Curbera, IBM
Greg Meredith, Microsoft
Sanjiva Weerawarana, IBM
版权所有2000 Ariba, International Business Machines Corporation, Microsoft
翻译:
何杭军,中国XML联盟
张亚,中国XML联盟
--------------------------------------------------------------------------------
摘要
WSDL是一种描述网络服务(network service)的XML格式,网络服务是能对面向文档类型的信息和面向过程的信息进行操作的端点(endpoint)的集合。对操作和消息的描述是抽象性的,并在定义端点时,将消息和操作绑定到具体的网络协议和消息格式上。相关的具体的端点集构成抽象的端点集(服务)。WSDL是可扩展的,它允许对端点和端点间的消息进行描述,同时不去考虑具体的消息格式或者双方用于通讯的网络协议,尽管如此,本文还是描述了怎样在WSDL中绑定SOAP 1.1, HTTP GET/POST, 和 MIME。
这个版本仅仅是WSDL语言的第一步,他不包含描述端点的构成(composition)和端点控制(orchestration)的框架。一个用于描述上述要求的完整的框架必需包含服务怎样组成和服务行为怎样表达,即消息接受和发送的排队规则等方面的内容。服务的构成必需是类型安全的(type safe),同时还应允许引用(reference)可以传递在运行时(run-time)交互和捆绑的服务引用,后者对于运行时的会话机制和俘获引用的服务和中间服务的行为甚为关键。
WSDL规范的作者打算及时的发布WSDL的修订版本和(或)补充文档,届时将包括:1)服务构成的框架2)用于描述服务行为的框架。
状态
这个草案代表了Ariba, IBM 和Microsoft关于服务描述的最新思想。它的概念可以从 NASSL, SCL, 和SDL (服务描述领域的早期提案)中找到思想的源头。
目录
1 简介
1.1 WSDL文档实例
1.2 符号约定
2 服务定义
2.1文档结构
2.1.1文档命名和链接
2.1.2 编写体例
2.1.3 语言扩展性和绑定
2.1.4注释文档
2.2 类型
2.3 消息
2.3.1消息块
2.3.2 抽象消息和具体消息
2.4 端口类型
2.4.1单向操作
2.4.2 请求-应答操作
2.4.3 被叫-应答操作
2.4.4 通知操作
2.4.5 操作内元素的命名
2.4.6 操作内参数顺序
2.5 绑定
2.6 端口
2.7 服务
3 绑定
3.1 SOAP例子
3.2 SOAP绑定怎样扩展
3.3 soap:binding元素
3.4 soap:operation元素
3.5 soap:body元素
3.6 soap:fault元素
3.7 soap:header元素
3.8 soap:address元素
4 HTTP GET & POST 绑定
4.1 HTTP GET/POST 例子
4.2 HTTP GET/POST如何扩展WSDL
4.3 http:address元素
4.4 http:binding元素
4.5 http:operation元素
4.6 http:urlEncoded元素
4.7 http:urlReplacement元素
5 MIME绑定
5.1 MIME 绑定例子
5.2 MIME绑定如何扩展WSDL
5.3 mime:content元素
5.4 mime:multipartRelated元素
5.5 soap:body元素
5.6 mime:mimeXml元素
6 参考文献
A 1 关于URI的注释
A 1.1 XML名域和schema定位
A 1.2 相对URI
A 1.3 产生URI
A 2 Wire format for WSDL examples
A 2.1 例1
A 3 扩展性元素的位置
A 4 Schemas
A 4.1 WSDL Schema
A 4.2 SOAP Binding Schema
A 4.3 HTTP Binding Schema
A 4.4 MIME Binding Schema
1. 简介
随着通讯协议和消息格式在WEB中的标准化,以某种格式化的方法描述通讯变得越来越重要并且其实现的可能性也越来越大。WSDL通过定义一套XML的语法来描述网络服务的方式满足了这种需求。WSDL把网络服务定义成一个能交换消息的通讯端点集(communication collection)。WSDL服务为分布式系统提供了帮助文档,同时该服务也可作为自动实现应用间通讯的解决方案。
一个WSDL文档将服务定义为一个网络端点的集合,或者说端口的集合。在WSDL里面,端点及消息的抽象定义与它们具体的网络实现和数据格式绑定是分离的。这样就可以重用这些抽象定义:消息,需要交换的数据的抽象描述;端口类型,操作的抽象集合。针对一个特定端口类型的具体协议和数据格式规范构成一个可重用的绑定。一个端口定义成网络地址和可重用的绑定的联接,端口的集合定义为服务。因此一个WSDL文档在定义网络服务的时候使用如下的元素:
类型–使用某种的类型系统(比如XSD)定义数据类型的容器
消息–通讯数据抽象的有类型的定义
操作– 服务支持的动作的抽象描述
端口类型–一个操作的抽象集合,该操作由一个或多个端点支持
绑定– 针对一个特定端口类型的具体的协议规范和数据格式规范
端口– 一个单一的端点,定义成一个绑定和一个网络地址的联接
服务– 相关的端点的集合
这些元素将在第二节详细描述。注意到WSDL并没有引入一种新的类型语言,这一点非常重要。为了描述消息的结构,需要具有丰富类型的系统,WSDL意识到了这种需求,因此它支持XML的schema规范[11]作为它的规范的类型系统。但是仅使用一种类型语言来描述现在和将来的所有消息格式显然是不可能的,因此WSDL可以扩展使用其他的类型定义语言。
另外,WSDL定义了一个通用的绑定机制。它用来将一个协议、数据格式、或者结构附加到一个抽象的消息、操作或者端点。它允许抽象定义的重用。
除了核心的服务定义框架,本规范为以下的协议和数据格式引入特殊的绑定扩展:
SOAP 1.1 (见第三节)
HTTP GET / POST (见第四节)
MIME (见第五节)
尽管上述语言扩展在本文档范围内定义,但它们都是构建在核心的服务定义框架之上的,因而不排除使用其他的绑定扩展。
1.2WSDL文档实例
以下的实例是一个用WSDL定义的简单的股票价格咨询服务。服务支持唯一一个操作称为GetLastTradePrice,该服务使用基于HTTP的SOAP协议来实现。请求带有一个字符串类型的交易标记(ticker symbol),同时返回一个浮点数类型的价格。关于该例子中出现的所有元素将在第二节(核心语言)和第三节(SOAP绑定)中详细解释。
范例11 通过HTTP实现的SOAP 1.1 Request/Response
<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<schema targetNamespace="http://example.com/stockquote.xsd"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="TradePriceRequest">
<complexType>
<all>
<element name="tickerSymbol" type="string"/>
</all>
</complexType>
</element>
<element name="TradePriceResult">
<complexType>
<all>
<element name="price" type="float"/>
</all>
</complexType>
</element>
</schema>
</types>
<message name="GetLastTradePriceInput">
<part name="body" element="xsd1:TradePriceRequest"/>
</message>
<message name="GetLastTradePriceOutput">
<part name="body" element="xsd1:TradePriceResult"/>
</message>
<portType name="StockQuotePortType">
<operation name="GetLastTradePrice">
<input message="tns:GetLastTradePriceInput"/>
<output message="tns:GetLastTradePriceOutput"/>
</operation>
</portType>
<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetLastTradePrice">
<soap:operation soapAction="http://example.com/GetLastTradePrice"/>
<input>
<soap:body use="literal" namespace="http://example.com/stockquote.xsd"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="literal" namespace="http://example.com/stockquote.xsd"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="StockQuoteService">
<documentation>My first service</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://example.com/stockquote"/>
</port>
</service>
</definitions>
1.2 符号约定
1.本文档中出现的关键字"MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",和"OPTIONAL" 的解释与RFC-2119 [2]中的描述一致
2. 以下是全文中使用的名域前缀:
前缀 名域URI 定义
wsdl schemas.xmlsoap.org/wsdl/soap / WSDL框架下的WSDL名域
http schemas.xmlsoap.org/wsdl/http / HTTP GET & POST绑定的WSDL前缀
mime schemas.xmlsoap.org/wsdl/mime / MIME绑定的WSDL前缀
xsi www.w3.org/1999/XMLSchema-instance 根据XSD[11]定义的文档实例的名域.
xsd www.w3.org/1999/XMLSchema 根据XSD [11]中定义的Schema名域
tns (任意) 当前文档的名域
(其他) (任意) 其他用作范例的名域
3. 本规范使用一种非正规的语法来描述WSDL文档的XML语法:
语法以XML文档实例的形式出现,但文档的值表示的是数据类型而不是值。
在文档和属性后可能出现的字符为"?" (0次或者1次), "*" (0次或者多次), "+" (1次或者多次)
元素名以“...”结束(比如: <element…/> or <element…>)表示与上下文无关的元素或者属性被省略。
粗体表示的语法或者是以前的文档中没有出现过的内容或者是需要特别关注的内容。
<-- extensibility element --> 是为其他名域元素保留的占位符(如XSD中的##other)
XML名域前缀(定义如上)用于表示所定义的元素的名域。
只有以 <?xml 开始的例子是和符合本规范的例子,其他的例子都不是完全的。
XSD schemas 用于正式定义WSDL语法:
2. Service Definition服务定义
这一节描述WSDL语言的核心元素。对SOAP HTTP MIME的扩展将在第三、四、五节中论述。
2.1 WSDL Document Structure WSDL文档结构
一个WSDL文档可以简单的认为是一个定义集。definitions元素作为根元素,服务定义在文档内部。WSDL文档的语法如下:
<wsdl:definitions name="nmtoken"? targetNamespace="uri"?>
<import namespace="uri" location="uri"/>*
<wsdl:documentation…/> ?
<wsdl:types> ?
<wsdl:documentation…/>?
<xsd:schema…/>*
<-- extensibility element --> *
</wsdl:types>
<wsdl:message name="nmtoken> *
<wsdl:documentation…/>?
<part name="nmtoken" element="qname"? type="qname"?/> *
</wsdl:message>
<wsdl:portType name="nmtoken">*
<wsdl:documentation…/>?
<wsdl:operation name="nmtoken">*
<wsdl:documentation…/> ?
<wsdl:input name="nmtoken"? message="qname">?
<wsdl:documentation…/> ?
</wsdl:input>
<wsdl:output name="nmtoken"? message="qname">?
<wsdl:documentation…/> ?
</wsdl:output>
<wsdl:fault name="nmtoken" message="qname"> *
<wsdl:documentation…/> ?
</wsdl:fault>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="nmtoken" type="qname">*
<wsdl:documentation…/>?
<-- extensibility element --> *
<wsdl:operation name="nmtoken">*
<wsdl:documentation…/> ?
<-- extensibility element --> *
<wsdl:input name="nmtoken"?> ?
<wsdl:documentation…/> ?
<-- extensibility element -->
</wsdl:input>
<wsdl:output name="nmtoken"?> ?
<wsdl:documentation…/> ?
<-- extensibility element --> *
</wsdl:output>
<wsdl:fault name="nmtoken"> *
<wsdl:documentation…/> ?
<-- extensibility element --> *
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="nmtoken"> *
<wsdl:documentation…/>?
<wsdl:port name="nmtoken" binding="qname"> *
<wsdl:documentation…/> ?
<-- extensibility element -->
</wsdl:port>
<-- extensibility element -->
</wsdl:service>
<-- extensibility element --> *
</wsdl:definitions>
服务主要使用以下5个元素:
types, 消息的数据类型定义通常用来描述所交换的消息。
message, 代表待传输数据的抽象定义。一条message(消息)由逻辑上的消息构件(part)组成,每一个构件(part)使用某种类型系统来定义。
portType,是一个抽象的操作(operation)的集合。每一个operation 指向一条输入消息(message)和输出消息(message).
binding, 它表述operation和message的具体的协议和数据格式规范。如前所述,operation 和message由porttype定义。
port,它指定一个用于绑定的地址,由此定义一个通讯端点(endpoint)
service, 用于表示由相关的port集成的服务
这些元素将在2.2-2.7节中详细论述。本节的剩余部分我们着重论述WSDL中命名文档、引用文档定义、使用语言扩展和增加辅助性文档的规则。
2.1.1 文档的命名和连接
WSDL文档可以赋给一个类型是NCNAME的name属性,该属性是可选的,可以作为一个轻量级的注解文档(documentation)。同样,也可以指定类型URI的targetNamespace属性。这个URI不能是相对URI。
WSDL allows associating a namespace with a document location using an import statement:
WSDL允许通过import语句,关联一个有文档位置的名域。(译者注:这里的描述我们认为是不恰当的,我们理解的描述应该是:WSDL可以通过import元素将其它的文档导入)。
<definitions…>
<import namespace="uri" location="uri"/> *
</definitions>
在WSDL中对QName的解析和在XML schema规范中论述的QName解析是类似的。[11]
可以通过使用一个QName来产生对WSDL定义的一个引用。在WSDL文档中如下的类型定义是可以被引用的:
WSDL 定义: service, port, message, bindings, 和 portType
其他定义:如果其他的定义是通过扩展性定义的,他们必需使用QName链接。
每一个WSDL定义类型都有自己的名辖域范围(即端口名和消息名永远不会冲突)。在同一个名辖域范围内的名必需是唯一的。
2.1.2 编写风格
使用import元素可以将不同的服务定义元素分别定义到不同的文档中。这有助于将服务按照抽象层次的不同分别定义,从而使服务定义更加清晰。另外这也使得各种服务定义能够最大程度被重用。因此WSDL文档可以更好地使用和维护。范例2是范例1的翻版,但是在定义服务的过程中使用了上述的编写风格。这里将服务定义文档分成三个文档:数据类型定义,抽象定义和特定服务绑定。当然使用上述机制定义服务文档不必按部就班于范例2的方式,在例2中仅仅使用了在WSDL规范中出现的元素,对于基于语言扩展定义的其他类型同样可以用这种体例编码和重用。
Example 2. Example 1的另一种编写风格.
example.com/stockquote/stockquote.xsd
<?xml version="1.0"?>
<schema targetNamespace="http://example.com/stockquote/schemas"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="GetLastTradePrice">
<complexType>
<all>
<element name="tickerSymbol" type="string"/>
</all>
</complexType>
</element>
<element name="GetLastTradePriceResult">
<complexType>
<all>
<element name="result" type="float"/>
</all>
</complexType>
</element>
</schema>
example.com/stockquote/stockquote.wsdl
<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote/definitions"
xmlns:tns="http://example.com/stockquote/definitions"
xmlns:xsd1="http://example.com/stockquote/schemas"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<import namespace="http://example.com/stockquote/schemas"
location="http://example.com/stockquote/stockquote.xsd"/>
<message name="GetLastTradePriceRequest">
<part name="body"element="xsd1:GetLastTradePrice"/>
</message>
<message name="GetLastTradePriceResponse">
<part name="body"element="xsd1:GetLastTradePriceResult"/>
</message>
<portType name="StockQuotePortType">
<operation name="GetLastTradePrice">
<input message="tns:GetLastTradePriceRequest"/>
<output message="tns:GetLastTradePriceResponse"/>
</operation>
</portType>
</definitions>
example.com/stockquote/stockquoteservice.wsdl
<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote/service"
xmlns:tns="http://example.com/stockquote/service"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<import namespace="http://example.com/stockquote/definitions"
location="http://example.com/stockquote/stockquote.wsdl"/>
<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="document"/>
<operation name="GetLastTradePrice">
<soap:operation soapAction="http://my.org/GetLastTradePrice"/>
</operation>>
</binding>
<service name="StockQuoteService">
<documentation>My first service</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://my.org/stockquote"/>
</port>
</service>
</definitions>
2.1.3 语言的可扩展性和绑定
在WSDL中,绑定(binding)表示将特定的协议或者数据格式信息与抽象的实体比如消息,操作或者端口类型关联的过程。通过WSDL定义的不同的元素,WSDL允许用元素代表某种特定的技术(这里所指的元素是指扩展元素)。这种扩展方式比较典型的应用场合就是为特定协议或者消息格式指定绑定信息,当然还有别的应用场合。扩展元素必需使用和WSDL不同的名域。在附录A3中还说明了扩展元素在WSDL文档中允许出现的位置是什么。
扩展元素经常用于指定某种特定的绑定技术。为了在通讯中区分绑定技术的语义是不是必需的,扩展元素可以使用一个布尔类型属性wsdl:required来表明。该属性默认值为false。该属性具体在名域"http://schemas.xmlsoap.org/wsdl/soap/"中定义。
扩展元素的例子见3,4,5节。
2.1.4 Documentation注释文档
WSDL使用一个可选的wsdl:document元素用于容纳对人提供帮助信息的注释文档。该元素的内容是任意的文本或者元素(即在XSD中的混合类型)。该元素允许在任何WSDL语言的元素中出现。
2.2 Types类型
type元素封装了与被交换消息相关的数据类型的定义。出于最大化互操作性和平台独立的考虑,WSDL偏向于使用XSD作为规范的类型系统,并将它看作固有的类型系统。
<definitions…>
<types>
<xsd:schema…/>*
</types>
</definitions>
XSD类型系统可以用于定义消息中的类型而不关心最终实现的数据格式是否为XML形式,以及是否对最终的数据用XSD schema校验。使用XSD类型系统在某些场合下是非常必要的,比如对同一条消息需要多种绑定或者对同一消息只有一种绑定但这种绑定类型还没有一个广为流传的类型系统。在这些情况下,使用XSD对抽象类型编码的最佳方式是:
仅使用元素(不使用属性)
不包括仅在特殊的协议和数据格式中使用的元素或者属性(也就是说与消息的抽象内容无关的属性和元素)。
对数组类型使用Soap:Array 类型。(不管结果形式是否使用第5节SOAP1.1所叙述的编码)。使用ArrayOfXXX作为数组类型的名(这里表示数组项的类型)
然而,不能指望单单一个类型系统语法来描述所有现在和将来的抽象类型,因此WSDL允许通过扩展元素增加其他类型系统。type元素可以有一个扩展子元素用于表示需要使用的类型系统定义和作为类型定义的XML容器元素。这个元素的作用类似与在schema中出现的schema元素。
<definitions…>
<types>
<-- type-system extensibility element --> *
</types>
</definitions>
2.3 消息
消息由一个或者多个的逻辑构件(part)构成。每一构件都与某一类型系统中的类型相关联,构件通过消息类型属性(message-typing attributes)来指定类型。消息类型属性集是可扩展的。WSDL使用XSD定义了一些消息类型属性:
element元素. 指使用合格名的一个XSD元素
type类型. 指一个使用合格名标识XSD简单类型或者复杂类型
(译者注:这里的元素和类型都是属性,具体地说都是part元素的属性,该属性可以用于指定part元素的数据类型)。
其它消息类型属性同样可以定义,只要它们使用不同于WSDL的名域。绑定扩展元素同样可以使用消息类型属性。
以下表示定义一条消息的语法。消息类型属性(视类型系统的不同而有可能不同)用粗体表示。
<definitions…>
<message name="nmtoken"> *
<part name="nmtoken"? element="qname" type="qname"?/> *
</message>
</definitions>
在WSDL文档内消息通过name属性区分。
在同一条消息内,消息构件通过name属性区分。
2.3.1消息构件
构件是一种用于描述消息的抽象逻辑内容的灵活机制。一个绑定有可能引用消息构件的名以便指明这个构件的与绑定相关的信息。例如,如果定义一条用于RPC的消息,一个消息构件可能表示消息中的一个参数。然而,要了解这个部分的真实含义却必须对绑定进行检查。
如果消息具有多个逻辑单位,则需要使用多个part元素。例如下列的消息就是由一个订单构件和顾客构件组成。
<definitions…>
<types>
<schema…>
<element name="PO" type="tns:POType"/>
<complexType name="POType">
<element name="id" type="string/>
<element name="name" type="string"/>
<element name="items">
<complexType>
<element name="item" type="tns:Item" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
</element>
</complexType>
<complexType name="Item">
<element name="quantity" type="int"/>
<element name="product" type="string"/>
</complexType>
<element name="Customer" type="tns:CustomerType"/>
<complexType name="CustomerType">
<element name="name" type="string"/>
</complexType>
</schema>
</types>
<message name="PO">
<part name="po" element="tns:PO"/>
<part name="customer" element="tns:Customer"/>
</message>
</definitions>
但是,若消息内容非常复杂,则可以使用另一种语法即直接使用类型系统定义的方法来表述消息的复合结构。下面的例子中,体是一个订单或者一系列的顾客。
<definitions…>
<types>
<schema…>
<complexType name="POType">
<element name="id" type="string/>
<element name="name" type="string"/>
<element name="items">
<complexType>
<element name="item" type="tns:Item" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
</element>
</complexType>
<complexType name="Item">
<element name="quantity" type="int"/>
<element name="product" type="string"/>
</complexType>
<complexType name="CustomerType">
<element name="name" type="string"/>
</complexType>
<complexType name="Composite">
<choice>
<element name="PO" minOccurs="1" maxOccurs="1" type="tns:POType"/>
<element name="Customer" minOccurs="0" maxOccurs="unbounded" type="tns:CustomerType"/>
</choice>
</complexType>
</schema>
</types>
<message name="PO">
<part name="composite" type="tns:Composite"/>
</message>
</definitions>
2.3.2 抽象消息和具体消息
消息定义通常认为是消息内容的抽象定义。一个消息绑定描述了抽象消息内容到具体消息格式的映射。对某种或某些绑定而言,在有些情况下抽象定义与具体消息表示非常接近,这样的绑定不提供或很少提供映射的信息。而另外一些对同样消息的绑定却需要更多的映射信息。正是这个原因,抽象消息只有在具体对绑定检查的时候才知道消息“到底有多抽象”。
2.4 Port Types端口类型
一个端口类型是一个由抽象操作和抽象消息构成的有名称的集合。
<wsdl:definitions…>
<wsdl:portType name="nmtoken">
<wsdl:operation name="nmtoken"…/> *
</wsdl:portType>
</wsdl:definitions>
在WSDL中,端口类型由它的name属性值区分。
操作通过name属性命名。
WSDL具有端点(endpoint)支持的4种原子传输方式
One-way单向.端点接收一条消息
Request-response请求-应答.端点接收一条消息,并发送一条相关消息。
Solicit-response要求-应答. 端点发送一条消息并接收一条相关消息。
Notification通知.端点发送一点消息
WSDL将这些原子操作看作operation.尽管请求/应答 要求/应答模式可以使用两个单向消息来替代,但仍将它们看作原子操作类型是因为:
它们非常普遍
不引入更复杂的流信息就可以将消息序列相互联系。
有些端点只能接收同步请求的回应消息。
从算法的角度上看如果有必要定义简单流,则它可以从这些原子操作中衍生出来。
尽管请求应答或者要求应答模式在WSDL文档中都是逻辑相关的,但具体的相关信息需在给定的绑定中描述。例如,请求和应答的消息可以作为一个或者两个实际的网络通讯的消息构件而进行交换。
操作中引用到的消息通过message属性指定。该属性服从WSDL定义的链接规则(见 2.1.2节)。
2.4.1 单向操作
单向操作的语法是:
<wsdl:definitions…> <wsdl:portType…> *
<wsdl:operation name="nmtoken">
<wsdl:input name="nmtoken"? message="qname"/>
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>
input元素指定用于单向操作的抽象消息格式。
2.4.2 请求应答操作
请求应答操作的语法是:
<wsdl:definitions…>
<wsdl:portType…> *
<wsdl:operation name="nmtoken" parameterOrder="nmtokens">
<wsdl:input name="nmtoken"? message="qname"/>
<wsdl:output name="nmtoken"? message="qname"/>
<wsdl:fault name="nmtoken" message="qname"/>*
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>
input和output元素分别指定请求和应答的抽象消息格式。可选的fault元素指定可能的任何错误消息,该消息可能作为操作的结果输出(抽象的错误消息,与协议和具体细节无关)。
注意请求应答操作是一个抽象的标记,一个特定的绑定必须明确怎样真正地发送消息:在同一个通讯连接中发送(比如HTTP的请求/应答)还是在两个独立的通讯连接中发送(比如两个独立的HTTP请求)。
2.4.3 要求-应答操作
要求-应答操作的语法是:
<wsdl:definitions…>
<wsdl:portType…> *
<wsdl:operation name="nmtoken" parameterOrder="nmtokens">
<wsdl:output name="nmtoken"? message="qname"/>
<wsdl:input name="nmtoken"? message="qname"/>
<wsdl:fault name="nmtoken" message="qname"/>*
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>
input和output 元素指定分别用于要求和应答的抽象消息格式。可选的fault元素指定可能的任何错误消息,该消息可能作为操作的结果输出(抽象的错误消息,与协议和具体细节无关)。
注意要求应答操作是一个抽象的标记,一个特定的绑定必须明确怎样真正发送消息:在同一个通讯连接中发送(比如HTTP的请求/应答)还是在两个独立的通讯连接中发送(比如两个独立的HTTP请求)。
2.4.4 通知操作
通知操作的语法是:
<wsdl:definitions…>
<wsdl:portType…> *
<wsdl:operation name="nmtoken">
<wsdl:output name="nmtoken"? message="qname"/>
</wsdl:operation>
</wsdl:portType >
</wsdl:definitions>
output元素指定用于通知操作的抽象消息格式。
2.4.5 操作内元素的名
在同一个端口类型范围内,所有的input和output元素各自通过元素名区分。
为了避免必须给操作内的每一个input和 output元素命名,WSDL提供了基于操作名的默认元素名.在单向传输或者是在通知方式的消息中,操作内元素的默认名是操作名,在另外两种方式下,input output元素的默认名是操作名分别加上 "Request"/"Solicit" 或者"Response"。
错误信息元素命名时必须允许一个绑定来指定错误信息的具体格式。在同一个操作内,出错信息元素名是唯一的。
2.4.6 操作内参数的顺序
操作并不明确规定它们是否能够应用到类似RPC的绑定中。但如果要在RPC绑定中使用操作,需要有一种方式能够表达RPC原来的结构。出于这个原因,请求应答和要求应答操作可以通过parameterOrder(nmtokens类型)指定一个参数名列表。该属性的值是一个用空格分开的消息构件名序列 。消息构件名必须满足以下的规则:
消息构件的序列必须反映RPC中参数的顺序
返回值消息构件在列表中不出现T
如果构件名同时在input和output消息中同时出现,它是一个in/out参数I
如果构件名只在in消息中出现,则它是一个传入参数I
如果构件名在output消息中出现,则它是一个传出参数
注意这些信息只作为“提示”,不关心RPC结构的应用完全可以忽略这些信息。同时,这些信息也不是必须的,甚至在类似RPC的绑定中,也可以不出现。
2.5 绑定
绑定定义了操作的消息格式和协议细节以及由端口类型定义的消息。对一个给定的端口类型,可以有任意数量的绑定。绑定的语法如下:
<wsdl:definitions…>
<wsdl:binding name="nmtoken" type="qname"> *
<-- extensibility element (1) --> *
<wsdl:operation name="nmtoken"> *
<-- extensibility element (2) --> *
<wsdl:input name="nmtoken"?> ?
<-- extensibility element (3) -->
</wsdl:input>
<wsdl:output name="nmtoken"?> ?
<-- extensibility element (4) --> *
</wsdl:output>
<wsdl:fault name="nmtoken"> *
<-- extensibility element (5) --> *
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
</wsdl:definitions>
WSDL文档内绑定通过name属性区分。
绑定通过type属性引用一个它绑定的端口类型。绑定的值服从在WSDL中定义的连接规则。(见2.1.2节)
绑定中出现的operation,input,output和fault元素与端口类型定义中的相应的元素关联,关联通过每个元素的name属性完成,在绑定中出现的这些元素具有和端口类型中定义的元素同样的行为。(见2.4.5节)
绑定扩展元素用于指定相应元素的具体语法,如input(3),output(4)和fault信息(5)。同时也可指定每个操作绑定信息(2)和绑定信息(1)。
绑定必需指定恰好一个协议。
绑定不可以指定地址信息。
2.6 端口
端口通过为绑定指定唯一地址的形式定义一个端点。
<wsdl:definitions…>
<wsdl:service…> *
<wsdl:port name="nmtoken" binding="qname"> *
<-- extensibility element (1) -->
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
在WSDL文档范围内,所有的端口使用name属性区别。
binding属性(类型)指向特定的绑定,在指向的关连规则在WSDL中定义(见 2.1.2节)
绑定扩展元素用于指定端口的地址信息。
端口不可以指定多个地址。
端口不可以指定处理地址信息以外的人很绑定信息。
2.7 服务
一个service将相关的端口组织在一起:
<wsdl:definitions…>
<wsdl:service name="nmtoken"> *
<wsdl:port…/>*
</wsdl:service>
</wsdl:definitions>
在WSDL范围内服务的name属性值是唯一的。
在一个服务内的端口具有如下的关系:
端口之间不相互通讯(即一个端口的输出不会是另一个端口的输入)
如果服务具有多个端口类型相同的端口,但他们对应不同的绑定或者地址,则这些端口是可替换的。每一个端口在语义上是等价的(在绑定施加给传输和消息格式的限制范围内)。这样就允许WSDL文档的用户可以根据一些选择标准(协议、距离等)选择特定的通讯端口。
通过检查服务的端口,我们可以确定服务的端口类型。这样就允许WSDL文档的使用者能够根据它支持的端口类型决定是否和一个特定的服务通讯。这在有些时候是非常有用的,比如在端口类型的操作之间有一些内在的联系,并且为了完成一个特定的任务所有的端口类型必需出现的情况下。
3. SOAP绑定
WSDL包括对SOAP1.1端点的绑定,它支持对与协议相关的信息作如下的设定:
表明绑定到SOAP1.1的标记
给SOAP端点指定地址
SOAP绑定到HTTP时需要指定SOAPAction HTTP头,该头是一个URI类型的值
对SOAP头的定义列表,该SOAP头将转化为SOAP封装(SOAP Envelope)
一个在XSD中指定SOAP根的方式
这里的绑定语法并不是一个最终的规范,因为SOAP绑定集还处在发展之中。相反额外的SOAP绑定可以从原来的语法部分中无限制的衍生出来,例如:
通过替换soap:address元素(在 section 3.8定义),不使用URI定位模式的SOAP绑定可以使用其他的定位模式
不需要SOAPAction的SOAP绑定可以忽略在3.4节中定义的soapaction属性。
3.1 SOAP 范例
在下列例子中,一个 SubscribeToQuotes SOAP 1.1单向(one-way)消息通过SMTP绑定发送到StockQuote服务中。请求带一个字符串类型的交易标记,同时还包括一个头,该头定义了发送者的URI
范例 3. 在SMTP之上的单向(one-way)操作的SOAP绑定,使用SOAP头
<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<message name="SubscribeToQuotes">
<part name="body" element="xsd1:SubscribeToQuotes"/>
</message>
<portType name="StockQuotePortType">
<operation name="SubscribeToQuotes">
<input message="tns:SubscribeToQuotes"/>
</operation>
</portType>
<binding name="StockQuoteSoap" type="tns:StockQuotePortType">
<soap:binding style="document" transport="http://example.com/smtp"/>
<operation name="SubscribeToQuotes">
<input message="tns:SubscribeToQuotes">
<soap:header element="xsd1:SubscriptionHeader"/>
</input>
</operation>
</binding>
<service name="StockQuoteService">
<port name="StockQuotePort" binding="tns:StockQuoteSoap">
<soap:address location="mailto://subscribe@example.com"/>
</port>
</service>
<types>
<schema targetNamespace="http://example.com/stockquote.xsd"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="SubscribeToQuotes">
<complexType>
<all>
<element name="tickerSymbol" type="string"/>
</all>
</complexType>
</element>
<element name="SubscriptionHeader" type="uriReference"/>
</schema>
</types>
</definitions>
这个例子描述了一个 GetLastTradePrice SOAP 1.1 请求,该请求可能通过SOAP 1.1 HTTP绑定发送到StockQuote服务。请求带一个字符串类型交易标记,一个时间实例(timeInstant)类型的时间,请求在SOAP应答中返回一个浮点数的价格。
范例 4. 在HTTP之上的请求应答RPC操作的SOAP绑定
<?xml version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<message name="GetLastTradePriceRequest">
<part name="tickerSymbol" element="xsd:string"/>
<part name="time" element="xsd:timeInstant"/>
</message>
<message name="GetLastTradePriceResponse">
<part name="result" type="xsd:float"/>
</message>
<portType name="StockQuotePortType">
<operation name="GetLastTradePrice">
<input message="tns:GetLastTradePriceRequest"/>
<output message="tns:GetLastTradePriceResponse"/>
</operation>
</portType>
<binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetLastTradePrice">
<soap:operation soapAction="http://example.com/GetLastTradePrice"/>
<input>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="http://example.com/stockquote"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>>
</binding>
<service name="StockQuoteService">
<documentation>My first service</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://example.com/stockquote"/>
</port>
</service>
</definitions>
3.2 SOAP绑定如何扩展WSDL
SOAP绑定扩展WSDL表现在以下新增的元素:
<definitions…>
<binding…>
<soap:binding style="rpc|document" transport="uri">
<operation…>
<soap:operation soapAction="uri"? style="rpc|document"?>?
<input>
<soap:body parts="nmtokens"? use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>
<soap:header element="qname" fault="qname"?>*
</input>
<output>
<soap:body parts="nmtokens"? use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>
<soap:header element="qname" fault="qname"?>*
</output>
<fault>*
<soap:fault name="nmtoken" use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>
</fault>
</operation>
</binding>
<port…>
<soap:address location="uri"/>
</port>
</definitions>
所有的SOAP绑定扩展元素在后续的章节中都会涉及。
3.3 soap:binding元素
SOAP binding 元素表明WSDL文档绑定到SOAP协议格式:封装,头,体等元素。这个元素没有声明消息的编码或者格式(举例来说,消息的编码和格式根据SOAP1.1规范的要求是必需的)。
该元素在使用SOAP绑定时是必需的。
<definitions…>
<binding…>
<soap:binding transport="uri"? style="rpc|document"?>
</binding>
</definitions>
sosp:binding 元素的style属性的值同时是它所包含的操作子元素的style属性的默认值。如果该属性省略,默认为"document"。关于style属性的语义的更多信息,见 3.4节。
transport属性是必需的,它的值表示绑定的传输方式与SOAP的何种传输方式一致。URI值http://schemas.xmlsoap.org/soap/http 表示传输方式和SOAP规范的HTTP绑定相一致。
3.4 soap:operation元素
该元素提供关于操作元素的整体信息。
<definitions…>
<binding…>
<operation…>
<soap:operation soapAction="uri"? style="rpc|document"?>
</operation>
</binding>
</definitions>
style属性表示操作是面向RPC(RPC-oriented 消息中包含参数和返回值)还是面向文档(document-oriented消息中包含文档)的。这些信息对选择一个合适的编程模型是由帮助的。如果该属性值没有指定,则默认与soap:binding元素的style值一致,如果在soap:binding中没有指定该属性值,则默认值是document。
soapAction属性指定SOAPAction头的值。该URI直接用作SOAPAciton头的值,不允许使用相对URI。对于SOAP的HTTP绑定,该属性值是必需的。对于SOAP的其他协议绑定,可以不指定,甚至soap:operation元素也可以省略。
3.5 soap:body元素
soap:body 元素指定消息构件在SOAP体元素中怎样出现。
消息构件有可能是抽象类型定义的也有可能是具体schema定义的。如果是抽象定义,则将根据编码风格定义的规则序列化这些类型。就象在SOAP规范中的一样,每一个编码风格用URI的列表区分。在某些编码风格比如SOAP的编码风格(http://schemas.xmlsoap.org/soap/encoding/)下,给定抽象类型集的消息格式允许一定的自由度,因此理解所有不同格式消息的任务就落到了读者的头上,这可以称之为:读者决定方式(读者读到所有的格式,并决定他能理解的格式,译者注)。为了避免需要支持所有的格式类型,消息可能具体地定义,并同时指定它的原始编码风格。在这种情况下,消息的写者必需确保消息与他指定的消息格式一致,这可以称之为:写者决定方式(写着决定选用那种编码风格,一旦决定选用某种方式,则需要在消息中指明这种方式,并严格按照这种格式写消息)。
soap:body元素可同时用于定义面向RPC和面向文档的消息。如果包含它的操作元素的style属性值是“rpc”,则所有的消息构件都是rpc的参数或者返回值,并且这些参数包裹在一个元素内出现在SOAP体中(见SOAP规范的7.1节)。如果style属性值是“document”,每一个消息构建是一个文档并直接出现在体元素中。上述的机制同时适用于这两个元素(体元素和包裹元素)的子元素。
<definitions…>
<binding…>
<operation…>
<input>
<soap:body parts="nmtokens"? use="literal|encoded"?
encodingStyle="uri-list"? namespace="uri"?>
</input>
<output>
<soap:body parts="nmtokens"? use="literal|encoded"?
encodingStyle="uri-list"? namespace="uri"?>
</output>
</operation>
</binding>
</definitions>
可选的nmtokens 类型的属性parts表示消息的哪些构件出现在SOAP体元素的消息部分中(其它的消息构件可能出现在其他消息部分中,比如SOAP绑定与MIME绑定合用的时候)。如果该part属性缺省,则默认所有在消息中定义的消息构件都出现在SOAP体元素部分中。
soap:body元素的必要属性use表示消息构件是使用某种编码方式编码,还是使用某种具体的消息类型。(该类型在本文档中定义,译者注)
如果use的值是encoded,则每一个消息构件通过类型属性引用抽象(消息)类型。encodingStyle属性的应用可以使抽象类型转变成具体的消息。构件的name types 属性以及namespace属性的都传入(消息构件的)编码中,这里namespace属性只应用到在构件内容没有被显式定义的抽象类型中。如果被引用的编码风格允许格式上的自由变化(例如SOAP的编码风格),则格式所有的可能形式都要被支持(读者决定方式)。
如果use属性值为lieteral,则每一个构件引用一个具体的schema,对简单的构件通过element属性引用,对复合的构件,则通过type属性引用。encodingstyle属性的值用于表示具体的格式可以衍生自一个特定的编码方式(比如SOAP编码),但这时只支持被指定的衍生方式(写者决定方式)。
属性encodingStyle的值是一个用空格分开的URI列表。URI表示的编码风格在该消息内被应用。列表顺序表明了对应编码风格的严格程度(与SOAP规范中定义的encodingStyle非常类似)。
3.6 soap:fault元素
soap:fault元素指定需要在SOAP 出错细节信息(SOAP Fault Details)元素的内容中出现的内容。该元素必需在soap:body元素之后出现(见 3.5节)。
<definitions…>
<binding…>
<operation…>
<fault>*
<soap:fault name="nmtoken" use="literal|encoded"
encodingStyle="uri-list"? namespace="uri"?>
</fault>
</operation>
</binding>
</definitions>
name属性将soap:fault元素和wsdl:fault元素关联。
fault消息必需有唯一一个消息构件。use,encodingStyle namespace属性同soap:body(见section 3.5 )。
3.7 soap:header元素
soap:header定义了在SOAP的头元素中出现的内容。在本节详尽地列出所有的头是没有必要的,因为在WSDL的其它规范中将头元素加入实际传输文档中是很正常的,显然没有必要将这些元素也列进来。
<definitions…>
<binding…>
<operation…>
<input>
<soap:header element="qname" fault="qname"?>*
</input>
<output>
<soap:header element="qname" fault="qname"?>*
</output>
</operation>
</binding>
</definitions>
element属性指向头元素具体的schema。头的schema可以不包括soap:actor soap:mustUnderstand属性的定义。
可选的fault属性(与element属性类似)可以为 header元素的出错信息指定具体的schema。SOAP规范规定头元素的出错信息必需在头元素中返回,fault属性允许为这些头元素规定schema.
3.8 soap:address
SOAP地址绑定用于给端口指定一个地址(URI)。使用SOAP绑定的端口必需指定且仅指定一个地址。
<definitions…>
<port…>
<binding…>
<soap:address location="uri"/>
</binding>
</port>
</definitions>
4. HTTP GET & POST 绑定
为了描述WEB浏览器和WEB服务器之间的交互。WSDL包含了一个对HTTP的GET和POST动词的绑定。该绑定同样允许非浏览器的应用与WEB 服务器之间的交互。在HTTP绑定中需要说明如下的与协议相关的信息:
一个HTTP绑定的标记
A 一个端口的地址
每个操作相对于端口地址的相对地址
4.1 HTTP GET/POST 范例
以下的范例表示将一个给定的端口类型绑定到不同的3个端口。
如果传递的值是part1=1, part2=2, part3=3,每一个端口请求格式将会是如下形式
port1: GET, URL="http://example.com/o1/A1B2/3"
port2: GET, URL="http://example.com/o1?p1=1&p2=2&p3=3
port3: POST, URL="http://example.com/o1", PAYLOAD="p1=1&p2=2&p3=3"
对于每一个端口,应答是一个GIF或者JPG
范例5. GET和FORM POST,返回一个GIF或JPG
<definitions…>
<message name="m1">
<part name="part1" type="xsd:string"/>
<part name="part2" type="xsd:int"/>
<part name="part3" type="xsd:string"/>
</message>
<message name="m2">
<part name="image" type="xsd:binary"/>
</message>
<portType name="pt1">
<operation name="o1">
<input message="tns:m1"/>
<output message="tns:m2"/>
</operation>
</portType>
<service name="service1">
<port name="port1" binding="tns:b1">
<http:address location="http://example.com/"/>
</port>
<port name="port2" binding="tns:b1">
<http:address location="http://example.com/"/>
</port>
<port name="port3" binding="tns:b1">
<http:address location="http://example.com/"/>
</port>
</service>
<binding name="b1" type="pt1">
<http:binding verb="GET"/>
<operation name="o1">
<http:operation location="o1/A(part1)B(part2)/(part3)"/>
<input>
<http:urlReplacement/>
</input>
<output>
<mime:content type="image/gif"/>
<mime:content type="image/jpeg"/>
</output>
</operation>
</binding>
<binding name="b2" type="pt1">
<http:binding verb="GET"/>
<operation name="o1">
<http:operation location="o1"/>
<input>
<http:urlEncoded/>
</input>
<output>
<mime:content type="image/gif"/>
<mime:content type="image/jpeg"/>
</output>
</operation>
</binding>
<binding name="b3" type="pt1">
<http:binding verb="POST"/>
<operation name="o1">
<http:operation location="o1"/>
<input>
<mime:content type="application/x-www-form-urlencoded"/>
</input>
<output>
<mime:content type="image/gif"/>
<mime:content type="image/jpeg"/>
</output>
</operation>
</binding>
</definitions>
4.2 HTTP GET/POST 如何扩展WSDL
HTTP GET/POST绑定通过如下的扩展元素扩展WSDL:
<definitions…>
<binding…>
<http:binding verb="nmtoken"/>
<operation…>
<http:operation location="uri"/>
<input…>
<-- mime elements -->
</input>
<output…>
<-- mime elements -->
</output>
</operation>
</binding>
<port…>
<http:address location="uri"/>
</port>
</definitions>
在后续章节中将会涉及这些元素。
4.3 http:address元素
location属性指定端口的基URI。该属性值和http:operation元素的location属性值结合。详情参见4.5节。
4.4 http:binding元素
http:binding元素表示绑定使用HTTP协议。
<definitions…>
<binding…>
<http:binding verb="nmtoken"/>
</binding>
</definitions>
verb属性是必需的,它的值对应HTTP的动词。通常情况下,值为GET和POST,但其它的动词也可能使用。注意HTTP动词是大小写敏感的。
4.5 http:operation元素
location属性指定该操作的相对URI,它和http:address元素的location属性结合表示完整的HTTP请求的URI。该属性值必需是相对URI.
<definitions…>
<binding…>
<operation…>
<http:operation location="uri"/>
</operation>
</binding>
</definitions>
4.6 http:urlEncoded
urlEncoded元素表示所有的消息构件使用标准的URI编码规则(name1=value&name2=value…)编入HTTP请求的URI。参数的名和消息构件的名一致。构成消息构件的每一个值都用name=value对的形式编码。这些值可以和GET一起使用用于指定URL编码,或者和POST一起表示一个FORM-POST。对于GET而言,如果有必要"?"字符会自动添加。
<http:urlEncoded/>
欲了解URI编码参数的更多的信息,见[5], [6], and [7]。
4.7 http:urlReplacement元素
http:urlReplacement元素表示所有的消息构件编码成HTTP请求的URI时使用替换算法。
根据一个搜索模式集合搜索http:operation的相对URI值
搜索的时机是在http:operation和http:address的location属性连接之前
所有消息构件都有一个统一的搜索模式 。表示搜索模式的字符串是括号括住的消息构件名(比如<http:operation location="o1/A(part1)B(part2)/(part3)"/>中的part1等,译者注)
匹配在任何值被替换以前执行(即替换的值不触发额外的匹配)
对每个匹配,对应的消息构件的值在该匹配所在的位置被替换
消息构件值不能重复。
<http:urlReplacement/>(为了更好的理解http:urlReplacement http:encoded,请仔细体会http绑定的例子,译者注)
5. MIME 绑定
WSDL还支持MIME格式的消息绑定。绑定为如下的MIME类型给出了定义:
multipart/related
text/xml
application/x-www-form-urlencoded (用于提交HTML表单的格式t)
Others (通过指定MIME类型)
MIME中定义的类型集合不但很大而且不够稳定,在必要的情况下可以补充额外的定义额外的MIME类型和为定义该类型而增加的语法。因此WSDL的目的并不在于为每一个MIME类型定义相应的XML语法。如果一个MIME类型串有足够的能力描述内容,则以下定义的mime元素可以得到应用。
5.1 MIME 绑定范例
范例 7. 在SOAP中使用 multipart/related with SOAP
这个例子描述了一个SOAP1.1的GetCompanyInfo请求,该请求通过SOAP1.1的HTTP绑定发送到StockQuote服务。请求附带一个字符串类型的交易标记。应答包含多个使用MIME格式 multipart/related编码的消息构件:即一个SOAP封装包含浮点类型的股票价格,零个或多个营销性质的HTML文档,甚至一个可选的公司的LOGO,该LOGO可能是GIF或者是JPEG。
<definitions…>
<types>
<schema…>
<element name="GetCompanyInfo">
<complexType>
<all>
<element name="tickerSymbol " type="string"/>
</all>
</complexType>
</element>
<element name="GetCompanyInfoResult">
<complexType>
<all>
<element name="result" type="float"/>
</all>
</complexType>
</element>
<complexType name="ArrayOfBinary" base="soap:Array">
<all>
<element name="value" type="xsd:binary"/>
</all>
</complexType>
</schema>
</types>
<message name="m1">
<part name="body" element="tns:GetCompanyInfo"/>
</message>
<message name="m2">
<part name="body" element="tns:GetCompanyInfoResult"/>
<part name="docs" type="xsd:string"/>
<part name="logo" type="tns:ArrayOfBinary"/>
</message>
<portType name="pt1">
<operation name="GetCompanyInfo">
<input message="m1"/>
<output message="m2"/>
</operation>
</portType>
<binding name="b1" type="tns:pt1">
<operation name="GetCompanyInfo">
<soap:operation soapAction="http://example.com/GetCompanyInfo"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<mime:multipartRelated>
<mime:part>
<soap:body parts="body" use="literal"/>
</mime:part>
<mime:part>
<mime:content part="docs" type="text/html"/>
</mime:part>
<mime:part>
<mime:content part="logo" type="image/gif"/>
<mime:content part="logo" type="image/jpeg"/>
</mime:part>
</mime:multipartRelated>
</output>
</operation>
</binding>
<service name="CompanyInfoService">
<port name="CompanyInfoPort"binding="tns:b1">
<soap:address location="http://example.com/companyinfo"/>
</port>
</service>
</definitions>
5.2 MIME如何扩展WSDL
MIME绑定对WSDL的扩展通过如下的扩展元素表现:
<mime:content part="nmtoken"? type="string"?/>
<mime:multipartRelated>
<mime:part> *
<-- mime element -->
</mime:part>
</mime:multipartRelated>
<mime:mimeXml part="nmtoken"?/>
他们出现在WSDL文档中的如下位置:
<definitions…>
<binding…>
<operation…>
<input…>
<-- mime elements -->
</input>
<output…>
<-- mime elements -->
</output>
</operation>
</binding>
</definitions>
MIME元素在input和output元素中出现。如果多次出现,则可以替换(例如上例定义的LOGO就出现了两个可选MIME元素,这时发送的数据可以是GIF或者是JPEG,译者注)。
5.3 mime:content元素
为了避免为每一个MIME格式定义一个新的元素,在没有额外的关于格式(MIME类型串除外)的信息需要发送时,可以使用mimi:element元素。
<mime:content part="nmtoken"? type="string"?/>
part属性用于指定消息构件。如果消息只有一个构件(例如单向操作的场合,译者注),则该属性可选。type属性包含MIME类型串。一个类型值有两个部分,中间用“/”分开,两个部分都可能是*。如果没有指定type属性值,则所有的MIME类型都允许。
如果返回格式是XML文档,但返回文档的schema在事先不知道(即文档是无法事先校验的,译者注)则可以使用通用的mime元素,它表示类型值为text/xml:
<mime:content type="text/xml"/>
*用于表示一个mime类型族,例如所有的文本类型可以这样表示:
<mime:content type="text/*"/>
The following two examples both specify all mime types:
下面的两个例子都指定了所有的mime类型
<mime:content type="*/*"/>
<mime:content/>
5.4 mime:multipartRelated元素
multipart/related MIME类型将任意的MIME格式化的消息构件并成一个消息。mime:multipartRelated 元素描述了类似消息的具体的格式。
<mime:multipartRelated>
<mime:part> *
<-- mime element -->
</mime:part>
</mime:multipartRelated>
mime:part元素描述了 multipart/related消息的每个构件。MIME元素出现在mime:part元素内,用于指定指定消息构件的具体的MIME类型。如果在一个mimi:part元素内出现多个MIME元素,则这些元素是可以相互替换的。
5.5 soap:body元素
在SOAP请求中使用MIME绑定的情况下,将soap:element元素用作一个MIME元素是合法的。它还表示内容的类型是“text/xml”并且有一个SOAP封装元素。
5.6 mime:mimeXml元素
mime:mimeXml元素在这样的场合下使用:需要使用XML的格式,并且有一个特殊的schema但不必兼容SOAP(即没有一个SOAP封装)。part属性指向一个消息构件,该消息构件定义了XML根元素的具体的schema。如果消息只有一个构件的话,该属性可以忽略。对简单类型的构件part通过element属性引用一个具体的schema,对复杂类型构件则通过type属性引用schema。
<绑定可以理解为文档的转化,即抽象定义服务的WSDL文档,转化为复合特定协议规范的字符串序列,如果转化以后的文档是XML文档,则甚至可以用XSLT实现,译者注>
<mime:mimeXml part="nmtoken"?/>
6. 参考文献
[2] S. Bradner, "Key words for use in RFCs to Indicate Requirement Levels", RFC 2119, Harvard University, March 1997
[4] T. Berners-Lee, R. Fielding, L. Masinter, "Uniform Resource Identifiers (URI): Generic Syntax", RFC 2396, MIT/LCS, U.C. Irvine, Xerox Corporation, August 1998.
[5] www.w3.org/TR/html401/interact/forms.html#submit-format
[6] www.w3.org/TR/html401/appendix/notes.html#ampersands-in-uris
[7] www.w3.org/TR/html401/interact/forms.html#h-17.13.4
[10] W3C Working Draft "XML Schema Part 1: Structures". This is work in progress.
[11] W3C Working Draft "XML Schema Part 2: Datatypes". This is work in progress.
A 1. Notes on URIs关于URI的解释
本节仅提供在实现本规范有益的一些背景,不对规范有任何实际的作用。
A 1.1 XML名域&schema定位
将XML schema的targetNamespace或者XML文档实例的xmlns属性值与相应的schema的定位等同起来是一个常见的误区。既然名域实际上是URI,而URI可能是定位,并且从该定位中获取schema也是可行的,但这并不意味着只有一个schema与该名域关联。有可能同时有多个schema与同一个特定的名域关联,并且在特定的处理场景中决定使用哪一个schema是XML处理器的职责。WSDL通过import机制提供处理这种场景,它来源于XMLschema的语法中的类似概念。
A 1.2 相对URI
在整个文档中,可以看到WSDL XSD文档中使用了完全合格的URI。使用完全合格的URI仅仅为了方便解释引用的概念。使用相对URI在很多情况下不但是允许的并且是合理的。欲知更多处理相对URI的信息,请参见http://www.normos.org/ietf/rfc/rfc2396.txt
A 1.3 产生URI
在WSDL中,有时候给实体虚构一个URI是非常需要的,但不用在所有时间都保证该URI全局唯一也不用保证它所有时候都有意义。有一个保留的URI基可以满足这样的需要。URI基http://tempuri.org/可用于构建一个没有唯一实体关联的URI。例如,两个用户或者程序可以同时使用URI tempuri.org/myschema 引用完全不同的schema,只要使用该URI的辖域不重叠,它们就认为是充分唯一的。这样作还有一个潜在的好处是被URI引用的实体可以版本化但不用产生更多的URI,只要在处理场景下可以理解。不推荐http://tempuri.org/作为一个稳定和固定的实体的URI引用基。
A 2. Wire format for WSDL examples
A 2.1. Example 1
SOAP Message Embedded in HTTP Request
POST /StockQuote HTTP/1.1
Host: www.stockquoteserver.com
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "Some-URI"
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<m:GetLastTradePrice xmlns:m="Some-URI">
<symbol>DIS</symbol>
</m:GetLastTradePrice>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
SOAP Message Embedded in HTTP Response
HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<SOAP-ENV:Body>
<m:GetLastTradePriceResponse xmlns:m="Some-URI">
<Price>34.5</Price>
</m:GetLastTradePriceResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
A 3.扩展性元素的位置
在WSDL文档中,扩展性元素可以出现在如下的位置
位置 含义 可能的用法
definitions 扩展性元素作为一个整体应用于这个WSDL文档 ? 作为一个整体介绍这个WSDL文档的附加信息和定义
definitions/types 扩展性元素是一个类型系统 ? 在XSD之外的类型系统中指定消息的格式
definitions/service 扩展性元素应用于一个服务 ? 介绍服务的附加信息或定义
definitions/service/port 扩展性元素应用于端口 ? 指定端口的地址
definitions/binding 扩展性元素作为一个整体应用于绑定 ? 为被绑定的端口类型中的所有操作提供特定协议的信息
definitions/binding/ operation 扩展性元素作为一个整体应用于操作 ? 提供应用于input消息和output消息的特定协议的信息
definitions/binding/ operation/input 扩展性元素应用于操作的input消息 ? 提供绑定时抽象消息构件映射到具体的协议和数据格式的细节
? 为input消息提供附加的特定协议信息
definitions/binding/ operation/output 扩展性元素应用于操作的output消息 ? 提供绑定时抽象消息构件映射到具体的协议和数据格式的细节
? 为output消息提供附加的特定协议信息
definitions/binding/ operation/fault 扩展性元素应用于操作的fault消息 ? 提供绑定时抽象消息构件映射到具体的协议和数据格式的细节
? 为fault消息提供附加的特定协议信息
--------------------------------------------------------------------------------
A 4. Schemas
A 4.1 WSDL Schema
<schema targetNamespace="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://www.w3.org/1999/XMLSchema"
elementFormDefault="qualified">
<element name="documentation" >
<complexType content="mixed">
<any minOccurs="0" maxOccurs="unbounded"/>
<anyAttribute/>
</complexType>
</element>
<complexType name="documented" abstract="true" content="elementOnly">
<element ref="wsdl:documentation"/>
</complexType>
<complexType name="openAtts" abstract="true" content="elementOnly">
<annotation>
<documentation>
This type is extended by component types
to allow attributes from other namespaces to be added.
</documentation>
</annotation>
<element ref="wsdl:documentation"/>
<anyAttribute namespace="##other"/>
</complexType>
<element name="definitions" type="wsdl:definitionsType">
<key name="message">
<selector>message</selector>
<field>@name</field>
</key>
<key name="portType">
<selector>portType</selector>
<field>@name</field>
</key>
<key name="binding">
<selector>binding</selector>
<field>@name</field>
</key>
<key name="service">
<selector>service</selector>
<field>@name</field>
</key>
<key name="import">
<!-- Is it too restrictive?-->
<selector>import</selector>
<field>@namespace</field>
</key>
<key name="port">
<selector>service/port</selector>
<field>@name</field>
</key>
</element>
<complexType name="definitionsType" base="wsdl:documented" derivedBy="extension">
<element ref="wsdl:import" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:types" minOccurs="0" maxOccurs="1"/>
<element ref="wsdl:message" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:portType" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:binding" minOccurs="0" maxOccurs="unbounded"/>
<element ref="wsdl:service" minOccurs="0" maxOccurs="unbounded"/>
<any namespace="##other" minOccurs="0" maxOccurs="unbounded">
<annotation>
<documentation>to support extensibility elements </documentation>
</annotation>
</any>
<attribute name="targetNamespace" type="uriReference" use="optional"/>
<attribute name="name" type="NMTOKEN" use="optional"/>
</complexType>
<element name="import" type="wsdl:importType" />
<complexType name="importType" base="wsdl:documented" derivedBy="extension" >
<attribute name="namespace" type="uriReference" use="required"/>
<attribute name="location" type="uriReference" use="required"/>
</complexType>
<element name="types" type="wsdl:typesType"/>
<complexType name="typesType" base="wsdl:documented" derivedBy="extension" >
<any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
<element name="message" type="wsdl:messageType">
<unique name="part">
<selector>part</selector>
<field>@name</field>
</unique>
</element>
<complexType name="messageType" base="wsdl:documented" derivedBy="extension">
<element ref="wsdl:part" minOccurs="0" maxOccurs="unbounded"/>
<attribute name="name" type="NCName" use="required"/>
</complexType>
<element name="part" type="wsdl:partType"/>
<complexType name="partType" base="wsdl:openAtts" derivedBy="extension">
<attribute name="name" type="NMTOKEN" use="optional"/>
<attribute name="type" type="QName" use="optional"/>
<attribute name="element" type="QName" use="optional"/>
</complexType>
<element name="portType" type="wsdl:portTypeType">
<key name="operation">
<selector>operation</selector>
<field>@name</field>
</key>
</element>
<complexType name="portTypeType" base="wsdl:documented" derivedBy="extension" content="elementOnly" >
<element ref="wsdl:operation" minOccurs="0" maxOccurs="unbounded"/>
<attribute name="name" type="NCName" use="required"/>
</complexType>
<element name="operation" type="wsdl:operationType">
<unique name="paramName">
<selector>input| output| fault</selector>
<field>@name</field>
</unique>
</element>
<complexType name="operationType" base="wsdl:documented" derivedBy="extension" >
<choice minOccurs="1" maxOccurs="1">
<group ref="wsdl:one-way-operation"/>
<group ref="wsdl:request-response-operation"/>
<group ref="wsdl:solicit-response-operation"/>
<group ref="wsdl:notification-operation"/>
</choice>
<attribute name="name" type="NCName" use="required"/>
</complexType>
<group name="one-way-operation">
<sequence>
<element ref="wsdl:input" />
</sequence>
</group>
<group name="request-response-operation">
<sequence>
<element ref="wsdl:input"/>
<element ref="wsdl:output"/>
<element ref="wsdl:fault" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</group>
<group name="solicit-response-operation">
<sequence>
<element ref="wsdl:output"/>
<element ref="wsdl:input" />
<element ref="wsdl:fault" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</group>
<group name="notification-operation">
<sequence>
<element ref="wsdl:output"/>
</sequence>
</group>
<element name="input" type="wsdl:paramType"/>
<element name="output" type="wsdl:paramType"/>
<element name="fault" type="wsdl:faultType"/>
<complexType name="paramType" base="wsdl:documented" derivedBy="extension" >
<attribute name="name" type="NMTOKEN" use="optional"/>
<attribute name="message" type="QName" use="required"/>
</complexType>
<complexType name="faultType" base="wsdl:documented" derivedBy="extension" >
<attribute name="name" type="NMTOKEN" use="required"/>
<attribute name="message" type="QName" use="required"/>
</complexType>
<complexType name="startWithExtensionsType" base="wsdl:documented" derivedBy="extension"
content="elementOnly" abstract="true">
<any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
<element name="binding" type="wsdl:bindingType"/>
<complexType name="bindingType" base="wsdl:startWithExtensionsType" derivedBy="extension"
content="elementOnly">
<element name="operation" type="wsdl:binding_operationType" minOccurs="0" maxOccurs="unbounded"/>
<attribute name="name" type="NCName" use="required"/>
<attribute name="type" type="QName" use="required"/>
</complexType>
<complexType name="binding_operationType" base="wsdl:startWithExtensionsType"
derivedBy="extension" content="elementOnly">
<element name="input" type="wsdl:startWithExtensionsType" minOccurs="0" maxOccurs="1"/>
<element name="output" type="wsdl:startWithExtensionsType" minOccurs="0" maxOccurs="1"/>
<element name="fault" minOccurs="0" maxOccurs="unbounded">
<complexType base="wsdl:startWithExtensionsType" derivedBy="extension">
<attribute name="name" type="NMTOKEN" use="required"/>
</complexType>
</element>
<attribute name="name" type="NCName" use="required"/>
</complexType>
<element name="service" type="wsdl:serviceType"/>
<complexType name="serviceType" base="wsdl:documented" derivedBy="extension" >
<element ref="wsdl:port" minOccurs="0" maxOccurs="unbounded"/>
<any namespace="##other" minOccurs="0" maxOccurs="1"/>
<attribute name="name" type="NCName" use="required"/>
</complexType>
<element name="port" type="wsdl:portType"/>
<complexType name="portType" base="wsdl:documented" derivedBy="extension">
<any namespace="##other" minOccurs="0" maxOccurs="1"/>
<attribute name="name" type="NCName" use="required"/>
<attribute name="binding" type="QName" use="required"/>
</complexType>
</schema>
A 4.2 SOAP Binding Schema
<schema targetNamespace="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="binding" type="soap:bindingType"/>
<complexType name="bindingType" content="empty">
<attribute name="transport" type="uriReference" use="optional"/>
<attribute name="style" type="soap:styleChoice" use="optional"/>
</complexType>
<simpleType name="styleChoice" base="string" derivedBy="restriction">
<enumeration value="rpc"/>
<enumeration value="document"/>
</simpleType>
<element name="operation" type="soap:operationType"/>
<complexType name="operationType" content="empty">
<attribute name="soapAction" type="uriReference" use="optional"/>
<attribute name="style" type="soap:styleChoice" use="optional"/>
</complexType>
<element name="body" type="soap:bodyType"/>
<complexType name="bodyType" content="empty">
<attribute name="encodingStyle" type="uriReference" use="optional"/>
<attribute name="parts" type="NMTOKENS" use="optional"/>
<attribute name="use" type="soap:useChoice" use="optional"/>
<attribute name="namespace" type="uriReference" use="optional"/>
</complexType>
<simpleType name="useChoice" base="string">
<enumeration value="literal"/>
<enumeration value="encoded"/>
</simpleType>
<element name="fault" type="soap:faultType"/>
<complexType name="faultType" base="soap:bodyType" derivedBy="restriction">
<attribute name="parts" type="NMTOKENS" use="prohibited"/>
</complexType>
<element name="header" type="soap:headerType"/>
<complexType name="headerType" content="empty">
<attribute name="element" type="QName" use="required"/>
<attribute name="fault" type="QName" use="optional"/>
</complexType>
<element name="address" type="soap:addressType"/>
<complexType name="addressType" content="empty">
<attribute name="location" type="uriReference" use="required"/>
</complexType>
</schema>
A 4.3 HTTP Binding Schema
<schema targetNamespace="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="address" type="http:addressType"/>
<complexType name="addressType" content="empty">
<attribute name="location" type="uriReference" use="required"/>
</complexType>
<element name="binding" type="http:bindingType"/>
<complexType name="bindingType" content="empty">
<attribute name="verb" type="NMTOKEN" use="required"/>
</complexType>
<element name="operation" type="http:operationType"/>
<complexType name="operationType" content="empty">
<attribute name="location" type="uriReference" use="required"/>
</complexType>
<element name="urlEncoded">
<complexType content="empty"/>
</element>
<element name="urlReplacement">
<complexType content="empty"/>
</element>
</schema>
A 4.4 MIME Binding Schema
<schema targetNamespace="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns="http://www.w3.org/1999/XMLSchema">
<element name="content" type="mime:contentType"/>
<complexType name="contentType" content="empty">
<attribute name="type" type="string" use="optional"/>
<attribute name="part" type="NMTOKEN" use="optional"/>
</complexType>
<element name="multipartRelated" type="mime:multipartRelatedType"/>
<complexType name="multipartRelatedType" content="elementOnly">
<element ref="mime:part" minOccurs="0" maxOccurs="unbounded"/>
</complexType>
<element name="part" type="mime:partType"/>
<complexType name="partType" content="elementOnly">
<any namespace="targetNamespace" minOccurs="0" maxOccurs="unbounded"/>
<attribute name="name" type="NMTOKEN" use="required"/>
</complexType>
<element name="mimeXml" type="mime:mimeXmlType"/>
<complexType name="mimeXmlType" content="empty">
<attribute name="part" type="NMTOKEN" use="optional"/>
</complexType>
</schema>