5-4-3 一般复合类型
在这里提到的编码规则不仅仅限于accessor名已知的情况,如果accessor名是运行环境下实时获得的,编码规则同样适用,也就是说accessor编码成一个元素名与accessor名匹配的元素,同时accessor可能包含或者引用该元素的值。如果accessor包含类型不能事先确定的值,它必须包含一个合适的属性xsi:type 。类似地,上述引用的规则已经足够用于复合类型的序列化,这些复合类型可能包含用名区分的accessors(结构)和用名及序数位置区分的accessors。(可能包含重复的accessor) 实际上这并不要求任何schema模式包含这些类型,但更为准确的说法是:一个类型模型(type-model)schema如果有这些类型,就可以构造一个符合XML句法规则的schema和XML文档实例。
<xyz:purchaseorder>
<CustomerName>Henry Ford</CustomerName>
<ShipTo>
<Street>5th Ave</Street>
<City>New York</City>
<State>NY</State>
<Zip>10010</Zip>
</ShipTo>
<PurchaseLineItems>
<Order>
<Product>Apple</Product>
<Price>1.56</Price>
</Order>
<Order>
<Product>Peach</Product>
<Price>1.48</Price>
</Order>
</PurchaseLineItems>
</xyz:PurchaseOrder>
类似地,将一个结构上类似数组但实际上不是一个 SOAP-enc:array类型或者 SOAP-enc:array子类型的复合值序列化同样是允许的,例如:
<purchaselineitems>
<Order>
<Product>Apple</Product>
<Price>1.56</Price>
</Order>
<Order>
<Product>Peach</Product>
<Price>1.48</Price>
</Order>
</PurchaseLineItems>
5-5 缺省值
省略accessor元素意味着或者有一个缺省值或者值不知道。具体细节依靠这个accessor,方法和上下文。例如,对于多态accessor,省略accessor一般意味着一个Null值。同样,省略布尔accessor一般意味着False值或者值不知道,省略数字accessor一般意味着值为零或者值不知道。
5-6 SOAP root属性
SOAP root 属性可用于标记一个序列化root,从而一个对象可以反序列化(deserialized),而实际上该root并不是真正的对象root。这个属性有两个可选值"1" or "0"。对象真正的roots属性值为“1” ,序列化root但不是真正的root属性值也为“1”,元素如果要显式地指定不能为序列化root,只需将该属性设置为“0” SOAP root属性可以出现在SOAP头和SOAP体元素的任意子元素中。SOAP root属性可以出现在SOAP头和SOAP体元素的任意子元素中。这个属性没有缺省值。
6·在HTTP中使用SOAP
这一节讲述了如何在HTTP中使用SOAP。把SOAP绑定到HTTP,无论使用或不用HTTP扩展框架,都有很大的好处:在利用SOAP的形式化和灵活性的同时,使用HTTP种种丰富的特性。在HTTP中携带SOAP消息,并不意味着SOAP改写了HTTP已有的语义,而是将构建在HTTP之上SOAP语义自然地对应到HTTP语义。SOAP自然地遵循HTTP的请求/应答消息模型使得SOAP的请求和应答参数可以包含在HTTP请求和应答中。注意,SOAP的中间节点与HTTP的中间节点并不等同,即,不要期望一个根据HTTP连接头中的域寻址到的HTTP中间节点能够检查或处理HTTP请求中的SOAP消息。
在HTTP消息中包含SOAP实体时,按照RFC2376 HTTP应用程序必须使用媒体类型 "text/xml"。
6-1 SOAP HTTP请求
虽然SOAP可能与各种HTTP请求方式相结合,但是绑定仅定义了在HTTP POST请求中包含SOAP消息。(第7节中描述了如何在RPC中使用SOAP,第6.3节描述了如何使用HTTP扩展框架)
6-1-1 HTTP头中SOAPaction域
一个HTTP请求头中的SOAPAction域用来指出这是一个SOAP HTTP请求,它的值是所要的URI。在格式、URI的特性和可解析性上没有任何限制。当HTTP客户发出SOAP HTTP请求时必须使用在HTTP头中使用这个域。
SOAPaction = "SOAPaction" ":" [ <"> uri-reference <"> ]
URI-reference = <as defined in RFC 2396 [4]>
http头中SOAPaction域使服务器(如防火墙)能正确的过滤http中SOAP请求消息。如果这个域的值是空字符串(""),表示SOAP消息的目标就是http请求的uri。这个域没有值表示没有SOAP消息的目标的信息。例子:
SOAPaction: "http://electrocommerce.org/abc#MyMessage"
SOAPAction: "myapp.sdl"
SOAPAction: ""
SOAPAction:
6-2 SOAP HTTP应答
SOAP HTTP遵循HTTP 中表示通信状态信息的HTTP状态码的语义。例如,2xx状态码表示这个包含了SOAP组件的客户请求已经被成功的收到,理解和接受。在处理请求时如果发生错误,SOAP HTTP服务器必须发出应答HTTP 500 "Internal Server Error",并在这个应答中包含一个SOAP Fault元素(见4.4节)表示这个SOAP处理错误。
6-3 HTTP扩展框架
一个SOAP消息可以与HTTP扩展框架一起使用以区分是否有SOAP HTTP请求和它的目标。是使用扩展框架或是普通的HTTP关系到通信各方的策略和能力。通过使用一个必需的扩展声明和"M-"HTTP方法名前缀,客户可以强制使用HTTP扩展框架。服务器可以使用HTTP状态码510 "Not Extended"强制使用HTTP扩展框架。也就是说,使用一个额外的来回,任何一方都可以发现另一方的策略并依照执行。用来表示SOAP使用了扩展框架的扩展标志符是http://schemas.xmlSOAP.org/SOAP/envelope/
6-4 SOAP HTTP举例
例3 使用POST的SOAP HTTP
post /stockquote http/1.1
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "http://electrocommerce.org/abc#MyMessage"
<SOAP-ENV:Envelope...
HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
<SOAP-ENV:Envelope...
例4 使用扩展框架的SOAP http
m-post /stockquote http/1.1
Man: "http://schemas.xmlSOAP.org/SOAP/envelope/";; ns=NNNN
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
NNNN-SOAPAction: "http://electrocommerce.org/abc#MyMessage"
<SOAP-ENV:Envelope...
HTTP/1.1 200 OK
ext:
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
<SOAP-ENV:Envelope...
7·在RPC中使用SOAP
设计SOAP的目的之一就是利用XML的扩展性和灵活性来封装和交换RPC调用。这一节定义了远程过程调用和应答的统一表示形式。虽然可以预计到这种表示形式最可能被用于与第5节中定义的编码方式相结合,但也可能有其它的表示形式。SOAP的encodingstyle属性(见4.3.2节)可以用来表明方法调用和应答都使用这一节所指定的表示方式。在RPC中使用SOAP和SOAP协议绑定(见第6节)是紧密相关的。在使用HTTP作为绑定协议时,一个RPC调用自然地映射到一个HTTP请求,RPC应答同样映射到HTTP应答。但是,在RPC中使用SOAP并不限于绑定HTTP协议。
要进行方法调用,以下的信息是必需的:
目标对象的URI
方法名
方法signature(可选)
方法的参数
头数据(可选)
SOAP依靠协议绑定提供传送URI的机制。例如,对HTTP来说,请求的URI指出了调用的来源 。除了必须是一个合法的URI之外,SOAP对一个地址的格式没有任何限制。
7-1 RPC和SOAP体
RPC方法调用和应答都包含在SOAP Body元素中(见4.3节),它们使用如下的表示形式:
一个方法调用用一个结构表示
一个方法调用被看作一个单个的结构,每个[in]和[in/out]参数有一个accessor。结构的名和类型与方法相同。每个[in]和[in/out]参数都被看作一个accessor,这个accessor的名和类型与参数的名和类型相对应。它们的出现顺序和方法中定义的参数顺序相同。
一个方法应答用一个结构表示
一个方法应答被看作一个单个的结构,返回值和每个[in]和[in/out]参数有一个accessor。第一个accessor是返回值,之后是参数accessor,参数accessor的出现顺序和方法中定义的参数顺序相同。每个参数accessor的名称和类型与参数的名称和类型相对应。返回值accessor的名称并不重要。同样,结构的名称也不重要,不过,通常在方法名称的后面加上字符串"Response"作为结构的名称。
方法错误使用SOAP Fault元素(见4.4节)表示。如果绑定的协议有额外的规则表示错误,则这些规则也必须要遵从。正如上面所述,方法调用和应答结构可以按照第5节中规则编码,或者用encodingstyle属性(见4.1.1节)指定编码方式。应用程序可以处理缺少参数的请求,但是可能返回一个错误。因为返回结果表示调用成功,错误表示调用失败,所以,在方法应答中同时包含返回结果和错误是错误的。
7-2 RPC和SOAP头
在RPC编码中,可能会有与方法请求有关但不是正规的方法Signature的附加信息。如果这样,它必须作为SOAP头元素的子元素。使用这种头元素的一个例子是在消息中传递事务ID。由于事务ID不是方法signature的一部分,通常由底层的组件而不是应用程序代码控制,所以没有一种直接的方法在调用中传递这个必要的信息。通过在头中添加一个给定名字的条目,接收方的事务管理器就可以析取这个事务ID,而且不影响远程过程调用的代码。