五、SOAP编码
soap编码格式基于一个简单的类型系统。一个类型可以是一个简单类型,比如字符串、整数和枚举等,也可以是由几个部分组合而成的复合类型,其中,每个部分都有自己的类型,比如订单类和报表类等。
1、简单类型
soap采用xml架构规范中定义的内建数据类型作为它的简单类型,例如:200(int 类型)、355222E+1(float 类型)、-32768(negativeInteger 类型)和"Louis"(string 类型)等。
在soap中可以直接使用xml架构规范中声明的数据类型,也可以使用从这些类型派生的新类型。例如,下面给出了一个具有简单类型的架构文档:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="age" tyep="xs:int"/>
<xs:element name="height" type="xs:float"/>
<xs:element name="dispacement" type="xs:negativeInteger"/>
<xs:element name="color">
<xs:simpleType base="xsd:string">
<xs:restriction base="xs:string">
<xs:enumeration value="Green"/>
<xs:enumeration value="Blue"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:schema>
下面给出了符合上面架构文档的实例文档片段:
<age>45</age>
<height>5.9</height>
<displacement>450</displacement>
<color>Blue</color>
所有简单值必须编码为元素的内容,它的类型或者在xml架构规范中定义,或者是使用xml架构规范提供的机制进行派生。如果一个简单值编码为一个与名称无关的元素,则可以使用一个对应于数据类型的元素声明。(我理解,就是说,有一个值,不需要对应的名称,这时可以直接声明)。因为xml架构规范中包括了类型定义,但是没有包括对应的元素声明,所以,soap编码架构和命名空间为每一个简单数据类型声明了一个元素。例如下面的代码就是用了soap编码架构中声明的元素enc:int
<enc:int xmns:enc="http://www.w3.org.2001/12/soap-encoding" id="int1">45</enc:int>
2、字符串
字符串数据类型string在xml架构规范中定义。
字符串可以编码为一个单重引用或多重引用值。
包含字符串值的元素可以具有一个id属性,然后额外的访问器元素就可以具有与之匹配的href属性。例如,同一个字符串的两个访问器可能以如下形式出现:
<greeting id="String-0">Hello</greeting>
<salutation href="#String-0">
但是,如果两个访问器引用同一字符串实例,它们可以编码为两个单重应用的值,如:
<greeting>Hello</greeting>
<salutation>Hello</salutation>
下面的架构定义了上面两个例子中的元素(enc:string类型用作元素的类型,这是声明数据类型为"xsd:string"切允许id和href属性的元素的简便方法):
<?xml versino="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:enc="http://www.w3.org/2001/12/soap-encoding">
<xs:import namespace="http://www.w3.org/2001/12/soap-encoding"/>
<xs:element name="greeting" type="enc:string"/>
<xs:element name="salutation" type="enc:string"/>
</xs:schema>
3、枚举
xml架构规范中定义了一种称为枚举的机制。soap数据模型直接采用了这种机制。
枚举就是对应于特定基类型的不同值得列表。例如:
<?xml version="1.0"/>
<xs:schema xmlns:xs="http://wwww.w3.org/2001/XMLSchema"
xmlns:tns="http://example.org/2001/06/samples"
targetNamespace="http://example.org/2001/06/samples">
<xs:element name="EyeColor" type="tns:EyeColor"/>
<xs:simpleType name="EyeColor">
<xs:restriction base="xs:string">
<xs:enumeration value="Green"/>
<xs:enumeration value="Blue"/>
<xs:enumeration value="Brown"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
下面是符合上面架构的实例文档片段:
<p:EyeColor xmlns:p="http://example.org/2001/06/samples">Brown</p:EyeColor>
4、字节数组
字节数组可以编码为单重引用或多重引用。字节数组的编码规则与字符串的编码规则类似。特别的是,包含字节数组的元素可能具有一个id属性,然后而外的访问器元素就可以具有与之匹配的href属性。
推荐使用xml架构规范中定义的base64编码来表示字节数组。不过,MIME中的行长度限制不会应用到soap中。soap中使用"enc:base64"子类型。
5、多态访问器
许多语言允许能够多态访问多种类型值得访问器。一个多态访问器实例必须包含一个描述实际值得类型的xsi:type属性。例如,下面显示了一个名为"cost"具有"xsd:float"类型值得多态访问器:
<cost xmlns:xsi="http://www.w3.org/2001/XMLScheam-instance"
xmlsn:xs="http://www.w3.org/2001/XMLSchema"
xsi:type="xs:float">22.22</cost>
与其对照,具有固定值类型的访问器如下:
<cost>222.22</cost>
(不太明白,多态体现在哪里?)
6、复合类型
soap定义了两个复合类型:结构(struct)和数组(array)。在结构中,访问器只能够通过成员值来区分,并且它们的名称不能相同。在数组中,只能够使用成员的位置来区分成员值。
(1)结构
复合值的成员编码为访问器元素。当访问器通过名称区分时,访问器名称用作元素的名称。具有局部名称的访问器具有非限定名称,其他的访问器则具有限定名称。
下面的例子显示了一个类型为"Book"的结构:
<e:Book xmlns:e="http://example.org/2001/06/books">
<autor>Henry Ford</autor>
<preface>Prefactory text</preface>
<intro>This is a book</intro>
</e:Book>
下面是描述上面的结构的架构片段:
<xs:element name="Book"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType>
<xs:sequence>
<xs:element name="author" type="xs:string"/>
<xs:element name="preface" type="xs:string"/>
<xs:element name="intro" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
下面的例子中显示了一个同时具有简单和复杂成员的类型,它显示了两级引用。注意,Author访问器元素的href属性引用具有匹配id属性的值,Address访问器元素与之类似。
<e:Book xmlns:e="http://example.org/2001/06/books">
<title>My Life and Work</title>
<author href="#Person-1"/>
</e:Book>
<e:Person xmlns="http://example.org/2001/06/books"
id="Person-1">
<name>Henry Ford</name>
<address>#Address-2/>
</e:Person>
<e:Address xmlns="http://example.org/2001/06/books"
id="Address-2">
<email>mailto:henryford@hotmail.com</email>
<web>http://www.henryford.com</web>
</e:Address>
(2)数组
soap数组具有enc:Array类型或者它的派生类型。在数组值中,元素名不足以区分访问器,元素可以具有任意名称。实际上,架构中的元素名称通常可以提示或确定它们的值。如果一个数组项的值是单重引用值,则这个数组项包含它的值。否则,该数组项通过href属性应用它的值。
在下面的例子中,数组包含整数成员。
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:enc="http://www.w3.org/2001/12/soap-encoding">
<xs:import namespace="http://www.w3.org/2001/12/soap-encoding"/>
<xs:element name="myFavoriteNumbers" type="enc:Array"/>
</xs:schema>
上面的架构对应的数组实例如下:
<myFavoriteNumbers xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:enc="http://www.w3.org/2001/12/soap-encoding"
enc:arrayType="xs:int[2]">
<number>3</number>
<number>4</number>
</myFavoriteNumbers>
注意enc:Array类型允许任意命名空间中的限定元素名称和非限定元素名称,它们不传达任何类型信息,所以在使用时,它们必须要具有xsi:type属性,或者所属元素必须具有enc:arrayType属性。(这句话不太明白,呵呵)
http://www.w3.org/2001/12/soap-encoding命名空间中包含对应于xml架构规范中定义的元素声明,也包含Array声明。例如下面的例子给出了enc:Array元素的用法:
<enc:Array xmlns:enc="http://www.w3.org/2001/12/soap-encoding"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
enc:ArrayType="xs:int[2]">
<enc:int>3</enc:int>
<enc:int>4</enc:int>
</enc:Aray>
数组可以包含指定arrayType的任意子类型的实例。例如,整形数组可以包含从integer类型派生的任意类型(比如int或用户定义的任意integer派生类型)。因为enc:Array类型允许任意类型的成员,所以可以混合包含任意类型除非使用arrayType属性加以特别的限制。
在实例文档中,可以使用xsi:type指定成员元素的类型,或通过成员元素架构中的声明来指定,下面的两个数组演示了这种情况。
<enc:Array xmlns:enc="http://www.w3.org/2001/12/soap-encoding"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
enc:ArrayType="xs:anyType[4]">
<thing xsi:type="xs:int">12345</thing>
<thing xsi:type="xs:decimal">1.2345</thing>
<thing xsi:type="xs:string">abcdefg</thing>
<thing xsi:type="xs:anyURI">http://www.sina.com</thing>
</enc:Array>
数组值可以是结构或其他复合值。