随笔 - 17  文章 - 49  trackbacks - 0
<2006年10月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

留言簿(1)

随笔分类(17)

随笔档案(17)

相册

最新随笔

搜索

  •  

最新评论

阅读排行榜

评论排行榜

2006 8 23 星期三

XSD 浅学笔记

 

简单明快的 XSD 的入门笔记,希望能让你和我一样,用半天时间步入第一道门槛。

这一片记录基础知识,第二篇会是些进阶知识和总结,然后你就可以写出自己的第一个 XSD 文档,并用来验证一个 XML 文档了。

XSD 是什么 ?

一个 xml schema 是用来描述 xml 文档结构的,而 XSD xml schema definition 是继 DTD 后的基于 xml schema 语言,比起 DTD ,它有更好的扩展性,增加了功能,更重要的是,它本身就是以 xml 来写的,而不需要象 DTD 那样重新学一门语言。同时也可以利用所有对 xml 有效的便利。

那么为什么要有 schema 呢, xml well-formed 是不足够的,一个语法上合法的 xml 仍然可能有错误,而这些错误可能导致严重的应用后果。

 

基础概念

第一印象

      

以下是一份 xml 文档

<?xml version="1.0"?>

<note>

<to>Tove</to>

<from>Jani</from>

<heading>Reminder</heading>

<body>Don't forget me this weekend!</body>

</note>

 

而它对应的一份 xsd 会是这样的:

 

<?xml version="1.0"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

targetNamespace="http://www.w3schools.com"

xmlns="http://www.w3schools.com"

elementFormDefault="qualified">

<xs:element name="note">

    <xs:complexType>

      <xs:sequence>

       <xs:element name="to" type="xs:string"/>

       <xs:element name="from" type="xs:string"/>

       <xs:element name="heading" type="xs:string"/>

       <xs:element name="body" type="xs:string"/>

      </xs:sequence>

    </xs:complexType>

</xs:element>

</xs:schema>

 

简单元素:

简单元素是不包含其他元素和属性的元素。

定义简单元素的语法为:

<xs:element name="xxx" type="yyy"/>

常用的内建类型有:

xs:string

xs:decimal

xs:integer

xs:boolean

xs:date

xs:time

可以通过 default 属性和 fixed 属性来修饰。

<xs:element name="color" type="xs:string" default="red"/>

<xs:element name="color" type="xs:string" fixed="red"/>

 

属性:

只有复合元素可以有属性,但属性本身总是被定义为简单类型的。

<xs:attribute name="xxx" type="yyy"/>

除了和简单元素的定义一样可以用 default fixed 来作为属性之外,还可以用 use 属性,如果把 use 属性指定为“ required ”,就说明这个属性在 xml 文档中是必须指明的,默认情况下属性的使用是可选的。

 

限制

当一个元素或者属性定义了类型( type ), 就可以用 restriction 来限制这个类型, restriction 又叫 facet ,可以为类型增添更多的细节要求。当 xml 文档中对应的元素值违反了这个 restriction 就不能通过检验。限制是 XSD 里比较常用的内容,我们会看大量的例子。

 

对数值大小的限制:(只能取 0 120 的闭区间)

<xs:element name="age">

<xs:simpleType>

  <xs:restriction base="xs:integer">

    <xs:minInclusive value="0"/>

    <xs:maxInclusive value="120"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

将值限制在一组既定值内:(类似于枚举 enumeration

<xs:element name="car">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:enumeration value="Audi"/>

    <xs:enumeration value="Golf"/>

    <xs:enumeration value="BMW"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

限制一定范围的值:(只能取小写的 26 个字母)

<xs:element name="letter">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:pattern value="[a-z]"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

(只能取长度为 3 的大写字母组合)

<xs:element name="initials">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:pattern value="[A-Z][A-Z][A-Z]"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

(只能取长度为 3 的字母,大小写均可)

<xs:element name="initials">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:pattern value="[a-zA-Z][a-zA-Z][a-zA-Z]"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

(只能取 xyz 中的一个)

<xs:element name="choice">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:pattern value="[xyz]"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

(只能取长度为 5 的数字串)

<xs:element name="prodid">

<xs:simpleType>

  <xs:restriction base="xs:integer">

    <xs:pattern value="[0-9][0-9][0-9][0-9][0-9]"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

(只能取任意长度的小写字符串,长度可以为 0

<xs:element name="letter">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:pattern value="([a-z])*"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

(有了上一个,你自然也会猜到这一个:只能取长度大于 0 的字符串)

<xs:element name="letter">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:pattern value="([a-z][A-Z])+"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

(选取,其实和前面的枚举式功效类似,只能取其一)

<xs:element name="gender">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:pattern value="male|female"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

(特定长度的字符数字串,用作密码最合适。)

<xs:element name="password">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:pattern value="[a-zA-Z0-9]{8}"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

(如果不需要在 base 上加内容限制,也可以这样来表达长度)

<xs:element name="password">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:length value="8"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

(设定长度区间)

<xs:element name="password">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:minLength value="5"/>

    <xs:maxLength value="8"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

另外,在 xml 里,空白符的情况比较特别,不小心处理就得不到你要的真正效果。

 

(保留所有的空白符)

<xs:element name="address">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:whiteSpace value="preserve"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

( 所有的回车,过行,制表符,长空白都被替换成相应长度的空格符 )

<xs:element name="address">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:whiteSpace value="replace"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

(所有空白符都被变为单空格符,首尾空白都被去掉)

<xs:element name="address">

<xs:simpleType>

  <xs:restriction base="xs:string">

    <xs:whiteSpace value="collapse"/>

  </xs:restriction>

</xs:simpleType>

</xs:element>

 

最后,上面说到的所有的限制,还可以以下面这种格式来写,把 simpleType 加上名字,在元素中的 type 引用这个名字,好处就是它不再单独属于这个元素或者属性的定义了,其他元素可以复用这个类型限制,类似于面向对象编程语言中的包装与复用。

<xs:element name="car" type="carType"/>

<xs:simpleType name="carType">

  <xs:restriction base="xs:string">

    <xs:enumeration value="Audi"/>

    <xs:enumeration value="Golf"/>

    <xs:enumeration value="BMW"/>

  </xs:restriction>

</xs:simpleType>

 

复合元素

复合元素的定义就和简单元素的刚好相反了,就是包含其他元素或属性的元素。

细分一下有四种:

空元素;

<product pid="1345"/>

 

只包含其他元素的;

<employee>

<firstname>John</firstname>

<lastname>Smith</lastname>

</employee>

 

只有文本内容的;

<food type="dessert">Ice cream</food>

 

 

同时包括文本内容和其他元素的。

<description>

It happened on <date lang="norwegian">03.03.99</date> ....

</description>

而这四个同时又都可以有属性。

 

接下来我们一一详细介绍。

<product prodid="1345" />

空元素的定义语法:

<xs:element name="product">

  <xs:complexType>

    <xs:attribute name="prodid" type="xs:positiveInteger"/>

  </xs:complexType>

</xs:element>

 

 

<person>

<firstname>John</firstname>

<lastname>Smith</lastname>

</person>

包含其他元素的复合元素定义:

<xs:element name="person">

  <xs:complexType>

    <xs:sequence>

      <xs:element name="firstname" type="xs:string"/>

      <xs:element name="lastname" type="xs:string"/>

    </xs:sequence>

  </xs:complexType>

</xs:element>

xs:sequence 来定义这些元素必须按照这个次序出现,类似于 sequence 这样的指示符还有几个,稍后统一介绍。

 

定义一个只有文本内容和属性的复合元素,我们需要用一个 simpleContent 标记,再用一个 restriction 或者 extension 来限制文本的内容 :

 

<xs:element name="somename">

  <xs:complexType>

    <xs:simpleContent>

      <xs:extension base="basetype">

        ....

        ....

      </xs:extension>    

    </xs:simpleContent>

  </xs:complexType>

</xs:element>

或:

<xs:element name="somename">

  <xs:complexType>

    <xs:simpleContent>

      <xs:restriction base="basetype">

        ....

        ....

      </xs:restriction>    

    </xs:simpleContent>

  </xs:complexType>

</xs:element>

例子:

<xs:element name="shoesize">

  <xs:complexType>

    <xs:simpleContent>

      <xs:extension base="xs:integer">

        <xs:attribute name="country" type="xs:string" />

      </xs:extension>

    </xs:simpleContent>

  </xs:complexType>

</xs:element>

注意 extension integer 是限制 shoesize 的文本内容,而 attribute string 是限制 attribute 本身的内容的。

对应这个复合模式的 xml 可以是:

<shoesize country="france">35</shoesize>

 

要描述混合的复合元素:

<letter>

Dear Mr.<name>John Smith</name>.

Your order <orderid>1032</orderid>

will be shipped on <shipdate>2001-07-13</shipdate>.

</letter>

就可以用:

<xs:element name="letter">

  <xs:complexType mixed="true">

    <xs:sequence>

      <xs:element name="name" type="xs:string"/>

      <xs:element name="orderid" type="xs:positiveInteger"/>

      <xs:element name="shipdate" type="xs:date"/>

    </xs:sequence>

  </xs:complexType>

</xs:element>

只是在包含其他元素的同时指定 mixed 等于“ true “,而 sequence 或其他指示符的使用依然有效。你的文本可以穿插于元素之间,但元素的出现次序仍受 sequence 的限制。

 

记得简单元素里的复用吗,这里同样可以,在 complexType 标记里加上 name 属性,就完成了分离和复用了,对上面所有的复合类型都是通用的。即使写 xsd ,也要象 oop 语言那样,通过复用来提高修改的效率,同时让页面看起来整洁清晰,至少,我是有着这样的偏执的,呵呵。

 

指示符里有以下几种:

顺序指示符:

All 所有元素可以不分顺序出现,但只能出现一次。

Choice 只有其中一个可以出现

Sequence 前面说过了,必须按顺序出现。

上面的限制可以配合次数指示符加以进一步的限制:

maxOccurs 最多出现次数

minOccurs 最少出现次数

例如:

<xs:element name="person">

  <xs:complexType>

    <xs:sequence>

       <xs:element name="full_name" type="xs:string"/>

      <xs:element name="child_name" type="xs:string"

      maxOccurs="10" minOccurs="0"/>

    </xs:sequence>

  </xs:complexType>

</xs:element>

注意用了 all 的时候,最大次数还是不能超过 1 ,最小可以是 0 1

 

组指示符:

Group 元素组

attributeGroup 属性组

通过例子来看看:

<xs:group name="persongroup">

  <xs:sequence>

    <xs:element name="firstname" type="xs:string"/>

    <xs:element name="lastname" type="xs:string"/>

    <xs:element name="birthday" type="xs:date"/>

  </xs:sequence>

</xs:group>

定义了一组元素, group 必须包含已经用顺序指示符包含起来的元素。

定义后,别的地方可以用 ref 来引用:

<xs:complexType name="personinfo">

  <xs:sequence>

    <xs:group ref="persongroup"/>

    <xs:element name="country" type="xs:string"/>

  </xs:sequence>

</xs:complexType>

 

以下这两个是对应的 attribute group 的用法:

<xs:attributeGroup name="personattrgroup">

  <xs:attribute name="firstname" type="xs:string"/>

  <xs:attribute name="lastname" type="xs:string"/>

  <xs:attribute name="birthday" type="xs:date"/>

</xs:attributeGroup>

 

<xs:element name="person">

  <xs:complexType>

    <xs:attributeGroup ref="personattrgroup"/>

  </xs:complexType>

</xs:element>

 

这一篇到这里为止。

 

posted on 2006-08-23 18:25 Ye Yiliang 阅读(1198) 评论(7)  编辑  收藏 所属分类: Java

FeedBack:
# re: XSD浅学笔记 2006-08-25 09:48 hsp
~~~~~~~~~~~~~go on  回复  更多评论
  
# re: XSD浅学笔记 2006-08-25 11:17 yeyiliang
- -b@hsp
  回复  更多评论
  
# re: XSD浅学笔记 2006-08-25 16:08 icedee
不错,_^^_  回复  更多评论
  
# re: XSD浅学笔记 2006-09-07 22:13 stoneshao
不错,狠狠地补了一把;D  回复  更多评论
  
# re: XSD浅学笔记 2006-10-12 11:46 谔谔
不错,不错,希望继续努力啊!
  回复  更多评论
  
# re: XSD浅学笔记 2006-12-22 12:23 Away
对于入门者, 受益了。  回复  更多评论
  
# re: XSD浅学笔记 2007-01-22 12:01 xkq
呵呵,写的很好啊 ,继续加油哦 !  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: