<! ATTLIST ElementName
AttributeName Type Default
AttributeName Type Default
…..
>
ATTLIST是一个XML语言的保留字,也可以称为是关键字,就象C++语言中的保留字struct,class,inline等一样。ElementName表示元素的名称,元素的名称相当于程序设计语言中变量的名称,你可以任意取,比如student、teacher、book等等。你要取为ttt、kkk也没关系,只是这种名称不能确切的表示它所代表的意义而已。
一个元素可以包含多个属性,一个属性有三部分构成:属性名称(AttributeName)、属性类型(Type)和属性特点(Default)。AttributeName表示属性的名字,你可以任意取名,比如身高、体重、性别等等。Type表明该属性的类型,就象在C++中我们对一个变量需要指定它的类型(比如int,double,bool等等)。Default表明这个属性的特点,在XML语言中,可以有四种形式:#REQUIRED,#IMPLIED,#FIXED value,defaultvalue。在后面会对这四中形式做详细的说明。
现在我们先来看一下XML所定义的属性类型的种类,见图表:
类型 | 具体的含义说明 |
CDATA | 这个类型表明该属性只能包含字符数据,比如"strong","23","美女","恐龙"等等 |
ID | 该属性的取值必须是唯一的,就象我们每个人都有的身份证号码一样。在一个文档内两个ID属性的值一定不可以一样。 |
IDREF,IDREFS | 这个属性的值实际上就象C++中的指针一样,它是一个指向文档中其他地方声明的ID值。所以如果具体的文档中该属性的取值和它所指向的ID值不匹配的话,就会返回错误。IDREFS和IDREF类似,但是可以具有由空格分隔的多个引用。 |
ENTITY,ENTITIES | ENTITY属性的值必须对应一个在文档内部声明的但还没有分析过的实体。ENTITIES属性和ENTITY类似,不同的是它可以包含多个实体,每一个实体之间可以用空格进行分隔。需要注意的是实体包括普通实体、外部实体、参数实体和外部参数实体。一般来说,你可以把实体理解为类似C++中的一个定义,比如在C++中,我们定义一个变量: const MYCOMPANYNAME="BigSoft"以后你就可以在程序中使用变量MYCOMPANYNAME。这里可以把MYCOMPANYNAME当成一个实体来理解。 |
NMTOKEN,NMTOKENS | NMTOKEN和CDATA非常类似,不同之处在于它是CDATA的一个子集。它所使用的字符必须是字母、数字、句点、破折号、下划线或冒号。NMTOKENS和NMTOKEN类似,不同之处在于它可以包含多个值,每个值之间用空格进行分隔 |
NOTATION | NOTATION属性的值必须引用在文档中其他地方声明的某个注解的名称 |
NOTATION(enumerated) | 该属性的值必须匹配NOTATION名称列表中的某个名称,比如我们已经存在两个NOTATION,一个为beauty,一个为beast。我们可以定义一个属性类型为NOTATION(beauty|beast) |
Enumerated | 这个几乎和C++中的枚举变量一样,我们事先定义好一些值,该属性的值必须匹配所列出的这些值。比如现在有值为美丽、泼辣、性感、智慧。该属性的类型就可以表现为(美丽|泼辣|性感|智慧),实际内容文档必须从这些值中取一个。注意值之间用"|"进行分隔 |
我们看上面的XML的例子,它仅仅用到了两种类型,CDATA和Enumerated,其他的还没有使用。在下面的段落中,我们会陆续介绍这些属性类型的使用,在介绍之前,我们需要详细说明一下Default这个字段。
上面我们已经提到Default这个字段可以包含四种形式,下面的表格对这四种形式进行了详细的介绍:
值 | 含义 |
#REQUIRED | 用来告诉XML解析程序,该元素的所有实例都必须有该属性的值。就象数据表中某一个字段不允许为空一样。 |
#IMPLIED | 表示如果该元素的实例中没有指定该元素的值的话,就忽略该属性。就象在数据表中某一个字段的值可以为NULL一样。 |
#FIXED value | 表示包含该属性的元素实例必须指定所列出的值,比如一个属性名称为美女:美女 CDATA #FIXED "我的老婆"表示如果在实例中没有列出这个属性的话,解析器依然认为存在美女这个属性,它的值就是"我的老婆"。一般的应用是设计这个属性用来说明这些文档都是由一个DTD来实例化产生的。 |
Defaultvalue | 为属性提供一个默认的值。比如一个属性名称为美女:美女 CDATA "我的老婆"如果在该属性的实例中没有包含这个属性的话,解析器就认为该属性的值就是"我的老婆",如果在该属性的实例中包含了这个属性并赋值了的话,就采用这个赋值。 |
到现在为止,我们就可以定义任意元素的属性了。
举一个例子用来说明属性类型IDREF/IDREFS的使用,见下面的DTD范例:
<!ELEMENT FAMILY (PERSON+)>
<!ELEMENT PERSON EMPTY>
<ATTLIST PERSON
relID ID #REQUIRED
parentID IDREFS #IMPLIED
name CDATA #REQUIRED
>
注意到这里的parentID的类型为IDREFS,这个表明该属性的值必须在文档中出现过。如果该属性的值没在文档中出现过的话,该文档就属于不规范文档,解析器就不会认为该文档是有效的。
比如下面的文档就是一个不正确的文档。
<FAMILY>
<PERSON relID="P_1" name="Joe">
<PERSON relID="P_2" name="NiEr">
<PERSON relID="P_3" name="MoZi">
< PERSON relID="P_4" parentID="P_1 P_5" name="Violet">
</FAMILY>
原因是parentID中出现了值"P_5",而这个值在没有在文档中出现过。
举一个例子用来说明属性类型NMTOKENS的使用,见下面的DTD(ex02.dtd)范例:
<!ELEMENT PERSON (NAME,FAVOURITY)>
<!ELEMENT NAME (#PCDATA)>
<!ATTLIST NAME
USERID NMTOKENS #REQUIRED
>
<!ELEMENT FAVOURITY (#PCDATA)>
<!ATTLIST FAVOURITY
FAVOURDESC NMTOKENS #REQUIRED
>
下面的文档就是一个不正确的文档:
<?xml version="1.0" encoding="GB2312" standalone="no" ?>
<!DOCTYPE PERSON SYSTEM "ex02.dtd">
<PERSON>
<NAME USERID="JOBS22@#$_tt" />
<FAVOURITY FAVOURDESC="FOOTBALL" />
</PERSON>
因为在USERID这个属性值中包含了NMTOKENS所不允许的字符"@#$"。
下面来说明属性类型ENTITY/ENTITIES的使用
前面我们提到,实体可以分为四种类型:普通实体、外部实体、参数实体和外部参数实体。现在我们通过具体的例子来说明每一种实体的使用。