和简单数据类型对应就是复杂数据类型了,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. java中枚举(enum)小例子。之前学过枚举但是一直没用,这里有个枚举类帮你我理解下(很肤浅)

    直接上枚举类,代码简单易懂. package com.jy.modules.cims.data.interact.tbj.loan.request; /** * * @author shengzhou ...

  2. 【九度OJ】题目1111:单词替换

    题目1111:单词替换 题目描述: 输入一个字符串,以回车结束(字符串长度<=100).该字符串由若干个单词组成,单词之间用一个空格隔开,所有单词区分大小写.现需要将其中的某个单词替换成另一个单 ...

  3. apache虚拟主机配置HTTPS

    win+apache+php的环境下做虚拟主机的https. 1.https用的是443端口,确定防火墙已经开放443了.2.http.conf要加载以下模块: #这两个是用来存放SSLSession ...

  4. Linq学习工具及Lamada表达式

    好东西.转载一个.以备学习 Linq学习工具:     http://www.linqpad.net/ Lamada表达式: Func<int, int, int> IntPow = (x ...

  5. (转)如何为你的Viewcontroller瘦身

    View controllers are often the biggest files in iOS projects, and they often contain way more code t ...

  6. Activity劫持实例与防护手段

    原文地址:Activity劫持实例与防护手段 作者:cjxqhhh (本文只用于学习技术,提高大家警觉,切勿用于非法用途!)   什么叫Activity劫持   这里举一个例子.用户打开安卓手机上的某 ...

  7. Select loop

    The Bash Shell also offer select Loop, the syntax is: select varName in list do command1 command2 .. ...

  8. iOS开发零基础--Swift篇 元组

    元组的介绍 元组是Swift中特有的,OC中并没有相关类型 它是什么呢? 它是一种数据结构,在数学中应用广泛 类似于数组或者字典 可以用于定义一组数据 组成元组类型的数据可以称为“元素” 元组的定义 ...

  9. Windows下mysql忘记root密码的解决方法

    1. 首先检查mysql服务是否启动,若已启动则先将其停止服务,可在开始菜单的运行,使用命令: net stop mysql 打开第一个cmd窗口,切换到mysql的bin目录,运行命令: mysql ...

  10. linux Makefile编写的整理

    最近将Makefile的编写进行了整理和提炼了一下,大致分为五个步骤: 编译总共为五个部分 1.设置编译环境 set compile environment 2.获取要编译的源文件,以及把源文件转换为 ...