和简单数据类型对应就是复杂数据类型了,XML元素的数据类型可以是简单数据类型,也可以是复杂数据类型,而XML属性的数据类型就只能是简单数据类型。这篇笔记,就来学习一下XSD中的复杂数据类型了。
1、定义复杂数据类型
(1)和
<complexType
id=ID
name=NCName
abstract=true|false
mixed=true|false
block=(#all|extension与restriction的自由组合)
final=(#all|extension与restriction的自由组合)
any-attributes> (annotation?,(simpleContent|complexContent|((group|all|choice|sequence)?,((attribute|attributeGroup)*,anyAttribute?)))) complexType>
其中
属性 | 说明 |
id | 唯一标识 |
name | 使用 |
abstract | 是否为抽象的数据类型,如为抽象的,则不能在XML文档中直接使用这种数据类型 |
mixed | 是否为混合类型,如果是混合类型,则允许同时出现字符数据和子元素 如果子元素是 如果子元素是 |
block | 防止使用指定派生类型的复杂类型来替换当前定义的复杂类型 |
final | 防止使用指定派生类型来派生新的类型 |
any attributes | 指定non-schema命名空间的任何其他属性 |
(2)复杂数据类型只能用于元素而不能用于属性,进一步,可以根据能应用的元素对数据类型进行分类:
- 简单数据类型:相应的元素内容是简单类型值,并且元素不能有属性,使用
定义 - 含简单内容的复杂数据类型:相应的元素内容是简单类型值,但元素具有属性,使用
元素的语法如下:
<simpleContent id=ID any-attributes> (annotation?,(restriction|extension)) simpleContent>
- 含复杂内容的复杂数据类型:相应的元素可以是包含子元素的元素,空元素或包含混合内容的元素,而不管元素是否有属性,使用
元素的语法如下:
<complexContent id=ID mixed=true|false any-attributes> (annotation?,(restriction|extension)) complexContent>
(3)在根元素
(4)final属性用于指定不能以那种方式派生新类型,可以取的值有#all,extension和restriction的自由组合,默认值为根元素
(5)block属性指定不能使用指定方式派生出来的类型来替换所定义的类型,可以取的值和final相同,默认值为根元素
2、定义元素
(1)在定义复杂数据类型时,需要定义子元素和属性,那么怎么定义元素呢?在XSD中,可以使用
<element
id=ID
name=NCName
ref=QName
type=QName
substitutionGroup=QName
default=string
fixed=string
form=qualified|unqualified
maxOccurs=nonNegativeInteger|unbounded
minOccurs=nonNegativeInteger
nillable=true|false
abstract=true|false
block=(#all|extension、restriction和substitution的自由组合)
final=(#all|extension和restriction的自由组合)
any-attributes> (annotation?,((simpleType|complexType)?,(unique|key|keyref)*) element>
其中element元素的各属性如下表:
属性 | 说明 |
id | 唯一标识 |
name | 新定义元素的名称,根元素 |
ref | 对另一个元素的引用,可包含一个命名空间前缀 |
type | 数据类型,可以是内建数据类型、simpleType或complexType定义的类型 |
substitutionGroup | 可用来替代该元素的元素名称,必须具有相同的类型或从其派生类型 |
default | 默认值,元素内容是简单类型或textOnly时使用 |
fixed | 固定值,元素内容是简单类型或textOnly时使用,默认值default和固定值fixed不能同时指定 |
form | 是否通过命名空间前缀限定该元素,默认值为 |
maxOccurs | 在父元素中出现的最大次数,非负整数或无限制(unbounded),默认值为1 |
minOccurs | 在父元素中出现的最少次数,必须小于或等于maxOccurs,默认值为1 |
nillable | 是否可以将显示的零值分配给该元素,默认为false,如果为true,则在XML文档中可以设定该元素的nil属性为true |
abstract | 是否为抽象元素,如为抽象元素,则不能直接在XML文档中使用 |
block | 阻止使用指定派生方式的元素来替换当前元素 |
final | 设置element元素上final属性的默认值 |
any attributes | 指定non-schema命名空间的任何其他属性 |
其中父元素是根元素
(2)可以通过
<group
id=ID
name=NCName
ref=QName
maxOccurs=nonNegativeInteger|unbounded
minOccurs=nonNegativeInteger
any-attributes> (annotation?,(all|choice|sequence)?) group>
看一个例子:
<xs:group name="personGroup"> <xs:sequence> <xs:element name="firstname" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> xs:sequence> xs:group> <xs:element name="person" type="personType"/> <xs:complexType name="personType"> <xs:sequence> <xs:group ref="personGroup"/> <xs:element name="country" type="xs:string"/> xs:sequence> xs:complexType>
这里涉及到了三种顺序指示器,用于定义元素的顺序:
- all:子元素能以任意顺序出现,但是每个子元素必须只出现一次,这个时候可以把minOccurs设置为0或1,并且只能把maxOccurs设置为1
- choice:子元素是互斥的关系,只能出现其中之一
- sequence:子元素必须按照指定的顺序出现
(3)元素通配符
在某些情况下,如果无法确定指定元素还需要包含哪些子元素、哪些属性,这时候可使用通配符。XSD中使用
<any id=ID maxOccurs=nonNegativeInteger|unbounded minOccurs=nonNegativeInteger namespace=namespace processContents=lax|skip|strict any-attributes> (annotation?) any>
属性 | 说明 | 取值/取值类型 | 默认值 |
id | 唯一标识该元素 | ID类型 | |
maxOccurs | 该元素最多可出现的次数 | 非负整数或unbounded | 1 |
minOccurs | 该元素最少可出现的次数 | 非负整数,必须小于maxOccurs | 1 |
namespace | 指定可代替该通配符的元素必须来自哪个空间 |
|
|
processContents | 指定应用程序或XML处理器如何对替换元素进行验证 |
|
strict |
(4)元素替换
XSD还提供了一种机制,允许使用一个元素替换另一个元素,如果想定义某个元素可替换另一个元素,可以为该元素增加substitutionGroup属性,其值就是该元素想替换的元素的名字。使用元素替换需注意两点:
- 替换元素和被替换元素必须以全局元素的形式来声明
- 替换元素和被替换元素要么有相同的数据类型,要么替换元素类型是被替换元素类型的派生类型
另外,
- 可以使用final属性来阻止自己被指定派生类型替换
- 可以使用block属性来阻止指定派生类型的替换
3、定义属性
定义属性和定义元素是完全统一的,只是定义属性使用
<attribute
id=ID
name=NCName
ref=QName
type=QName
default=string
fixed=string
form=qualified|unqualified
uese=optional|prohibited|required
any-attributes> (annotation?,(simpleType?)) attribute>
(1)
- optional:属性是可选的,并且可以具有指定数据类型的任意值
- prohibited:不能使用属性(既然不能使用,为何还要定义?主要是在派生新类型使用,用来删除原类型的某个属性)
- required:必须的属性,此时不能指定default和fixed
(2)在根元素
(3)类似
<attributeGroup id=ID name=NCName ref=QName any-attributes> (annotation?,((attribute|attributeGroup)*,anyAttribute?)) attributeGroup>
(4)属性通配符
类似于元素通配符,可以使用
<anyAttribute id=ID namespace=namespace processContents=lax|skip|strict any-attributes> (annotation?) anyAttribute>
其中属性含义与元素通配符
4、再看看怎么派生复杂数据类型
知道怎么定义元素和属性之后,就可以进一步看怎么定义复杂数据类型了,总的来说,定义复杂数据类型需要弄清两个问题:第一个问题是基类型的问题——定义复杂数据类型的基础是哪个类型?第二个问题就是派生方式的问题——派生复杂数据类型可以使用限制
(1)基类型
- anyType类型:和DTD中的ANY类似,XSD中也有一个anyType类型,这种类型的元素没有任何限制,可以包含子元素,可以包含字符串内容,还可以添加任何属性(但这些属性需要在XSD文件中定义过),anyType类型是所有简单类型和所有复杂类型的基类型,通常用于派生新的类型,而不是直接用来定义元素。
- 简单类型
- 含简单内容的复杂类型:元素内容是简单类型值,但元素包括属性
- 空元素类型:用于定义内容为空或空字符串的元素,但是该元素可以接受属性。定义空元素类型有两种方式:
- 扩展长度为0的字符串:如果该元素不需要包含属性,那么直接使用长度为0的字符串类型定义该元素即可
- 限制anyTye:限制anyType时不定义任何子元素,只定义所需属性即可
<xs:simpleType name="emptyString"> <xs:restriction base="xs:string"> <xs:maxLength value="0"/> xs:restriction> xs:simpleType> <xs:element name="book"> <xs:complexType> <xs:simpleContent> <xs:extension base="emptyString"> <xs:attribute name="name" type="xs:token"/> xs:extension> xs:simpleContent> xs:complexType> xs:element> <xs:element name="book2"> <xs:complexType> <xs:attribute nae="name" type="xs:token"/> xs:complexType> xs:element>
- 包含子元素的类型
- 混合内容类型
(2)派生方式
- 限制
- 扩展
下面是我从这基类型和派生方式两个维度统计的一个列表:
基类型 | 派生方式 | 定义时使用的XSD元素 | 说明 |
anyType类型 | 限制 | |
因为anyType只能限制,不能扩展,所以可以省略 而直接在 |
扩展 |
|
anyType类型已经没有任何限制了,所以也就不需要再扩展了 |
|
简单类型 | 限制 | |
限制简单类型最终结果也是一个简单类型,因此使用 |
扩展 | |
可以通过添加属性或属性组派生复杂数据类型 | |
包含简单内容的复杂类型 | 限制 | |
|
扩展 | |
添加属性 | |
空元素类型 | 限制 | |
|
扩展 | |
|
|
包含子元素的类型 | 限制 | |
|
扩展 | |
|
|
混合内容类型 | 限制 | |
限制混合内容类型的方式和限制包含子元素的类型基本相同 |
扩展 | |
扩展混合内容类型的方式和扩展包含子元素的类型基本相同,但是必须保留mixed="true" |
派生类型的另外一种用法:
假设在XSD中定义了元素
<book name="example1"/> <book name="example2" xsi:type="extended_book_type" price="100"/>
5、一致性约束
定义元素还可以指定3种类型的约束:
- key约束:相当于DB里面的主键约束,要求指定内容必须存在而且唯一
- keyref约束:相当于DB里面的外键约束,要求指定内容的值必须使用refer属性引用另一个key约束或unique约束
- unique约束:相当于DB里面的唯一约束,要求指定内容必须唯一,但可以不存在
这3个一致性约束都只能在
在DB中定义约束时,不仅需要指定使用哪类约束,还需要定义应该对哪些字段应用约束,在XSD中定义一致性约束也完全类似,也需要指定该约束将对哪些部分起作用,因此需要在约束内使用如下两个子元素:
:需指定一个xpath属性,其值是一个XPath表达式,用来确定一个元素范围,在一次约束定义中, 必须且只能出现一次 :需要指定一个xpath属性,其值是一个XPath表达式,在一次约束定义中, 至少要出现一次,也可以出现多次
这两个元素的含义是:在
看下例子:
<xs:element name="book-list"> <xs:complexType> <xs:sequence> <xs:element ref="book" maxOccurs="unbounded"/> xs:sequence> xs:complexType> <xs:key name="nameKey"> <xs:selector xpath="book"/> <xs:field xpath="name"/> xs:key> xs:element>
6、定义符号
最后看一下和DTD中对应的定义符号的用法,在XSD中使用
- id:指定该符号的唯一标识,通常无需指定
- name:指定该符号的名称,是一个必填属性,而且该名称在整个XSD内必须是唯一的
- public:指定该符号所标识数据的外部格式或对应处理程序,必填属性,相当于DTD中中PUBLIC的作用
- system:指定该符号所标识数据的外部格式或对应处理程序,可选属性,相当于DTD中中SYSTEM的作用