Namespace
<definitions>和子节点<schema>都是namespace属性:
<definitions name="FooSample"
targetNamespace="http://tempuri.org/wsdl/"
xmlns:wsdlns="http://tempuri.org/wsdl/"
xmlns:typens="http://tempuri.org/xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:stk="http://schemas.microsoft.com/soap-toolkit/wsdl-extension"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<schema targetNamespace="http://tempuri.org/xsd"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
elementFormDefault="qualified" >
</schema>
</types>
每个namespace属性都声明了一个缩略语,用在文档中。例如"xmlns:xsd"就为 http://www.w3.org/2001/XMLSchema定义了一个缩略语(xsd)。这就允许对该namespace的引用只需简单的在名字前加上前缀就可以了,如:"xsd:int"中的"xsd"就是合法的类型名。普通范围规则可运用于缩略前缀。也就是说,前缀所定义的元素只在元素中有效。
Namespace派什么用?namespace的作用是要避免命名冲突。如果我建立一项Web Service,其中的WSDL文件包含一个名为"foo"的元素,而你想要使用我的服务与另一项服务连接作为补充,这样的话另一项服务的WSDL文件就不能包含名为"foo"的元素。两个服务器程序只有在它们在两个事例中表示完全相同的东西时,才可以取相同的名字。如果有了表示区别的namespace,我的网络服务里的"foo"就可以表示完全不同于另一个网络服务里"foo"的含义。在你的客户端里,你只要加以限制就可以引用我的"foo"。
见下例:http://www.infotects.com/fooService#foo 就是完全限制的名字,相当于"carlos:foo",如果我声明了carlos作为http://www.infotects.com/fooService的快捷方式。请注意namespace中的URL是用来确定它们的唯一性的,同时也便于定位。URL所指向的地方不必是实际存在的网络地址,也可以使用GUID来代替或补充URL。例如,GUID"335DB901-D44A-11D4-A96E-0080AD76435D"就是一个合法的namespace指派。
targetNamespace属性声明了一个namespace,元素中所有的声明的名字都列于其内。在WSDL示例中,<definitions>的targetNamespace 是http://tempuri.org/wsdl。这意味着所有在WSDL文档中声明的名字都属于这个namespace。<schema>元素有自己的targetNamespace属性,其值为 http://tempuri.org/xsd ,在<schma>元素中定义的所有名字都属于这个namespace而不是main的target namespace。
<schema>元素的以下这行声明了默认的namespace。Schema中所有有效的名字都属于这个namespace。
xmlns=http://www.w3.org/2001/XMLSchema
SOAP消息
对于使用WSDL的客户机和服务机来说,研究WSDL文件的一种方法就是决定什么来接受所发送的信息。尽管SOAP使用底层协议,如IP和HTTP等,但应用程序决定了服务器与客户机之间交互的高级协议。也就是说,进行一项操作,比如"echoint"把输入的整数送回,参数的数目、每个参数的类型、以及参数如何传送等因素决定了应用程序特定的协议。有很多方法可以确定此类协议,但我相信最好的方法就是使用WSDL。如果我们用这种视角来看待它,WSDL不只是一种接口协议,而且是一种协议特定的语言。它就是我们超越"固定"协议(IP、HTTP等)所需要的应用程序特定协议。
WSDL可以确定SOAP消息是否遵从RPC或文档风格。RPC风格的消息(就是示例中所用的)看起来像是函数调用。而文档风格的消息则更普通,嵌套层次更小。下面的XML消息就是示例WSDL文件解析后的发送/接受效果,解析使用的是MS SOAP Toolkit 2.0(MSTK2)中的SoapClient对象。
从客户端调用"foo(5131953)"函数:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<m:foo xmlns:m="http://tempuri.org/message/">
<arg>5131953</arg>
</m:foo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
从服务器接受的信息:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<SOAPSDK1:fooResponse xmlns:SOAPSDK1="http://tempuri.org/message/">
<result>5131953</result>
</SOAPSDK1:fooResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
两函数都调用了消息,其回应是有效的XML。SOAP消息由几部分组成,首先是<Envelop>元素,包含一个可选的<Header>元素以及至少一个<body>元素。Rpc函数所调用的消息体有一个根据操作"foo"命名的元素,而回应信息体有一个"fooResponse"元素。Foo元素有一个部分<arg>,就和WSDL中描述的一样,是单参数的。fooResponse也相应的有一个<result>的部分。注意encodingStyle、envelope和message的namespace和WSDL Bindings栏中的预定义的一致,重复如下:
<binding name="SimpleBinding" type="wsdlns:SimplePortType">
<stk:binding preferredEncoding="UTF-8" />
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="foo">
<soap:operation
soapAction="http://tempuri.org/action/Simple.foo"/>
<input>
<soap:body use="encoded"
namespace="http://tempuri.org/message/"
encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/" />
</input>
<output>
<soap:body use="encoded"
namespace="http://tempuri.org/message/"
encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/" />
</output>
</operation>
</binding>