为什么80%的码农都做不了架构师?>>>
当你使用Web Service、SOAP 传递或接受数据进行通讯时,
当你使用Spring、Struts、Maven 等当今流行框架及工具进行搭建配置时,
当你开发中需要解析Html、xls、PDF、Access 等文件时,
你会发现Xml将是这些领域中一项不可或缺的技术。可是你真正的研究过其中的奥秘么?如果一直以来只是一知半解的话,那么接下来就跟我一起扫扫盲吧。
一、XML与XSD(XML Schema Definition)
IT男's blog
http://www.it-nan.com
上面这行代码是一个简单的xml格式文档。下面我们来逐一了解其中的含义:
第一行:xml标签,指明这是一个xml文档;version是版本号(指明xml的版本);encoding是编码规则(指明当前文档采用的编码格式 )。
第二行:xmlns是默认命名空间,声明url为“http://www.it-nan.com/schema/libs”的是默认的命名空间(如果后面有:xxx 则表明是定义为xxx的命名空间,如:xmlns:xsi);itnan是默认命名空间中定义的根节点标签(如果前面有类似于xxx: 的前缀,则表明该标签是从xxx命名空间中定义的标签,如:xsi:schemaLocation)。
第三行:这行是声明url为“http://www.w3.org/2001/XMLSchema-instance”的命名空间,由前缀xsi代表。“http://www.w3.org/2001/XMLSchema-instance”这个地址为xml的基础空间,所有的基础属性的定义都来自于这里,如:下面用到的schemaLocation属性,xsi是开发人员约定的一个名字,不是固定的,可以随意定义。
第四行:这行是用于指定命名空间与定义标签结构的XSD(XML Schema Definition)文件的对应关系。schemaLocation属性的值由多个URI引用对组成,两个URI之间以空白符分隔。第奇数个URI是命名空间的名字,第偶数个URI给出模式文档的位置(可以是url地址,也可以是相对路径),编辑器将从这个位置读取XSD文件,并与他的命名空间匹配来限制该空间下的标签结构。
第五、六行:这个是在定义itnan下的标签,而这个标签的结构是根据默认命名空间下的xsd文件定义出来的。下面就让我们看看xsd文件是如何定义的。
上面这行代码是一个简单的xsd文档。下面我们来逐一了解其中的含义:
第一行:由于xsd文档也是符合xml规范的,所以也要在第一行声明这是一个xml文档;version是版本号(指明xml的版本);encoding是编码规则(指明当前文档采用的编码格式 )。
第二行:xmlns也同上面xml文档的一样表示默认的命名空间;而“http://www.w3.org/2001/XMLSchema”这个地址为xsd的基础命名空间,所有的基础属性的定义都来自于这里,如:下面用到的targetNamespace、elementFormDefault、element等。
第三行:由于这个xml文档里的“http://www.w3.org/2001/XMLSchema”为默认命名空间,而targetNamespace就是这个命名空间所定义的属性,所以targetNamespace属性不用加前缀修饰。这个属性是用于定义下面所规定的标签结构服务于哪个命名空间,所以这个值是与引用这个xsd文件的xml文档中声明的schemaLocation属性的命名空间必须要一致。(而这里表示下面的这些定义都是用于“http://www.it-nan.com/schema/libs”命名空间下的标签)
第四行:elementFormDefault有两个值“qualified”和“unqualified”。“qualified”表示:下面定义的所用标签都为targetNamespace设置的命名空间服务,而“unqualified”表示:除了全局元素或者类型将归于目标命名空间外,局部元素将归于无名命空间。(这个属性大部分都设置为“qualified”)
第五行之后:这些就都是xsd用来定义xml文档标签结构的代码,下面统一介绍。
二、常用的Schema文档教程
1. 最简单的Schema文档
如何写一个最简单的XML Schema文档呢?
首先,我们写出一个最简单的XML文档。
hello.xml:
Hello World!!
hello.xsd:
XML Schema文档后缀名是.xsd,完全符合XML语法,根元素是schema,命名空间xmlns:xsd=”http://www.w3.org/2001/XMLSchema,用元素定义实例文档中的元素,如greeting。
2. 含子元素的Schema文档
假设实例文档是如下的:
customer.xml:
teiki
No.237, Road Waitan, Shanghai
则可以写出以下的XML Schema文档:
customer.xsd:
实例文档customer.xml中,元素含有两个子元素,所以我们在Schema文档中采用ComplexType来定义该元素。sequence表示子元素依次出现的顺序。
3. 含子元素和孙元素的Schema文档
这次我们给出一个更加复杂一些的文档:
customer.xml:
Teiki
Zhejiang
Hangzhou
Xilu Road, No.121, 7F
为此,我们需要一个更加复杂一点的Schema文档:
address.xsd:
不过,我们还可以采用ref元素来重新编写这个Schema文档:
address2.xsd:
使用ref元素可以直接将其指向另一个模块,使文档更加具有可读性。
4. 定义相同子元素的数量
先看这个简单的订购数据实例文档:
order.xml:
Accounting Book Taxation Book
假设元素,即每次的订购书目不能超过10种,那该怎么写这个Schema文档呢?这里要用到的maxOccurs属性。
order.xsd:
第7行中的maxOccurs属性为10,代表orderItem元素可以最大有10个。如果,不设定元素个数,则可以用maxOccurs=”unbounded”来定义。
类似,如果要定义最小值,可以使用minOccurs,比如下面这句:
这两个属性缺省值都是1。
5. 定义可选项的子元素
假如上面的订书数据中,可以用书名或者书号任一一种订购,则实例文档可能如下:
order2.xml:
Accounting Book
7-5058-3496-7
这时书写Schema文档还需要使用choice元素。
order2.xsd:
稍微更复杂的可选项子元素
再稍微修改一下订书数据的实例文档:
order3.xml:
Accounting Book
2
7-5058-3496-7
这里假定值为1时,缺省。
如何修改Schema文档呢?
order3.xsd:
文档中的quantity最少出现值为0,也就是可以有,也可以没有。
当然,也可以直接在元素中,包含quantity,然后定义它的minOccurs。
6. 内置简单类型
具有简单类型的元素只能包含字符数据,不能包含子元素,也不能有属性。XML Schema推荐标准内置了44种简单类型,如例中的xs:string、xs:integer等,这些简单类型可以直接引用。XML Schema内置的数据类型的层次结构如下图所示。
xsd-simpleType
XML Schema支持类型的派生,这和面向对象语言中对象的继承有些类似,但又不完全相同。XML Schema类型的派生分为限制(restriction)和扩展(extension),通过限制派生的新类型的值范围是原类型值范围的子集,通过扩展则可以为现有类型添加新的元素和属性。
对于简单类型,只有限制派生而没有扩展派生,我们只能通过限制一个现有的简单类型(内置的简单类型或派生于内置简单类型的简单类型)来派生一个新的简单类型。那如何对现有的简单类型进行限制呢?XML Schema给我们提供了12个面(facet),用于指定一个值的有效范围、约束值的长度和精度、枚举一系列的有效值,或者指定有效值必须匹配的正则表达式。
面与类型的关系就好像棱镜的面与棱镜的关系,透过不同的面,你看到的景观(内容)是不同的。在XML Schema中,面相当于是对一个现有的简单类型添加某些约束(限制),约束不同,得到的结果就不同。也就是说,你可以把面(facet)看成是对数据类型的约束,目的是为了让它的值限制在一定的范围内。实际上,这些面就是http://www.w3.org/2001/XMLSchema名称空间中的一些元素,只不过这些元素是用来对现有类型的值进行约束的,因而称为面。
要定义新的简单类型,使用xs:simpleType元素,要对现有的基类型进行限制,使用xs:restriction元素,并在该元素的内部使用限制值范围的面(facet)。例如,我们定义一个雇员年龄的类型,雇员年龄要求在18~60岁之间,我们可以从内置的xs:integer类型派生一个新的简单类型ageType,然后使用xs:minInclusive和xs:maxInclusive面来限制年龄值的范围。
例如这个实力文档:
7. 自定义简单类型
如果内置简单类型的44种还不能满足要求,怎么办呢?下面学习自定义简单类型。(XML的扩展性充分体现在这里)
例如这个实例文档:
order4.xml:
7-5058-3496-7
5
ID是一个标准的ISBN编码,我们怎么定义这个ISBN编码呢?
idType是一个自定义的简单类型。
我们对它做了限制:
value=”\d{1}-\d{4}-\d{4}-\d{1}”这是一个正则表达式,关于正则表达式,以后再介绍。嘻嘻!
利用这个自定义的简单类型,我们可以重新写Schema文档:
order4.xsd:
假如我们事先确定好ID只有3个,即只有3个ISBN是可选的,那怎么办?我们可以用enumeration元素来进行列举。
再来看订购量quantity的值,如果我们设定其值必须在1-10之间,该怎么办呢?可以这些自定义一个简单类型。
其中,minInclusive,maxInclusive分别代表该类型的取值范围。
所以最终修改后的Schema文档如下:
order4-1.xsd:
8. 定义属性
最后,我们再来讲讲元素的属性如何在Schema文档中定义。
比如上面的order.xml实例文档中:
对此,我们在Schema文档中采用一个attribute来定义:
order.xsd:
←空元素
那么,实例文档中该属性值是必须的还是可有可无的呢?我们可以这样限制:
这里我们讲id属性类型作为一种自定义数据类型idType。
而且,用attribute元素的use属性来定义是否是必须的属性。
required是必须值,optional是可选值,prohibited是无属性值。
那么对于属性的缺省值,我们怎么定义呢?
比如:
我们还可以用attribute元素的另一个属性default来定义:
所以,我们可以重新写出一个Schema文档:
order2.xsd:
上面的属性我们定义我们还可以采用属性组的办法来重新改写Schema文档。
order3.xsd:
这个属性组就不详细解释了,不过,大家一看就清楚了吧。
9.最后,我们写一个完整的订书order.xml的Schema文档。