DTD元素属性介绍

一个DTD文档实际上就是元素定义的集合,而元素可能包含属性,也可能不包含属性,就象在C++的一个类中,我们可以有虚函数,也可以没有虚函数。属性可以通过以下的语法进行定义:

  <! 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的使用

  前面我们提到,实体可以分为四种类型:普通实体、外部实体、参数实体和外部参数实体。现在我们通过具体的例子来说明每一种实体的使用。
 
posted on 2007-12-27 21:05  C#家园  阅读(845)  评论(0编辑  收藏  举报