XML教程
一些XML元素具有属性。属性包含应用程序使用的信息。属性仅在程序对元素进行读、写操作时,提供元素的额外信息(如ID号等),对于人类读、写元素来说是毫无意义的。在本章中学习各种属性类型和如何在DTD中声明属性。
本章内容如下:
* 什么是属性?
* 如何在DTD中声明属性
* 如何声明多个属性
* 如何指定属性的缺省值
* 属性类型
* 预定义属性
* 基于属性的棒球比赛统计数据的DTD
10.1 什么是属性?
在第3章曾经讨论过开始标记和空标记可包含由等号"="分割开的成对的属性名和属性值。例如:
<GREETING LANGUAGE= "English">
Hello XML!
<MOVIE SOURCE= "WavingHand.mov" />
</GREETING>
上述例子中,GREETING元素具有LANGUAGE属性,其属性值为ENGLISH。MOVIE元素具有SOURCE属性,其属性值为WavingHand.mov。GREETING元素内容为Hello XML!。书写内容的语言对内容本身来说是一个有用的信息,可是语言不是内容的一部分。
与此相似,MOVIE元素内容为保存在WavingHand.mov文件中的二进制数据。尽管文件名告诉我们到何处可找到元素内容,但它本身不是元素内容。再次强调,属性包含有关元素内容信息,而不是元素内容本身。
元素可具有多个属性,例如:
<RECTANGLE WIDTH= "30" HEIGHT= "45" />
<SCRIPT LANGUAGE= "javascript" ENCODING= "8859_1" >...</SCRIPT>
上例中,SCRIPT元素属性LANGUAGE的值为javascript,SCRIPT元素属性ENCODING的值为8859_1;RECTANGLE元素属性WIDTH的值为30;RECT元素属性HEIGHT的值为45。这些属性值均为字符串数据,不是数字型数据。
结束标记不能带属性,下例视为非法:
<SCRIPT>...</SCRIPT LANGUAGE= "javascript" ENCODING= "8859_1" >
10.2 在DTD中声明属性
与元素和实体相似,为保持文档的合法性,需要在文档的DTD中声明属性。<!ATTLIST>标记用于声明属性,其形式如下:
<!ATTLIST Element_name Attribute_name Type Default_value>
Element_name为拥有该属性的元素名。Attribute_name为属性名,Type为表10-1列出的10种有效属性类型的一种。最常用的属性类型为CDATA。最后,若未规定属性值,则属性值为Default_value。
例如,研究下列元素:
<GREETING LANGUAGE= "Spanish">
Hola!
</GREETING>
在DTD中,可按如下格式声明该元素:
<!ELEMENT GREETING (#PCDATA)>
<!ATTLIST GREETING LANGUAGE CDATA "English">
<!ELEMENT>标记简单地说明greeting元素包含可析字符数据,这里没什么新内容。<!ATTLIST>标记表明GREETING元素拥有LANGUAGE属性,其值为CDATA类型,本质上与元素内容的#PCDATA相同。若所看见的GREETING标记中没有LANGUAGE属性,则LANGUAGE属性值为缺省指定的English。
表10-1 属性类型
类 型
含 义
CDATA
字符数据不是标记的文本
Enumerated
可能取值的列表,可从中选出正确的值
ID
不能被文档中其他任何ID类型属性共享的数字,具有唯一性
IDREF
文档中元素的ID类型属性的值
IDREFS
由空格分开的若干个ID
ENTITY
在DTD中声明的实体名
ENTITIES
在DTD中声明的若干个实体的名字,彼此间由空格分开
NMTOKEN
XML名称
NOTATION
在DTD中声明的注释名
NMTOKENS
由空格分开的多个XML名称
在各自的标记中分别声明各自的属性列表。属性所属元素的名字包含在<!ATTLIST>标记中,如上例中的属性声明仅用于GREETING元素。如果其余元素也具有LANGUAGE属性,就需要各自独立的<!ATTLIST> 声明。
对大部分声明而言,属性声明在文档中出现的顺序并无严格要求,可位于与其相连的元素声明之前或之后。实际上,甚至可以对同一属性进行多次声明。这时,第一个声明首先执行。
尽管非同寻常,甚至可以为并不存在的标记声明属性。在最初编辑DTD时,可以声明一些并不存在的属性,计划在以后再返回这里继续这些工作,为这些属性声明元素。
10.3 声明多个属性
元素通常具有多个属性。HTML的IMG元素可有HEIGHT、WIDTH、ALT、BORDER、ALIGN和其他几个属性 。实际上,大部分HTML标记都具有多个属性,XML标记也是如此。例如,很自然的RECTANGLE元素需要LENGTH和WIDTH属性:
<RECTANGLE LENGTH= "70px" WIDTH="85px"/>
也可用几个属性声明来声明这些属性,一个属性声明对应一个属性。例如:
<!ELEMENT RECTANGLE EMPTY>
<!ATTLIST RECTANGLE LENGTH CDATA "0px">
<!ATTLIST RECTANGLE WIDTH CDATA "0px">
上例说明,RECTANGLE元素具有LENGTH和WIDTH属性,它们的缺省值均为0px。
可按如下方式,组合两个<!ATTLIST>标记为一个单一声明:
<!ATTLIST RECTANGLE LENGTH CDATA "0px"
WIDTH CDATA "0px">
该声明声明了LENGTH和WIDTH属性,两个属性类型均为CDATA,缺省值为0px。若各属性的类型或缺省值不同,也可用这种语法结构进行声明。如下所示:
<!ATTLIST RECTANGLE LENGTH CDATA "15px"
WIDTH CDATA "34pt">
从个人角度来说,我不喜欢这种风格。看起来很混乱;且为易于辨认,过于依赖于额外的空格在其中的正确放置(尽管这些空格对标签的实际意义而言并不重要)。可是你一定会遇到其他人书写的、这种风格的DTD,所以必须掌握这种 书写方法。
10.4 指定属性的缺省值
若不采用明确指定一个缺省属性值(如0px)的方式,属性声明可以要求作者提供属性值,或者完全忽略该属性值,甚至总是使用缺省值。这三种类型分别由三个关键词#REQUIRED、#IMPLIED、#FIXED加以指定。
10.4.1 #REQUIRED
有时要选一个恰当的缺省属性值并不容易。例如,在为创建一个用于内部网的DTD时,可能要求所有的文档都至少有一个空的<AUTHOR1>标记;这些标记通常情况下并不显示,但可用来识别创建文档的作者。标记中拥有NAME、EMAIL和EXTENSION属性,以便与作者联系。例如:
<AUTHOR NAME="Elliotte Rusty Harold"
EMAIL= elharometalab.unc.edu EXTENSION= "3459"/>
假设要强制要求在内部网上张贴文档人的表明身份,就不采取为这些属性提供缺省值的方法。然而XML无法阻止任何人把作者身份定为"Luke Skywalker"(洛克天行者),但至少可通过使用#REQUIRED的缺省值方式,要求指定作者身份为某个人。例如:
<!ELEMENT AUTHOR EMPTY>
<!ATTLIST AUTHOR NAME CDATA #REQUIRED>
<!ATTLIST AUTHOR EMAIL CDATA #REQUIRED>
<!ATTLIST AUTHOR EXTENSION CDATA #REQUIRED>
如果语法分析器遇到一个<AUTHOR/>标记,该标记没有包含这些属性中的一个或几个时,将返回一个错误。
也可使用#REQUIRED强迫作者提交IMG元素的WIDTH、HEIGHT和ALT属性。例如:
<!ELEMENT IMG EMPTY>
<!ATTLIST IMG ALT CDATA #REQUIRED>
<!ATTLIST IMG WIDTH CDATA #REQUIRED>
<!ATTLIST IMG HEIGHT CDATA #REQUIRED>
任何试图忽略这些属性的行为(这样的Web页面太多了)都将产生一个不合法文档。XML处理器将注意到这种错误,并且将通知缺少这些属性的作者。
10.4.2 #IMPLIED
有时可能找到一个好的属性缺省值,但也不想要求文档作者包含这属性值。例如,假设在内部网上张贴文档的一些人拥有电子邮件地址,但它们没有电话分机号;为此,不想要求它们在<AUTHOR/>标记中包含EXTENSION(分机号)属性部分。例如:
<AUTHOR NAME="Elliotte Rusty Harold"
EMAIL="elharometalab.unc.edu "/>
如果依然不想为EXTENSION(分机号)提供缺省属性值,但是想提供作者引入这种类似属性的能力。在这种情况下,就可使用#IMPLIED的缺省值。如下所示:
<!ELEMENT AUTHOR EMPTY>
<!ATTLIST AUTHOR NAME CDATA #REQUIRED>
<!ATTLIST AUTHOR EMAIL CDATA #REQUIRED>
<!ATTLIST AUTHOR EXTENSION CDATA #IMPLIED>
如果XML处理器遇到没有EXTENSION属性的<AUTHOR/>标记,就不向XML应用程序提供有用的属性值。应用程序按收到的通知进行相应的选择。例如,应用程序把元素送入SQL数据库中,属性映射为字段,应用程序或许在数据库相应字段中插入空的数据。
10.4.3 #FIXED
最后,可能想提供一个不允许作者更改的属性缺省值。例如,希望为在内部网上张贴文档的人员的AUTHOR元素指定一个同等的COMPANY标识属性。方法如下:
<AUTHOR NAME= "Elliotte Rusty Harold" COMPANY="TIC"
EMAIL= "elharometalab.unc.edu" EXTENSION="3459"/>
可通过指定缺省值为#FIXED,其后跟随实际的缺省值,来要求所有的人员对COMPANY属性使用该缺省值。例如:
<!ELEMENT AUTHOR EMPTY>
<!ATTLIST AUTHOR NAME CDATA #REQUIRED>
<!ATTLIST AUTHOR EMAIL CDATA #REQUIRED>
<!ATTLIST AUTHOR EXTENSION CDATA #IMPLIED>
<!ATTLIST AUTHOR COMPANY CDATA #FIXED "TIC">
文档作者不需要在它们各自的标记中真正地引用固定的属性。如果它们没有包括固定属性,则使用缺省值;如果包括了固定的属性,无论如何它们使用的属性值必须一致,否则语法分析器将返回一个错误信号。
10.5 属性类型
前面的所有例子都具有CDATA类型的属性。CDATA是最通用的类型,但此外还允许使用其他九种属性类型。所有十种类型如下:
* CDATA
* Enumerated(枚举)
* NMTOKEN
* NMTOKENS
* ID
* IDREF
* IDREFS
* ENTITY
* ENTITIES
* NOTATION
上述属性类型中的九种在类型字段中的值为常数,而Enumerated是一种特殊的类型,表示属性值必须为一可能取值列表中的一个。下面分别对各类型进行深入的研究。
10.5.1 CDATA属性类型
最通用的属性类型CDATA,表明属性值为不包括小于号(<)和引号(")的任意文本字符串。可通过普通的实体引用(<;和";)的方式或由字符引用Unicode值的方式插入小于号和引号字符。原始的和号(&)