和简单数据类型对应就是复杂数据类型了,XML元素的数据类型可以是简单数据类型,也可以是复杂数据类型,而XML属性的数据类型就只能是简单数据类型。这篇笔记,就来学习一下XSD中的复杂数据类型了。

1、定义复杂数据类型

(1)和<simpleType>元素用来定义简单数据类型相对应,可以使用<complexType>元素来定义复杂数据类型。其语法为:

<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>

其中<complexType>元素的属性说明如下:

属性 说明
id 唯一标识<complexType>元素本身
name 使用<complexType>元素新定义的数据类型的名称
abstract 是否为抽象的数据类型,如为抽象的,则不能在XML文档中直接使用这种数据类型
mixed

是否为混合类型,如果是混合类型,则允许同时出现字符数据和子元素

如果子元素是<simplexContent>,则不能使用该属性

如果子元素是<complexContent>,则mixed属性可以被<complexContet>元素的mixed属性重写

block 防止使用指定派生类型的复杂类型来替换当前定义的复杂类型
final 防止使用指定派生类型来派生新的类型
any attributes 指定non-schema命名空间的任何其他属性

(2)复杂数据类型只能用于元素而不能用于属性,进一步,可以根据能应用的元素对数据类型进行分类:

  • 简单数据类型:相应的元素内容是简单类型值,并且元素不能有属性,使用<simpleType>定义
  • 含简单内容的复杂数据类型:相应的元素内容是简单类型值,但元素具有属性,使用<complexType> <simpleContent> </simpleContent> </complexType>定义,其中<simpleContent>元素的语法如下:
<simpleContent id=ID any-attributes>
(annotation?,(restriction|extension))
</simpleContent>
  • 含复杂内容的复杂数据类型:相应的元素可以是包含子元素的元素,空元素或包含混合内容的元素,而不管元素是否有属性,使用<complexType> <complexContent> </complexContent> </complexType>定义,其中<complexContent>元素的语法如下:
<complexContent id=ID mixed=true|false any-attributes>
(annotation?,(restriction|extension))
</complexContent>

(3)在根元素<schema>下定义的复杂数据类型为全局的,此时name属性是必须的,否则为局部的。

(4)final属性用于指定不能以那种方式派生新类型,可以取的值有#all,extension和restriction的自由组合,默认值为根元素<schema>的finalDefault属性值。这个属性其实和<simplexType>的final属性类似,只是<simplexType>的final属性取值可以是#all或restriction、list、union的自由组合。

(5)block属性指定不能使用指定方式派生出来的类型来替换所定义的类型,可以取的值和final相同,默认值为根元素<schema>的blockDefault属性值。

2、定义元素

(1)在定义复杂数据类型时,需要定义子元素和属性,那么怎么定义元素呢?在XSD中,可以使用<element>元素来定义元素,其语法如下:

<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 唯一标识<element>元素
name 新定义元素的名称,根元素<schema>下定义时为必须属性
ref 对另一个元素的引用,可包含一个命名空间前缀
type 数据类型,可以是内建数据类型、simpleType或complexType定义的类型
substitutionGroup 可用来替代该元素的元素名称,必须具有相同的类型或从其派生类型
default 默认值,元素内容是简单类型或textOnly时使用
fixed 固定值,元素内容是简单类型或textOnly时使用,默认值default和固定值fixed不能同时指定
form 是否通过命名空间前缀限定该元素,默认值为<schema>元素的elementFormDefault属性值
maxOccurs 在父元素中出现的最大次数,非负整数或无限制(unbounded),默认值为1
minOccurs 在父元素中出现的最少次数,必须小于或等于maxOccurs,默认值为1
nillable 是否可以将显示的零值分配给该元素,默认为false,如果为true,则在XML文档中可以设定该元素的nil属性为true
abstract 是否为抽象元素,如为抽象元素,则不能直接在XML文档中使用
block 阻止使用指定派生方式的元素来替换当前元素
final 设置element元素上final属性的默认值
any attributes 指定non-schema命名空间的任何其他属性

其中父元素是根元素<schema>时,不能使用ref、form、maxOccurs、minOccurs等属性,而substitutionGroup、final等属性则只能使用在父元素为根元素的情况下。

(2)可以通过<group>元素将一组属性定义在一起,然后在其它需要元素的地方用元素组的引用就可以了。语法如下:

<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>元素作为元素通配符,表示任何元素,即<any>元素出现的位置可以使用任何元素代替,其语法格式如下:

<any
  id=ID
  maxOccurs=nonNegativeInteger|unbounded
  minOccurs=nonNegativeInteger
  namespace=namespace
  processContents=lax|skip|strict
  any-attributes>
  (annotation?)
</any>

<any>元素的属性:

属性 说明 取值/取值类型 默认值
id 唯一标识该元素 ID类型  
maxOccurs 该元素最多可出现的次数 非负整数或unbounded 1
minOccurs 该元素最少可出现的次数 非负整数,必须小于maxOccurs 1
namespace 指定可代替该通配符的元素必须来自哪个空间
  • ##any:任意命名空间的元素
  • ##other:来自当前命名空间之外的其它任意命名空间的元素
  • ##local:无命名空间限定的元素
  • ##targetNamespace:当前命名空间的元素
  • 命名空间URI:指定命名空间的元素
  • 上面多个值的列表:值列表中的任意一个命名空间的元素
 
processContents 指定应用程序或XML处理器如何对替换元素进行验证
  • strict:XML处理器必须获得由namespace指定的命名空间对应的Schema,并验证来自该命名空间的所有元素
  • lax:XML处理器尝试获取由namespace指定的命名空间对应的Schema,成功则验证所有元素,否则也不报错
  • skip:XML处理器不会获取所需命名空间,也不会进行任何验证
strict

(4)元素替换

XSD还提供了一种机制,允许使用一个元素替换另一个元素,如果想定义某个元素可替换另一个元素,可以为该元素增加substitutionGroup属性,其值就是该元素想替换的元素的名字。使用元素替换需注意两点:

  • 替换元素和被替换元素必须以全局元素的形式来声明
  • 替换元素和被替换元素要么有相同的数据类型,要么替换元素类型是被替换元素类型的派生类型

另外,

  • 可以使用final属性来阻止自己被指定派生类型替换
  • 可以使用block属性来阻止指定派生类型的替换

3、定义属性

  定义属性和定义元素是完全统一的,只是定义属性使用<attribute>元素,其语法格式如下:

<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)<attribute>元素的属性基本和<element>元素相同,不同的是form属性的默认值是根元素<schema>的attributeFormDefault属性的值。另外,use属性是<element>所没有的,它表示怎么使用这个属性,可以取的值有:

  • optional:属性是可选的,并且可以具有指定数据类型的任意值
  • prohibited:不能使用属性(既然不能使用,为何还要定义?主要是在派生新类型使用,用来删除原类型的某个属性)
  • required:必须的属性,此时不能指定default和fixed

(2)在根元素<schema>下定义的属性称之为全局属性,其它的属性则可以通过<attribute>元素的ref属性来引用全局属性;也可以直接将<attribute>放在<complexType>元素内部定义属性。

(3)类似<group>元素定义元素组,还可以使用<attributeGroup>元素定义属性组,其语法格式如下:

<attributeGroup id=ID name=NCName ref=QName any-attributes>
(annotation?,((attribute|attributeGroup)*,anyAttribute?))
</attributeGroup>

(4)属性通配符

  类似于元素通配符,可以使用<anyAttribute>表示属性通配符,其语法格式如下:

<anyAttribute
  id=ID
  namespace=namespace
  processContents=lax|skip|strict
  any-attributes>
(annotation?)
</anyAttribute>

其中属性含义与元素通配符<any>相同。

4、再看看怎么派生复杂数据类型

  知道怎么定义元素和属性之后,就可以进一步看怎么定义复杂数据类型了,总的来说,定义复杂数据类型需要弄清两个问题:第一个问题是基类型的问题——定义复杂数据类型的基础是哪个类型?第二个问题就是派生方式的问题——派生复杂数据类型可以使用限制<restriction>和扩展<extension>两种方式。

(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)派生方式

  • 限制<restriction>
  • 扩展<extension> 

下面是我从这基类型和派生方式两个维度统计的一个列表:

基类型 派生方式 定义时使用的XSD元素 说明
anyType类型 限制

<complexType><complexContent><restriction>

因为anyType只能限制,不能扩展,所以可以省略<complexContent><restriction>元素,

而直接在<complexType>内部使用<all>|<choice>|<sequence>等元素

扩展

anyType类型已经没有任何限制了,所以也就不需要再扩展了

简单类型  限制

<simpleType>

限制简单类型最终结果也是一个简单类型,因此使用<simpleType>元素
扩展

<complexType><simpleContent><extension>

可以通过添加属性或属性组派生复杂数据类型
包含简单内容的复杂类型  限制

<complexType><simpleContent><restriction>

  • 为元素内容增加进一步的约束
  • 为元素的属性类型增加进一步的约束
  • 删除某些属性
扩展

<complexType><simpleContent><extension>

 添加属性
空元素类型 限制

<complexType><complexContent><restriction>

  • 对指定属性增加进一步的约束
  • 删除某个属性
扩展

<complexType><complexContent><extension>

  • 为原有类型增加属性:派生出来的新类型依然是空元素类型
  • 为原有类型增加子元素:派生出来的新类型将是包含子元素的类型
  • 为原有类型增加mixed="true":派生出来的新类型将是混合内容类型
包含子元素的类型 限制 

<complexType><complexContent><restriction>

  • 可以对指定属性的类型增加进一步约束
  • 可以对指定子元素的类型增加进一步约束
  • 可以删除指定属性
  • 可以删除指定元素
扩展

<complexType><complexContent><extension>

  • 为基类型增加新的子元素
  • 为基类型增加新的属性
混合内容类型 限制

<complexType><complexContent><restriction>

 限制混合内容类型的方式和限制包含子元素的类型基本相同
扩展

<complexType><complexContent><extension>

 扩展混合内容类型的方式和扩展包含子元素的类型基本相同,但是必须保留mixed="true"

  派生类型的另外一种用法:

  假设在XSD中定义了元素<book>,其类型是book_type(包含一个name属性),同时还定义了book_type的派生数据类型extended_book_type(在book_type基础上添加就价格price属性),这种情况下,在实际XML文档中, 可以以如下两种方式使用<book>元素:

<!--1。第一种方式,book元素实际类型为book_type类型-->
<book name="example1"/> <!--2。第二种方式,使用xsi:type指定book元素的实际类型为extended_book_type,这里xsi为命名空间http://www.w3.org/2001/XMLSchema-instance对应的前缀-->
<book name="example2" xsi:type="extended_book_type" price="100"/>

5、一致性约束

  定义元素还可以指定3种类型的约束:

  • key约束:相当于DB里面的主键约束,要求指定内容必须存在而且唯一
  • keyref约束:相当于DB里面的外键约束,要求指定内容的值必须使用refer属性引用另一个key约束或unique约束
  • unique约束:相当于DB里面的唯一约束,要求指定内容必须唯一,但可以不存在

这3个一致性约束都只能在<element>元素内定义,且只能在<element>元素的最后面定义。

  在DB中定义约束时,不仅需要指定使用哪类约束,还需要定义应该对哪些字段应用约束,在XSD中定义一致性约束也完全类似,也需要指定该约束将对哪些部分起作用,因此需要在约束内使用如下两个子元素:

  • <selector>:需指定一个xpath属性,其值是一个XPath表达式,用来确定一个元素范围,在一次约束定义中,<selector>必须且只能出现一次
  • <field>:需要指定一个xpath属性,其值是一个XPath表达式,在一次约束定义中,<field>至少要出现一次,也可以出现多次

这两个元素的含义是:在<selector>元素的XPath表达式表示的范围内,<field>元素的XPath表达式所表示的内容必须遵守一致性约束,如果有多个<field>元素,则它们的XPath表达式内容的组合必须遵守一致性约束,当XPath表达式所表示的内容无需遵守,这个概念相当于DB中的多列组合约束。

  看下例子:

<xs:element name="book-list">
<xs:complexType>
<xs:sequence>
<xs:element ref="book" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!--定义key约束,只在book-list之内有效-->
<xs:key name="nameKey">
<!--在当前上下文的book元素之内(即book-list/book之内)-->
<xs:selector xpath="book"/>
<!--指定book-list/book元素之内的name元素的值必须存在且唯一-->
<xs:field xpath="name"/>
</xs:key>
</xs:element>

6、定义符号

最后看一下和DTD中对应的定义符号的用法,在XSD中使用<notation>元素定义符号,用来标识XML文档中的外部数据,该元素可接受的属性有:

  • id:指定该符号的唯一标识,通常无需指定
  • name:指定该符号的名称,是一个必填属性,而且该名称在整个XSD内必须是唯一的
  • public:指定该符号所标识数据的外部格式或对应处理程序,必填属性,相当于DTD中<!NOTATION>中PUBLIC的作用
  • system:指定该符号所标识数据的外部格式或对应处理程序,可选属性,相当于DTD中<!NOTATION>中SYSTEM的作用

XML学习笔记5——XSD复杂数据类型的更多相关文章

  1. XML学习笔记4——XSD简单数据类型

    XSD提供了数据类型,并且支持自定义数据类型,但这一切都是建立在XSD内置数据类型和一套扩展内置数据类型的规则基础之上的,在这一篇笔记中,就来看看XSD中的数据类型. 1.XSD数据类型图 先看一下数 ...

  2. XML学习笔记7——XSD实例

    在前面的XSD笔记中,基本上是以数据类型为主线来写的,而在我的实际开发过程中,是先设计好了XML的结构(元素.属性),并写好了一份示例,然后再反过来写XSD文件(在工具生成的基础上修改),也就是说,是 ...

  3. XML学习笔记3——XSD简述

    现在的语言,如果不有那么一点OO的影子,都不好意思称之为语言了.在XML的语义约束方面,DTD虽然简单,但是功能不够强大,完全是直白的描述,于是又有了替代DTD的XSD(XML Schema Defi ...

  4. delphi操作xml学习笔记 之一 入门必读

    Delphi 对XML的支持---TXMLDocument类       Delphi7 支持对XML文档的操作,可以通过TXMLDocument类来实现对XML文档的读写.可以利用TXMLDocum ...

  5. XML学习笔记

    XML学习笔记 第一部分:XML简介 我们经常可以听到XML.HTML.XHTML这些语言,后两者比较清楚,一直不是很明白XML是什么,这里做一个总结. XML(eXtensible Markup L ...

  6. Mysql学习笔记(二)数据类型 补充

    原文:Mysql学习笔记(二)数据类型 补充 PS:简单的补充一下数据类型里的String类型以及列类型... 学习内容: 1.String类型 2.列类型存储需求 String类型: i.char与 ...

  7. Mysql学习笔记(一)数据类型

    原文:Mysql学习笔记(一)数据类型 学习内容: Mysql基本数据类型. 1.数字类型.. i.整型     Mysql数据类型             含义(有符号)     tinyint(m ...

  8. JavaSE学习笔记(1)---数据类型、运算符、控制结构

    javaSE学习笔记(1) 数据类型和运算符 1.注释可以提高程序的可读性.可划分为 单行注释 // 多行注释 /.../ 文档注释 /**...*/ 2.标识符的命名规则: 标识符必须以字母.下划线 ...

  9. XML学习笔记(三) -- Schema

    标签(空格分隔): 学习笔记 Schema的格式 XML Schema文档是由元素.属性.命名空间和XML文档中的其他节点构成的. XML Schema有两种重要的Schema模型:Microsoft ...

随机推荐

  1. .NET 4.5+项目迁移.NET Core的问题记录

    .NET 4.5+项目迁移.NET Core的问题记录 这几天试着把目前的开发框架迁移到新的.net core平台,中间遇到的问题在这里简单记录一下. 迁移过程遇到的最大的问题IOC容器.我目前使用的 ...

  2. [UCSD白板题] Points and Segments

    Problem Introduction The goal in this problem is given a set of segments on a line and a set of poin ...

  3. 未能从程序集“System.ServiceModel, Version=3.0.0.0问题解决

    在Windows Server 2008中的IIS服务器中部署WCF服务程序时,通过浏览器访问报出如下错误: 未能从程序集“System.ServiceModel, Version=3.0.0.0, ...

  4. 编译器错误信息: CS0433: 类型“ASP.usercontrols_total_ascx”同时存在

    “/”应用程序中的服务器错误. 编译错误 说明: 在编译向该请求提供服务所需资源的过程中出现错误.请检查下列特定错误详细信息并适当地修改源代码. 编译器错误信息: CS0433: 类型“ASP.use ...

  5. Restore Oracle database to another server

    1. Copy or remotely mount the backupset folder from the source server to the target server 2. On the ...

  6. 嵌入式linux开发环境构建

    2.1硬件环境构建 2.1.1主机与目标板结合的交叉开发模式 在主机上编辑.编译软件,然后再目标办上运行.验证程序. 对于S3C2440.S3C2410开发板,进行嵌入式Linux开发时一般可以分为以 ...

  7. B树系列

    参见 http://blog.csdn.net/quitepig/article/details/8041308

  8. 20145301&20145321&20145335实验五

    20145301&20145321&20145335实验五 这次实验我的组员为:20145301赵嘉鑫.20145321曾子誉.20145335郝昊 实验内容详见:实验五

  9. Android--短信

    1.Android 提供一系列 API,可以是我们在自己的程序中发送和接收短信: 2.接收短信: 1)当手机接收到一条短信时,系统会发出一条值为 android.provider.Telephony. ...

  10. Java学习笔记(五)

    作业1:将指定目录下的所有文件显示到列表框(JList)组件中. 代码如下: import java.awt.; import java.awt.event.; import javax.swing. ...