2.5. 定义复杂数据类型

摘要

XML 架构提供了灵活的强大机制,用于从其简单数据类型构建复杂数据结构。您可以通过创建由元素和属性组成的序列来创建数据结构。您还可以扩展您定义的类型,以创建更复杂的类型。

除了构建复杂数据结构外,您还可以描述专用类型,如枚举类型、具有特定范围的值的数据类型,或者通过扩展或限制原语类型需要遵守特定模式的数据类型。

2.5.1. 定义数据结构

概述

在 XML 架构中,作为数据字段集合的数据单元是使用 complexType 元素来定义的。指定复杂类型需要三部分信息:

  1. 定义的类型的名称在 complexType 元素的 name 属性中指定。
  2. complexType 的第一个子元素描述了当 structure 字段在线路上时的行为。请参阅 “复杂的类型 varieties”一节
  3. 定义结构的每个字段都在作为 complexType 元素的 Getndchildren 的元素中定义。请参阅 “定义结构的部分”一节

例如,在 XML 架构中作为带有两个元素的复杂类型来定义 例 2.3 “简单结构” 中的结构。

例 2.3. 简单结构

struct personalInfo
{
  string name;
  int age;
};

例 2.4 “复杂类型” 显示 例 2.3 “简单结构” 中显示的结构的可能 XML 架构映射,在 例 2.4 “复杂类型” 中定义的结构会生成包含两个元素: nameage 的消息。

.

例 2.4. 复杂类型

<complexType name="personalInfo">
  <sequence>
    <element name="name" type="xsd:string" />
    <element name="age" type="xsd:int" />
  </sequence>
</complexType>

复杂的类型 varieties

XML 架构有三种方法来描述复杂类型的字段在以 XML 文档表示并用线路传递时的方式。complexType 元素的第一个子元素决定使用哪些复杂类型。表 2.1 “复杂的类型描述符元素” 显示用于定义复杂类型行为的元素。

表 2.1. 复杂的类型描述符元素

元素复杂的类型行为

序列

所有复杂类型的字段都可以存在,且它们必须按类型定义中指定的顺序。

all

所有复杂的类型字段都可以存在,但可以按任何顺序排列。

choice

只有结构中的其中一个元素可以放在消息中。

如果使用 选择 元素定义结构,如 例 2.5 “简单复杂的选择类型” 所示,它将生成一个包含 name 元素或 age 元素的消息。

例 2.5. 简单复杂的选择类型

<complexType name="personalInfo">
  <choice>
    <element name="name" type="xsd:string"/>
    <element name="age" type="xsd:int"/>
  </choice>
</complexType>

定义结构的部分

您可以使用 元素元素 定义组成结构的数据字段。每个 complexType 元素都应该至少包含一个 元素complexType 元素 中的每个元素代表定义的数据结构中的一个字段。

要完全描述数据结构中的字段,元素 元素有两个所需的属性:

  • name 属性指定 data 字段的名称,它在定义的复杂类型中必须是唯一的。
  • type 属性指定字段中存储的数据类型。类型可以是 XML 架构简单类型之一,也可以是在合同中定义的任何指定复杂类型。

除了名称和类型外,元素元素 还有两个常用的可选属性: minOcurrsmaxOccurs 这些属性根据字段在结构中发生的次数进行绑定。默认情况下,每个字段仅在复杂类型中执行一次。使用这些属性,您可以更改字段必须或可以在结构中显示的次数。例如,您可以定义一个字段 previousJobs,它必须至少发生三次,且不超过七次,如 例 2.6 “具有发生限制的简单复杂类型” 所示。

例 2.6. 具有发生限制的简单复杂类型

<complexType name="personalInfo">
  <all>
    <element name="name" type="xsd:string"/>
    <element name="age" type="xsd:int"/>
    <element name="previousJobs" type="xsd:string:
             minOccurs="3" maxOccurs="7"/>
  </all>
</complexType>

您还可以通过将 minOccurs 设置为 0,使用 minOccurs 来指定 age 字段是可选的,如 例 2.7 “简单的复杂类型,将 minOccurs 设为零” 所示。在这种情况下,可以省略这些 年龄,数据仍将有效。

例 2.7. 简单的复杂类型,将 minOccurs 设为零

<complexType name="personalInfo">
  <choice>
    <element name="name" type="xsd:string"/>
    <element name="age" type="xsd:int" minOccurs="0"/>
  </choice>
</complexType>

定义属性

在 XML 文档中,属性包含在元素的标签中。例如,在下面的代码中的 complexType 元素中,name 是属性。要为复杂类型指定属性,您可以在 complexType 元素定义中定义 属性 元素。属性 元素只能在 所有序列 或选择元素 后显示。为每个复杂类型的属性指定一个 属性 元素。任何 属性 元素都必须是 complexType 元素的直接子项。

例 2.8. 具有属性的复杂类型

<complexType name="personalInfo">
  <all>
    <element name="name" type="xsd:string"/>
    <element name="previousJobs" type="xsd:string"
             minOccurs="3" maxOccurs="7"/>
  </all>
  <attribute name="age" type="xsd:int" use="required" />
</complexType>

在前面的代码中,attribute 元素指定 personalInfo 复杂类型具有 age 属性。attribute 元素具有这些属性:

  • Name - 指定用于标识属性的字符串的必需属性。
  • Type - 指定存储在字段中的数据类型。这个类型可以是 XML 架构简单类型之一。
  • 使用 - 指定具有此属性时是否需要复杂类型的可选属性。有效值 是必需的可选。默认值是 属性是可选的。

attribute 元素中,您可以指定可选的 default 属性,它允许您指定属性的默认值。

2.5.2. 定义数组

概述

Apache CXF 支持在合同中定义数组。首先定义一个复杂的类型,它 maxOccurs 属性的值大于一。第二个是使用 SOAP 阵列。SOAP 阵列提供添加功能,比如轻松地定义多维数组和传输稀疏填充阵列的功能。

复杂的类型数组

复杂的类型数组是序列复杂类型的特殊情况。您只需使用单个元素定义复杂类型,并为 maxOccurs 属性指定值。例如,要定义一系列调整浮动点号,您需要使用类似 例 2.9 “复杂的类型数组” 中显示的复杂类型。

例 2.9. 复杂的类型数组

<complexType name="personalInfo">
  <element name="averages" type="xsd:float" maxOccurs="20"/>
</complexType>

您还可以为 minOccurs 属性指定值。

SOAP 阵列

SOAP 阵列通过除 SOAP-ENC:Array 基本类型使用 wsdl:arrayType 元素来定义。这个语法显示在 例 2.10 “使用 wsdl:arrayType 派生的 SOAP 阵列语法” 中。确保 definition 元素声明 xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"

例 2.10. 使用 wsdl:arrayType 派生的 SOAP 阵列语法

<complexType name="TypeName">
  <complexContent>
    <restriction base="SOAP-ENC:Array">
      <attribute ref="SOAP-ENC:arrayType"
                 wsdl:arrayType="ElementType<ArrayBounds>"/>
    </restriction>
  </complexContent>
</complexType>

使用这个语法,TypeName 指定新定义的数组类型的名称。ElementType 指定阵列中元素的类型。ArrayBounds 指定阵列中的维度数。要指定单一维度数组使用 []; 指定双维数组,使用 [][][,]

例如: SOAP Array, SOAPStrings(如 例 2.11 “SOAP 阵列的定义” 所示)定义一个字符串的一个连续数组。wsdl:arrayType 属性指定数组元素的类型 xsd:string,以及维度的数量( [] 表示一个维度)。

例 2.11. SOAP 阵列的定义

<complexType name="SOAPStrings">
  <complexContent>
    <restriction base="SOAP-ENC:Array">
      <attribute ref="SOAP-ENC:arrayType"
                 wsdl:arrayType="xsd:string[]"/>
    </restriction>
  </complexContent>
</complexType>

您还可以使用简单元素描述 SOAP Array,如 SOAP 1.1 规范中所述。这个语法显示在 例 2.12 “使用元素派生的 SOAP 阵列的语法” 中。

例 2.12. 使用元素派生的 SOAP 阵列的语法

<complexType name="TypeName">
  <complexContent>
    <restriction base="SOAP-ENC:Array">
      <sequence>
        <element name="ElementName" type="ElementType"
                 maxOccurs="unbounded"/>
      </sequence>
    </restriction>
  </complexContent>
</complexType>

使用这种语法时,元素的 maxOccurs 属性必须始终设为 unbound

2.5.3. 按扩展定义类型

与大多数主要的编码语言一样,XML Schema 也允许您创建数据类型来继承其某些元素的数据类型。这称为按照扩展来定义类型。例如,您可以创建一个名为 alienInfo 的新类型,它通过添加一个名为 planet 的新元素来扩展 例 2.4 “复杂类型” 中定义的 个人Info 结构。

由 扩展定义的类型有四个部分:

  1. 类型的名称由 complexType 元素的 name 属性定义。
  2. 复杂的Content 元素指定新类型将具有多个元素。

    注意

    如果您只向复杂类型添加新属性,您可以使用 simpleContent 元素。

  3. 从派生新类型的类型(称为 基础 类型)在 extension 元素的 base 属性中指定。
  4. 新类型的元素和属性在 extension 元素中定义,它们与用于常规复杂的类型相同。

例如: alienInfo 定义,如 例 2.13 “由扩展定义的类型” 所示。

例 2.13. 由扩展定义的类型

<complexType name="alienInfo">
  <complexContent>
    <extension base="xsd1:personalInfo">
      <sequence>
        <element name="planet" type="xsd:string"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

2.5.4. 根据限制定义类型

概述

XML 架构允许您通过限制 XML 架构简单类型的可能值来创建新类型。例如,您可以定义一个简单类型 SSN,它是仅包含 9 个字符的字符串。通过限制简单类型来定义的新类型,可使用 simpleType 元素来定义。

按限制划分类型的定义需要三个操作:

  1. 新类型的名称通过 simpleType 元素的 name 属性指定。
  2. 从中派生新类型的简单类型(称为 基础类型 )在 limits 元素中指定。请参阅 “指定基础类型”一节
  3. 规则(称为 facets )定义基础类型所施加的限制是作为 限制 元素的子项的子项。请参阅 “定义限制”一节

指定基础类型

基础类型是受限制来定义新类型的类型。它通过 limit 元素 来指定限制 元素是 simpleType 元素的唯一子项,并且具有一个指定 基础 类型的属性(base)。基本类型可以是任何 XML 架构简单类型。

例如,通过限制 xsd:int 的值来定义新类型,您可以使用类似 例 2.14 “使用 int 作为基础类型” 中显示的定义。

例 2.14. 使用 int 作为基础类型

<simpleType name="restrictedInt">
  <restriction base="xsd:int">
    ...
  </restriction>
</simpleType>

定义限制

定义对基本类型实施的限制的规则称为 facets。facets 是带有一条属性( value )的元素,它定义了如何强制实施 facet。可用的难题及其 有效值 设置取决于基本类型。例如,xsd:string 支持六方面面,其中包括:

  • length
  • minLength
  • maxLength
  • pattern
  • whitespace
  • 枚举

每个 facet 元素都是 限制 元素的子元素。

示例

例 2.15 “SSN 简单类型描述” 显示了一个简单类型 SSN 的示例,它代表了一个社交安全号。生成的 type 是 xxx-xx-xxxx 形式的字符串。<SSN>032-43-9876<SSN> 是此类型的元素的有效值,但 <SSN>032439876</SSN> 不可用。

例 2.15. SSN 简单类型描述

<simpleType name="SSN">
  <restriction base="xsd:string">
    <pattern value="\d{3}-\d{2}-\d{4}"/>
  </restriction>
</simpleType>

2.5.5. 定义枚举的类型

概述

XML 架构中的枚举类型是根据限制的特殊定义情况。它们通过使用 枚举 面貌(受所有 XML 架构制语支持)加以说明。与大多数现代编程语言中枚举的类型一样,这种类型的变量只能具有其中一个指定值。

在 XML 架构中定义枚举

定义枚举的语法显示在 例 2.16 “枚举的语法” 中。

例 2.16. 枚举的语法

<simpleType name="EnumName">
  <restriction base="EnumType">
    <enumeration value="Case1Value"/>
    <enumeration value="Case2Value"/>
    ...
    <enumeration value="CaseNValue"/>
  </restriction>
</simpleType>

EnumName 指定枚举类型的名称。EnumType 指定问题单值的类型。CaseNValue,其中 N 是任意一个或更大值,它指定枚举的每个具体案例的值。枚举的类型可以包含任意数量的问题单值,但由于从简单类型派生出,因此一次只有一个问题单值有效。

示例

例如,如果一个带有由 enumeration widgetSize 定义的元素的 XML 文档,如果它包括了 < widgetSize >big</widgetSize>,则它无效,但如果包含 <widgetSize>big,mungo</widgetSize>。例 2.17 “widgetSize enumeration”

例 2.17. widgetSize enumeration

<simpleType name="widgetSize">
  <restriction base="xsd:string">
    <enumeration value="big"/>
    <enumeration value="large"/>
    <enumeration value="mungo"/>
  </restriction>
</simpleType>