XML schema允许complex类型的定义,就像C里是struct。例如,为了定义类似如下的C的struct类型:
typedef struct { string firstName; string lastName; long ageInYears; float weightInLbs; float heightInInches; } PERSON; |
我们可以写XML schema:
<xsd:complexType name="PERSON"> <xsd:sequence> <xsd:element name="firstName" type="xsd:string"/> <xsd:element name="lastName" type="xsd:string"/> <xsd:element name="ageInYears" type="xsd:int"/> <xsd:element name="weightInLbs" type="xsd:float"/> <xsd:element name="heightInInches" type="xsd:float"/> </xsd:sequence> </xsd:complexType> |
不过,complex类型可以表达比struct更多的信息。除了<sequence>以外,它还可以有其他的子元素,比如<all>
<xsd:complexType name="PERSON"> <xsd:all> <xsd:element name="firstName" type="xsd:string"/> <xsd:element name="lastName" type="xsd:string"/> <xsd:element name="ageInYears" type="xsd:int"/> <xsd:element name="weightInLbs" type="xsd:float"/> <xsd:element name="heightInInches" type="xsd:float"/> </xsd:all> </xsd:complexType> |
这意味着<element>的成员变量可以以任何顺序排列,每一个都是可选的。这和C中的struct类型不太一样。
注意内建数据类型string, int, float。C的string也是XML的string,float也类似。但C中的long类型在XML中是int(上表中)。
在WSDL文件中,像上面的complex类型可以在Types栏声明。例如,我可以用以下方式声明PERSON类型并用在Messages栏。
<?xml version="1.0" encoding="UTF-8" ?> <definitions … > <types> <schema targetNamespace="someNamespace" xmlns:typens="someNamespace" > <xsd:complexType name="PERSON"> <xsd:sequence> <xsd:element name="firstName" type="xsd:string"/> <xsd:element name="lastName" type="xsd:string"/> <xsd:element name="ageInYears" type="xsd:int"/> <xsd:element name="weightInLbs" type="xsd:float"/> <xsd:element name="heightInInches" type="xsd:float"/> </xsd:sequence> </xsd:complexType> </schema> </types> <message name="addPerson"> <part name="person" type="typens:PERSON"/> </message> <message name="addPersonResponse"> <part name="result" type="xsd:int"/> </message> </definitions> |
上例中第一个消息由"adperson",并且有一个<part>,其类型为"PERSON"。PERSON类型是在Types栏声明的。
如果我们使用完整的WSDL文件包含以上的部分,并以之初始化MSTK2 SoapClient,它将成功的解析该文件。当然,它不会去调用<addPerson>。这是因为SoapClient本身并不知道如何处理complex类型,它需要定制类型映射来处理complex类型。MSTK2文档中有包含定制类型映射的示例。
还有另一种方法可以把<part>元素联系到类型声明。这就是使用元素。下例中我将Types栏中声明两个元素("Person"和"Gendr"),然后我将在"addPerson"<message>中使用元素属性来引用它们。
<?xml version="1.0" encoding="UTF-8" ?> <definitions … > <types> <schema targetNamespace="someNamespace" xmlns:typens="someNamespace" > <element name="Person"> <xsd:complexType> <xsd:sequence> <xsd:element name="firstName" type="xsd:string"/> <xsd:element name="lastName" type="xsd:string"/> <xsd:element name="ageInYears" type="xsd:int"/> <xsd:element name="weightInLbs" type="xsd:float"/> <xsd:element name="heightInInches" type="xsd:float"/> </xsd:sequence> </xsd:complexType> </element> <element name="Gender"> <xsd:simpleType> <xsd:restriction base="xsd:string"> <xsd:enumeration value="Male" /> <xsd:enumeration value="Female" /> </xsd:restriction> </xsd:simpleType> </element> </schema> </types> <message name="addPerson"> <part name="who" element="typens:Person"/> <part name="sex" element="typens:Gender"/> </message> <message name="addPersonResponse"> <part name="result" type="xsd:int"/> </message> </definitions> |
Types栏中的Gender<element>里嵌入了枚举类型,其枚举值为"Male""Female"。然后我又在"addPerson"<message>中通过元素属性而不是类型属性来引用它。
"元素属性"和"类型属性"在把某特定类型关联到<part>时有什么不同呢?使用元素属性,我们可以描述一个部分,它可以假定几个类型(就像变量一样),而是用类型属性我们就无法这样做。下例说明了这一点。
<?xml version="1.0" encoding="UTF-8" ?> <definitions … > <types> <schema targetNamespace="someNamespace" xmlns:typens="someNamespace"> <xsd:complexType name="PERSON"> <xsd:sequence> <xsd:element name="firstName" type="xsd:string"/> <xsd:element name="lastName" type="xsd:string"/> <xsd:element name="ageInYears" type="xsd:int"/> <xsd:element name="weightInLbs" type="xsd:float"/> <xsd:element name="heightInInches" type="xsd:float"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="femalePerson"> <xsd:complexContent> <xsd:extension base="typens:PERSON" > <xsd:element name="favoriteLipstick" type="xsd:string" /> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="malePerson"> <xsd:complexContent> <xsd:extension base="typens:PERSON" > <xsd:element name="favoriteShavingLotion" type="xsd:string" /> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="maleOrFemalePerson"> <xsd:choice> <xsd:element name="fArg" type="typens:femalePerson" > <xsd:element name="mArg" type="typens:malePerson" /> </xsd:choice> </xsd:complexType> </schema> </types> <message name="addPerson"> <part name="person" type="typens:maleOrFemalePerson"/> </message> <message name="addPersonResponse"> <part name="result" type="xsd:int"/> </message> </definitions> |
上例也告诉我们extension的派生。"femailPerson"和"malePerson"都是从"PERSON"派生出来的。它们各有一些额外的元素:"femalePerson"有"favoriteLipstick"元素,"malePerson"有"favoriteShavingLotion"元素。两派生类型都归入一个complex类型"maleOrFemalePerson",使用的是<choice>构造。最后,在"adperson"<message>中,新类型有"person"<part>引用。这样,参数或<part>就可以是"femalePerson"或"malePerson"了。