SOAP技术与B2B应用集成(4)

SOAP 技术与 B2B 应用集成( 4 )

SOAP 消息中的类型 / 值的编序方法和示例

本文最初由 IBM developerWorks 中国网站 发表,其网址是
http://www.ibm.com/developerWorks/cn/

在前面的文章 SOAP 的型系统和数据编码规则中,我们能了解到 SOAP 的类型和数据的编码是基于一个简单类型系统的,这个简单类型系统是基于程序语言、数据库和半结构数据中的类型系统的,是程序语言、数据库和半结构数据中类型系统的公共特性的一个泛化。在该简单类型系统中,一个类型要么是一个简单 ( 可量化的 ) 类型或是一个复合类型,这个复合类型由多个部分组成,每个部分是一个类型 ( 包括简单类型或复合类型 ) 。那么本文就分别针对简单类型和复合类型 ( 数组和结构 ) 来详细介绍类型和值的遍序方法,希望通过详尽的示例给读者以清晰的了解和掌握。

XML Schema 提供了一种灵活性很高,具备良好可扩展性的类型的定义描述方式。 SOAP 规范主要是采用 XML Schema 作为其类型模式的定义语言,当然由于 SOAP 是开放的,灵活的,也可以使用其他任意的模式定义的 XML Application 来制订特定应用的类型和值的描述。

简单类型

对于简单类型, SOAP 采用了在 “XML Schema Part 2: Datatypes” 的 “ 内置数据类型 Build-in datatypes” 中定义的所有类型,包括值和词汇空间 (lexical spaces) 。例子包括:

Type

|

Example

---|---

Int

|

58502

Float

|

314159265358979E+1

negativeInteger

|

-32768

String

|

Louis "Satchmo" Armstrong

在 XML Schema 规范中声明的数据类型可以直接在元素模式中使用。而源于这些类型的类型也可以被使用。下面是一个模式片段和相应类型元素数据的例子:

1<element name="quantity" type="int"></element>
1<element name="discount" type="float"></element>
1<element name="displacement" type="negativeInteger"></element>
1<element name="color">
2<simpletype base="xsd:string">
3<enumeration value="Green"></enumeration>
4<enumeration value="Blue"></enumeration>
5</simpletype>
6</element>
1<quantity>45</quantity>
1<discount>5.9</discount>
1<displacement>-450</displacement>
1<color>Blue</color>

无论简单值类型是在 “XML Schema Part 2: Datatypes” 规范中定义,还是基于 XML Schema 规范所提供的类型定义机制,都 必须 被编码为元素的内容。

如果一个简单值被编码为一个独立元素或一个异构数组的元素,这就意味着有一个对应于数据类型的元素声明。因为 “XML Schema Part 2: Datatypes” 规范中包含了类型定义,但没有包含对应元素的声明,而 SOAP-ENC 模式和命名空间为每个简单数据类型声明了一个元素。这些定义都是 可以 被使用的。

1<soap-enc:int id="int1">45</soap-enc:int>

字符串

“string” 数据类型在 “XML Schema Part 2: Datatypes” 中被定义。值得注意的是在许多数据库或编程语言中, “string” 类型并不是一致的,在某些特别的语言中,可能只允许一些字符能出现在 “string” 中。 ( 这些值可能需要表示为 xsd:string 之外的一些数据类型 )

一个字串 可以 被编码为一个单引用或多引用值。

包含 string 值的元素 可以 有一个 “id” 属性。额外的存取标识元素可以有匹配它的 “href” 属性。

例如,如果有两个对同一 string 的存取标识出现,则可以表现为:

1<payment id="String-0">USD$5000</payment>
1<cost href="#String-0"></cost>

无论如何,事实上对一个 string( 或者是 string 的子类型 subtypr) 的实例加以两个引用与将他们编码成两个单引用值并没有本质的区别:

1<payment>Hello</payment>
1<cost>Hello</cost>

对于这些例子的模式描述可能是:

1<element name="payment" type="SOAP-ENC:string"></element>
1<element name="cost" type="SOAP-ENC:string"></element>

( 在这个例子中,用于描述元素类型的 SOAP-ENC:string 类型是一个方便使用的方法,用这样一个定义来描述一个元素的类型是 “xsd:string” ,并且它可以附带 “id” 和 “href” 属性。大家可以参阅 SOAP Encoding Schema 来得到确切的定义。实例模式也 可以 使用这些 SOAP Encoding 模式中的声明,但这不是必须的。 )

枚举

“XML Schema Part 2: Datatypes” 规范定义了一种称为 “ 玫举 enumeration” 的机制。 SOAP 数据模型直接采用了这个机制。可是,由于编程语言及其他语言在定义玫举上存在着一些细微的差别,因此我们在这里描述了更详细的概念,并描述了如何将一个成为玫举列表成员的值进行编码。具体的,它编码为该值的名。

在概念上, “ 玫举 ” 表示了一组不同的名。一个具体的玫举是一个符合基本类型的不同值的具体列表。例如,颜色名 (“Green”, “Blue”, “Brown”) 的集合可以被定义为一个基于内置 string 类型的玫举 , 值 (“1”, “3”, “5”) 则可能是一个基于 integer 的玫举,等等。 “XML Schema Part 2: Datatypes” 规范支持除 boolean 外所有简单类型的玫举。 “XML Schema Part 2: Structures” 规范语言可以用于定义玫举类型。如果一个模式是从另一种符号体系生成过来而没有具体的基本类型可应用,那么就使用 “string” 。在下面的模式例子 “EyeColor” 被定义为一个 string 的玫举,其可能的值包括 “Green” 、 “Blue” 、 “Brown” ,同时实例数据也对应地被给出了。

1<element name="ProductColor" type="tns:ProductColor"></element>
1<simpletype base="xsd:string" name="ProductColor">
2<enumeration value="Green"></enumeration>
3<enumeration value="Blue"></enumeration>
4<enumeration value="Brown"></enumeration>
5</simpletype>
1<product>
2<name>Jaguar X-Type</name>
3<price>240000.00
4<productcolor>Brown</productcolor>
5</price></product>

Byte 数组

一个 Byte 数组可以编码为单引用或多引用值。 Byte 数组的编码规则与 string 是类似的。

特别的,包含 Byte 数组值的元素 可以 有一个 “id” 属性。额外的存取标识元素可以有一个用于匹配的 “href” 属性。

对一个不透明的 Byte 数组的推荐表示是使用在 XML Schema 规范中定义的 “base64” 编码方式,具体编码算法是在 RFC2045 中定义。不过, MIME 中 base64 编码数据的数据行长度限制在 SOAP 中将不存在。 SOAP 中应使用 “SOAP-ENC:base64” 子类型来定义 base64 编码。

1<picture xsi:type="SOAP-ENC:base64">   
2aG93IG5vDyBicm73biBjb3cNCg==   
3</picture>

多态存取标识

许多语言允许存取标识可以是多态地访问数个类型的值,在运行时刻每个类型都是可使用的。一个多态存取标识实例必须包含一个 “xsi:type” 属性以描述类型的实际值。

例如,一个名为 “cost” 带有类型为 “xsd:float” 的值的多态存取标识可以编码为:

1<cost xsi:type="xsd:float">29.95</cost>

与之相对的是一个值类型不变的 cost 存取标识。

1<cost>29.95</cost>

多态的具体表示将仅在实例中出现,但多态的定义是在模式中出现,即在模式中应不绑定任意具体类型。

复合类型

SOAP 依照在程序语言中常常看见的以下结构模式来定义复合类型:

** 结构 **

“struct 结构 ” 是一个复合类型值,其成员的存取标识名是相互区别的唯一标志,应彼此各不相同。

** 数组 **

“array 数组 ” 是一个复合类型值,其成员的顺序位置是相互区别的唯一标志。

复合值、结构和值的引用

复合值的成员被编码为存取标识元素。存取标识由他们的名字来相区别 ( 例如在 struct 里面 ) ,而元素名就是存取标识名。存取标识名是局部的,作用域是包含他们的类型中,具备一个未修饰的元素名,而其他则有完全修饰名。

下面是一个 “Book” 结构的例子:

1<e:book>
2<author>CHAI Xiaolu</author>
3<preface>Prefatory text</preface>
4<intro>This is a book.</intro>
5</e:book>

下面则是一个描述该结构的模式片段:

  1<element name="Book">
  2<complextype>
  3<element name="author" type="xsd:string"></element>
  4<element name="preface" type="xsd:string"></element>
  5<element name="intro" type="xsd:string"></element>
  6</complextype>
  7
  8
  9下面是一个即包含简单类型成员也包含复合类型成员的类型的例子。它显示了两层的引用。注意  “Author”  存取标识元素的  “href”  属性对匹配  “id”  值对应的值的引用。  “Address”  中的情况也是类似的。 
 10
 11<e:book>
 12<title>InterOP Stack Technology</title>
 13<author href="#Person-1"></author>
 14</e:book>
 15<e:person id="Person-1">
 16<name>CHAI Xiaolu</name>
 17<address href="#Address-2"></address>
 18</e:person>
 19<e:address id="Address-2">
 20<email>mailto:[email protected]</email>
 21<web>http://fennivel.xmlprobe.com</web>
 22</e:address>
 23
 24当  “Person”  和  “Address”  的值是需要多引用的时候,上述描述是合适的。如果使用单引用来描述,则 **应该** 是嵌入的,如下: 
 25
 26<e:book>
 27<title>InterOP Stack Technology</title>
 28<author>
 29<name>CHAI Xiaolu</name>
 30<address>
 31<email>mailto:[email protected]</email>
 32<web>http://fennivel.xmlprobe.com</web>
 33</address>
 34</author>
 35</e:book>
 36
 37如果这里存在着一个限制:在一个给出的实例中不允许有两个人有同样的地址,地址可以是一个街道地址  (Street-address)  ,也可以是一个电子地址  (Electronic-address)  。一本有两个作者的书可以编码为: 
 38
 39<e:book>
 40<title>InterOP Stack Technology</title>
 41<firstauthor href="#Person-1"></firstauthor>
 42<secondauthor href="#Person-2"></secondauthor>
 43</e:book>
 44<e:person id="Person-1">
 45<name>CHAI Xiaolu</name>
 46<address xsi:type="m:Electronic-address">
 47<email>mailto:[email protected]</email>
 48<web>http://fennivel.xmlprobe.com</web>
 49</address>
 50</e:person>
 51<e:person id="Person-2">
 52<name>Fennivel</name>
 53<address xsi:type="n:Street-address">
 54<street>Fennix 2000</street>
 55<city>Shanghai</city>
 56<state>Shanghai</state>
 57</address>
 58</e:person>
 59
 60编序也可以包含一些不在同一资源中的值的引用: 
 61
 62<e:book>
 63<title>Paradise Lost</title>
 64<firstauthor href="http://www.dartmouth.edu/~milton/"></firstauthor>
 65</e:book>
 66
 67同时下面是一个对上面结构的模式描述片段: 
 68
 69<element name="Book" type="tns:Book"></element>
 70<complextype name="Book">
 71<!-- Either the following group must occur or else the   
 72href attribute must appear, but not both. -->
 73<sequence maxoccurs="1" minoccurs="0">
 74<element name="title" type="xsd:string"></element>
 75<element name="firstauthor" type="tns:Person"></element>
 76<element name="secondauthor" type="tns:Person"></element>
 77</sequence>
 78<attribute name="href" type="uriReference"></attribute>
 79<attribute name="id" type="ID"></attribute>
 80<anyattribute namespace="##other"></anyattribute>
 81</complextype>
 82<element base="tns:Person" name="Person"></element>
 83<complextype name="Person">
 84<!-- Either the following group must occur or else the   
 85href attribute must appear, but not both. -->
 86<sequence maxoccurs="1" minoccurs="0">
 87<element name="name" type="xsd:string"></element>
 88<element name="address" type="tns:Address"></element>
 89</sequence>
 90<attribute name="href" type="uriReference"></attribute>
 91<attribute name="id" type="ID"></attribute>
 92<anyattribute namespace="##other"></anyattribute>
 93</complextype>
 94<element base="tns:Address" name="Address"></element>
 95<complextype name="Address">
 96<!-- Either the following group must occur or else the   
 97href attribute must appear, but not both. -->
 98<sequence maxoccurs="1" minoccurs="0">
 99<element name="street" type="xsd:string"></element>
100<element name="city" type="xsd:string"></element>
101<element name="state" type="xsd:string"></element>
102</sequence>
103<attribute name="href" type="uriReference"></attribute>
104<attribute name="id" type="ID"></attribute>
105<anyattribute namespace="##other"></anyattribute>
106</complextype>
107
108###  数组 
109
110SOAP  数组被定义为类型为  “SOAP-ENC:Array”  或类型源于  “SOAP-ENC:Array”[  参阅规则  8]  。数组被表示为对包含其的元素的名无特殊约束的元素值  (  就象元素的值一般不会约束元素的名  )  。 
111
112数组可以包含任意类型的元素,包括嵌套数组。由  SOAP-ENC:Array  的约束建立的新类型也可以被创建并表示,例如,数组可以限于整数或一些用户自定义玫举型的数组。 
113
114数组值的表示是一个有序序列,该有序序列由该数组组成元素序列化组成。作为一个数组的值,元素名对于区分存取标识并非重要。元素可以有任意的名。实际上,这些元素的命名将按照模式中声明的建议,或由他们的类型所决定。就象在复合类型中通常情况下,如果数组中条目的值是单引用值,则该条目将包含它的值。否则,条目通过  “href”  属性引用它的值。 
115
116下面是一个模式的片段以及一个包含  integer  成员的数组: 
117
118<element name="myFavoriteNumbers" type="SOAP-ENC:Array"></element>
119<myfavoritenumbers soap-enc:arraytype="xsd:int[2]">
120<number>3</number>
121<number>4</number>
122</myfavoritenumbers>
123
124在这个例子中,  “myFavoriteNumber”  包含了几个成员,每个成员的值的类型都是  SOAP-ENC:int  。而类型是由  SOAP-ENC:arrayType  属性决定的。注意  SOAP-ENC:Array  的类型允许不严格的未修饰的元素名。这些名只传输了非类型的信息,因此在具体使用的时候,要么有一个  xsi:type  属性,要么包含它的元素要包含一个  SOAP-ENC:arrayType  属性。自然地,源于  SOAP-ENC:Array  的类型可以声明带类型信息的局部元素。 
125
126就象先前指出的,  SOAP-ENC  模式包含了一些元素名的申明,而这些名是对应于  “XML Schema Part 2: Datatypes”  规范中的每个简单类型的。这也包含一个  “Array”  的声明。使用这些定义,我们也许可以将显现先前的描述改写为: 
127
128<soap-enc:array soap-enc:arraytype="xsd:int[2]">
129<soap-enc:int>3</soap-enc:int>
130<soap-enc:int>4</soap-enc:int>
131</soap-enc:array>
132
133数组可以包含任意指定  arrayType  的子类型的实例。也就是说,成员的类型可以是任何描述在  arrayType  属性中类型的可替代类型,这将依照于在模式中表示的可替代规则。因此,例如,一个整数数组可以包含任何源于  integer  的类型的值  (  例如  “int”  或任何用户定义的源于  integer  的类型  )  。类似的,一个  “address”  数组可以包含一个严格的或扩展的类型,比如  “internationalAddress”  。因为提供的  SOAP-ENC:Array  类型允许包含任何类型或类型混合的成员,除非有对  arrayType  属性使用的特别限制。 
134
135成员元素类型在实例中可以使用  xsi:type  来描述,或则是在成员元素模式中声明,就象在下面两个数组中分别演示的那样。 
136
137<soap-enc:array soap-enc:arraytype="xsd:ur-type[4]">
138<thing xsi:type="xsd:int">12345</thing>
139<thing xsi:type="xsd:decimal">6.789</thing>
140<thing xsi:type="xsd:string">   
141Of Mans First Disobedience, and the Fruit   
142Of that Forbidden Tree, whose mortal tast   
143Brought Death into the World, and all our woe,   
144</thing>
145<thing xsi:type="xsd:uriReference">   
146http://fennivel.xmlprobe.com/collection/   
147</thing>
148</soap-enc:array>
149<soap-enc:array soap-enc:arraytype="xsd:ur-type[4]">
150<soap-enc:int>12345</soap-enc:int>
151<soap-enc:decimal>6.789</soap-enc:decimal>
152<xsd:string>   
153Of Mans First Disobedience, and the Fruit   
154Of that Forbidden Tree, whose mortal tast   
155Brought Death into the World, and all our woe,   
156</xsd:string>
157<soap-enc:urireference>   
158http://fennivel.xmlprobe.com/collection/   
159</soap-enc:urireference>
160</soap-enc:array>
161
162数组值可以是结构或其他复合值。例如一个  “xyz:Order”  结构的数组: 
163
164<soap-enc:array soap-enc:arraytype="xyz:Order[2]">
165<order>
166<product>Apple</product>
167<price>1.56</price>
168</order>
169<order>
170<product>Peach</product>
171<price>1.48</price>
172</order>
173</soap-enc:array>
174
175数组也可以有一些成员值是数组。下面是一个有两个数组的数组的例子,而那两个数组都是  string  数组: 
176
177<soap-enc:array soap-enc:arraytype="xsd:string[][2]">
178<item href="#array-1"></item>
179<item href="#array-2"></item>
180</soap-enc:array>
181<soap-enc:array id="array-1" soap-enc:arraytype="xsd:string[2]">
182<item>r1c1</item>
183<item>r1c2</item>
184<item>r1c3</item>
185</soap-enc:array>
186<soap-enc:array id="array-2" soap-enc:arraytype="xsd:string[2]">
187<item>r2c1</item>
188<item>r2c2</item>
189</soap-enc:array>
190
191包含一个数组值的元素并不需要一定被命名为  “SOAP-ENC:Array”  。它可以有任意的名,而提供的类型则要么是  SOAP-ENC:Array  ,要么是受源于  SOAP-ENC:Array  的限制。例如,下面是一个模式片段以及与之一致的一个实例数组。 
192
193<simpletype base="string" name="phoneNumber"></simpletype>
194<element name="ArrayOfPhoneNumbers">
195<complextype base="SOAP-ENC:Array">
196<element maxoccurs="unbounded" name="phoneNumber" type="tns:phoneNumber"></element>
197</complextype>
198<anyattribute></anyattribute>
199</element>
200<xyz:arrayofphonenumbers soap-enc:arraytype="xyz:phoneNumber[2]">
201<phonenumber>206-555-1212</phonenumber>
202<phonenumber>1-888-123-4567</phonenumber>
203</xyz:arrayofphonenumbers>
204
205数组可以是多维的。在这种情况下,就会有多个描述维数大小的值出现在  arrayType  属性的  asize  部分。 
206
207<soap-enc:array soap-enc:arraytype="xsd:string[2,3]">
208<item>r1c1</item>
209<item>r1c2</item>
210<item>r1c3</item>
211<item>r2c1</item>
212<item>r2c2</item>
213<item>r2c3</item>
214</soap-enc:array>
215
216上述例子中显示了一个数组如何被编码为独立元素,数组值 **可以** 以嵌套方式出现,如果并且他们是单引用的话,建议是以嵌套方式出现。 
217
218下面是一个模式片段的例子以及符合该模式的一个嵌套在  “Person”  结构中的电话号码数组,该数组可以从存取标识  “phone-numbers”  访问。 
219
220<simpletype base="string" name="phoneNumber"></simpletype>
221<element name="ArrayOfPhoneNumbers">
222<complextype base="SOAP-ENC:Array">
223<element maxoccurs="unbounded" name="phoneNumber" type="tns:phoneNumber"></element>
224</complextype>
225<anyattribute></anyattribute>
226</element>
227<element name="Person">
228<complextype>
229<element name="name" type="string"></element>
230<element name="phoneNumbers" type="tns:ArrayOfPhoneNumbers"></element>
231</complextype>
232</element>
233<xyz:person>
234<name>John Hancock</name>
235<phonenumbers soap-enc:arraytype="xyz:phoneNumber[2]">
236<phonenumber>206-555-1212</phonenumber>
237<phonenumber>1-888-123-4567</phonenumber>
238</phonenumbers>
239</xyz:person>
240
241下面是单引用数组值的另一个例子,数组值被编码为嵌入元素,这些元素都包含作为存取标识的元素名。 
242
243<xyz:purchaseorder>
244<customername>Henry Ford</customername>
245<shipto>
246<street>5th Ave</street>
247<city>New York</city>
248<state>NY</state>
249<zip>10010</zip>
250</shipto>
251<purchaselineitems soap-enc:arraytype="Order[2]">
252<order>
253<product>Apple</product>
254<price>1.56</price>
255</order>
256<order>
257<product>Peach</product>
258<price>1.48</price>
259</order>
260</purchaselineitems>
261</xyz:purchaseorder>
262
263####  部分传递数组 
264
265SOAP  提供对部分传递数组的支持,这就象在一些场合下称作的  “  可变长  ”  数组。一个部分传递数组应使用  “SOAP-ENC:offset”  属性标识,该属性的记数是以第一元素的位移为  0  开始的。如果省略该属性,则位移默认是  0  。 
266
267下面是一个大小为  5  的数组,同时在传递的时候仅传递第三和第四个元素: 
268
269<soap-enc:array soap-enc:arraytype="xsd:string[5]" soap-enc:offset="[2]">
270<item>The third element</item>
271<item>The fourth element</item>
272</soap-enc:array>
273
274####  稀疏数组 
275
276SOAP  提供对稀疏数组的支持。每一个表示成员值的元素包含一个  “SOAP-ENC:position”  属性来表明它处于数组的位置。下面是一个二维字串数组的稀疏数组的例子。他的大小是  4  ,但仅有位置  2  被使用: 
277
278<soap-enc:array soap-enc:arraytype="xsd:string[,][4]">
279<soap-enc:array href="#array-1" soap-enc:position="[2]"></soap-enc:array>
280</soap-enc:array>
281<soap-enc:array id="array-1" soap-enc:arraytype="xsd:string[10,10]">
282<item soap-enc:position="[2,2]">Third row, third col</item>
283<item soap-enc:position="[7,2]">Eighth row, third col</item>
284</soap-enc:array>
285
286如果在上述数组中对  &lt;SPAN lang=EN-US</element>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus