3.2.2.1 Schema 的简单实例
   

好了,上一节讲了很多Schema的优点和发展历程,除了要为Schema歌功颂德以外,就是要在大家脑海里建立一个基本概念:Schema是用XML规范改写的DTD,同时增加了一些扩充功能,使它具有DTD无以比拟的优势。不知道是不是有些读者正在后悔,前面花了这么多时间去学DTD,原来是在学一个可能要被淘汰的东东。其实,就象上一节里所讲的,DTD和Schema是一脉相承的,了解DTD可以帮助你更快更透彻地学习Schema。后面对于Schema语法的讲述也正是通过二者的对比来进行的,你可以从这种比较中慢慢体会Schema的优势所在。

下面,就让我们言归正传,看一看Schema长得什么样吧!不过先别忙,首先我们来看一个简单的例子。还记得我们的“联系人列表”文件吗?现在我们就把它作一个小小的改动,为“联系人列表”这个元素加一个“公司”属性,指明该列表所属的公司,修改后的XML文件如下:

<?xml version = "1.0" encoding="GB2312" standalone = "no"?>
<!DOCTYPE 联系人列表  SYSTEM "fclml.dtd">

<联系人列表 公司=“大地公司”>
    <联系人>
        <姓名>张三</姓名>
        <ID>001</ID>
        <公司>A公司</公司>
        <EMAIL>zhang@aaa.com</EMAIL>
        <电话>(010)62345678</电话>
        <地址>
            <街道>五街1234号</街道>
            <城市>北京市</城市>
            <省份>北京</省份>
            <ZIP>100001</ZIP>
        </地址>
    </联系人>

    <联系人>
        <姓名>李四</姓名>
        <ID>002</ID>
        <公司>B公司</公司>
        <EMAIL>li@bbb.org</EMAIL>
        <电话>(021)87654321</电话>
        <地址>
            <街道>南京路9876号</街道>
            <城市>上海</城市>
            <省份>上海</省份>
            <ZIP>200002</ZIP>
        </地址>
    </联系人>
</联系人列表>

相应的,它的DTD文件fclml.dtd也要作一点改动:

<?xml version="1.0" encoding="GB2312"?>

<!ELEMENT 联系人列表 (联系人)*>
<!ELEMENT 联系人 (姓名,ID,公司,EMAIL,电话,地址)>
<!ELEMENT 地址 (街道,城市,省份)>
<!ELEMENT 姓名 (#PCDATA)>
<!ELEMENT ID (#PCDATA)>
<!ELEMENT 公司 (#PCDATA)>
<!ELEMENT EMAIL (#PCDATA)>
<!ELEMENT 电话 (#PCDATA)>
<!ELEMENT 街道 (#PCDATA)>
<!ELEMENT 城市 (#PCDATA)>
<!ELEMENT 省份 (#PCDATA)>
<!ATTLIST 联系人列表
    公司 CDATA #REQUIRED
>

同样的文档结构要用Schema来描述的话,可写做下面的样子。我们给这个文件取名fclmlschema.xml。也许你要问:"为什么以.xml作为扩展名,而不象DTD那样有个特殊的名字?"答案很明确,因为Schema本身就是XML文档实例,以.xml作为扩展名正是为了强调这一点。不过,这并不是说,就只能以.xml作为扩展名。如果你愿意,你完全可以给它取一个全新的名字,比如:.aaa、.schema、...,只要你的文件系统支持就行。

[1]<?xml version="1.0" encoding="GB2312" ?>
[2]<Schema xmlns="urn:schemas-microsoft-com:xml-data"
               xmlns:dt="urn:schemas-microsoft-com:datatypes">
[3]    <AttributeType name="公司"/>
[4]    <ElementType name= "姓名"/>
[5]    <ElementType name= "ID"/>
[6]    <ElementType name= "公司"/>
[7]    <ElementType name= "EMAIL"/>
[8]    <ElementType name= "电话" dt:type="fixed.14.4"/>
[9]    <ElementType name= "街道"/>
[10]  <ElementType name= "城市"/>
[11]  <ElementType name= "省份"/>
[12]  <ElementType name= "地址" content="eltOnly">
[13]       <element type= "街道" />
[14]       <element type= "省份" />
[15]       <element type= "城市" />
[16]  </ElementType>
[17]  <ElementType name= "联系人" content="eltOnly">
[18]       <element type= "姓名" />
[19]       <element type= "ID" />
[20]       <element type= "公司" />
[21]       <element type= "EMAIL" />
[22]       <element type= "电话" />
[23]       <element type= "地址" />
[24]  </ElementType>
[25]  <ElementType name= "联系人列表" content="eltOnly">
[26]       <element type= "联系人" />
[27]       <attribute type="公司"/>
[28]  </ElementType>
[29]</Schema>

此外,为了告诉语法分析器现在是在用fclmlschema.xml给XML文件client.xml规定的文件结构,需要把client.xml文件中的第二行改成:

<学生花名册 xmlns="x-schema:rosterschema.xml">

下面我们就来逐字逐句地分析一下这个fclmlschema.xml:

[1]是XML类型声明语句,指明该文档是一个XML文档,并且符合版本1.0规范。另外,该文档采用GB2312编码。
[2]是Schema声明语句,它包含了Schema命名空间的声明。本例中用到了两个命名空间:一是xmlns="urn:schemas-microsoft-com:xml-data",它指定本文档是一个XML Schema文档;另一个是xmlns:dt="urn:schemas-microsoft-com:datatypes",它定义了在本文档中可允褂玫氖堇嘈汀9赜诿占浣谙乱唤谥邢晗嘎凼觥?/dd>
[3]是属性定义语句,它定义了属性“公司”。
[4]-[11]是元素定义语句,这里共定义了8个元素:姓名、ID、公司、EMAIL、电话、街道、城市、省份。其中为"电话"元素定义了数据类型:fixed.14.4。
[12]-[16]定义了本Schema的二级元素:地址,指明该元素包含三个子元素:街道、城市、省份。
[17]-[24]定义了本Schema的三级元素:联系人,它指明该元素包含六个子元素:姓名、ID、公司、EMAIL、电话、地址。
[25]-[28]定义了本Schema的顶级元素:联系人列表,指明该元素包含一个子元素:联系人,以及一个属性:公司。
[29]是结束标记语句,它指明该Schema的描述到此为止。

怎么样?简单吧。大概已经对XML有些造诣的广大读者不用看解释也能读懂这个Schema文件。下面,我们就来从整体上看一下XML Schema语法,下面给出的是XML Schema的DTD描述,相信已经熟悉DTD的你会有一种驾轻就熟的感觉。

<!ENTITY % datatypes "(entity | entities | enumeration | id | idref | idrefs | nmtoken | nmtokens | notation | string | bin.base64 | bin.hex | boolean | char | date | dateTime | dateTime.tz | fixed.14.4 | float | int | number | time | time.tz | i1 | i2 | i4 | r4 | r8 | ui1 | ui2 | ui4 | uri | uuid)"
>

<!-- *** 数据类型 **** -->
<!ELEMENT datatype (description)*>
<!ATTLIST datatype
dt:type %datatypes; #IMPLIED
xmlns:dt CDATA #FIXED "urn:schemas-microsoft-com:datatypes"
>
 
<!-- ***** 描述 ***** -->
<!ELEMENT description (#PCDATA) >
 
<!-- **** 元素引用 ***** -->
<!--附加限制: maxOccurs 必须是 1 or "*" -->
<!ELEMENT element (description)* >
<!ATTLIST element
type IDREF #REQUIRED
minOccurs CDATA #IMPLIED
maxOccurs CDATA #IMPLIED
>
 
<!-- **** 属性引用 ***** -->
<!ELEMENT attribute (description)* >
<!ATTLIST attribute
type IDREF #REQUIRED
default CDATA #IMPLIED
required (yes | no) "no"
>
 
<!-- **** 属性定义 ***** -->
<!ELEMENT AttributeType (datatype | description)* >
<!ATTLIST AttributeType
name ID #REQUIRED
default CDATA #IMPLIED
dt:type %datatypes; #IMPLIED
dt:values CDATA #IMPLIED
required (yes | no) #IMPLIED
xmlns:dt CDATA #FIXED "urn:schemas-microsoft-com:datatypes"
>
 
<!-- **** 元素定义 ***** -->
<!ELEMENT ElementType (datatype | description | AttributeType | attribute | element | group)* >
<!ATTLIST ElementType
name ID #REQUIRED
model (open | closed) #IMPLIED
content (empty | textOnly | eltOnly | mixed) #IMPLIED
order (one | seq | many) #IMPLIED
dt:type %datatypes; #IMPLIED
dt:values CDATA #IMPLIED
required (yes | no) #IMPLIED
xmlns:dt CDATA #FIXED "urn:schemas-microsoft-com:datatypes"
>
 
<!-- **** 分组 ***** -->
<!ELEMENT group (group | element | description)*>
<!ATTLIST group
minOccurs CDATA #IMPLIED
maxOccurs CDATA #IMPLIED
order (one | seq | many) #IMPLIED
>
 
<!-- **** Schema ***** -->
<!ELEMENT Schema (AttributeType | ElementType | description )* >
<!ATTLIST Schema
name CDATA #IMPLIED
xmlns:dt CDATA #FIXED "urn:schemas-microsoft-com:datatypes"
>

注意,和前面讲到的有规可循的XML语法的条条框框和DTD的定义方法不同,Schema还没有一个正式推荐标准。在这里,我们所讲的Schema的实现语法都是按照微软Internet Explorer 5.0所提供的支持。这个语法主要综合了W3C的两个Note:规范XML-Data (http://www.w3.org/TR/1998/NOTE-XML-data-0105/ )和文档内容描述DCD (http://www.w3.org/TR/NOTE-dcd ),并加入一些扩展。鉴于微软在业界的地位以及Internet Explorer 5.0的普及程度,该语法实现具有较强的适用性。

从下一节开始,我们将就Schema中的主要元素作详细分析。