Chapter 3. DTD
Table of Contents
3.1. 文档类型声明
3.2. 元素声明
3.3. 属性声明
3.3.1. 属性类型
3.3.2. 属性缺省值
3.4. 实体
由于XML可自定义标签,所以每个人定义的标签集都会不同,如果没有一套标准来规定标签的定义原则,则应用程序就不能对XML文档进行处理。解决该问题的方案采用DTD,DTD(Document Type Definition,文档类型定义),用于定义XML文档的编写规则。如哪些元素可出现在文档中,及元素的内容和属性的要求等。应用程序会利用这个DTD对文档进行检验,符合DTD约束规则的XML文档称之为有效文档,可以进行下一步处理,否则会报错,应用程序可捕获该错误进行相应的异常处理。检验过程是可选,这要视具体应用而定。
3.1. 文档类型声明
要使用DTD进行有效性检验,就要使用文档类型定义声明指定DTD。如:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE portal SYSTEM "http://www.w3c.com/dtd/portal.dtd">
<portal>
<name>Jims</name>
<email>Jims@163.com</email>
<email>Jims@21cn.com</email>
</portal>
文档类型声明位于XML声明之后,根元素之前。如果dtd文档位于本机,可用路径名直接指出dtd文档的位置。portal.dtd的内容如下:
<!ELEMENT portal (name,email*)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT email (#PCDATA)>
上面的内容也可直接写到XML文档内,这种dtd声明方式叫内部dtd子集,如:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE portal [
<!ELEMENT portal (name,email*)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT email (#PCDATA)>
]>
<portal>
<name>Jims</name>
<email>Jims@163.com</email>
<email>Jims@21cn.com</email>
</portal>
如果dtd位于XML文档外,则叫外部dtd子集。我们可以结合内外dtd,共同组成一个dtd来为XML文档作验证。如:
<!DOCTYPE portal SYSTEM "external.dtd" [
<!ELEMENT portal (name,email*)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT email (#PCDATA)>
]>
注意,使用内外dtd时,这两个dtd要互相兼容,不能有冲突。
3.2. 元素声明
上节文档类型声明中的每一项都是元素声明,定义了每个元素的约束。元素声明的格式为:
<!ELEMENT element_name (content_model)>
有效文档中使用的每个元素都必须在文档的DTD中用元素声明进行声明。element_name可是任何合法的XML名称,content_model(内容模型)指定元素可以或必须包含的子元素以及子元素的顺序。下面具体介绍内容模型的内容。
#PCDATA,规定元素只包含已析的字符数据。下面声明指出一个name元素可以包含文本,但不能划分为独立的area_code、number和extension元素:
<!ELEMENT name (#PCDATA)>
子元素,可指明元素的子元素。下面声明表示name元素必须包含且只包含一个desc元素。
<!ELEMENT name (desc)>
也可用逗号为分隔符,指明多个子元素。并且子元素出现的次序必须按定义时的顺序。如:
<!ELEMENT name (id,desc)>
name元素的id子元素必须在desc子元素前面,否则验证会出错,该文档不是一个有效的XML文档。
下面这个文档是有效的
<name>
<id>1</id>
<desc>dtd test</desc>
</name>
下面这个文档是无效的,顺序颠倒了
<name>
<desc>dtd test</desc>
<id>1</id>
</name>
下面的文档也是无效的,有多余的元素
<name>
<id>1</id>
<desc>dtd test</desc>
<date>2005/01/31</date>
</name>
子元素的个数,我们可通过正则表达式来规定子元素的个数。
?,允许零个或一个该元素
*,允许零个或多个该元素
+,允许一个或多个该元素
下面我们可利用这些符号规定id子元素必须出现,且只能出现一次,而desc子元素可选。
<!ELEMENT name (id,desc*)>
根据上面的声明,下面的name元素都是有效的。
<name>
<id>1</id>
<desc>dtd test</desc>
</name>
<name>
<id>2</id>
</name>
<name>
<id>3</id>
<desc>dtd test</desc>
<desc>another test</desc>
</name>
可选项(
),选项是一个参数列表,每个参数间用“
”分隔,代表能且只能选一个子元素。
<!ELEMENT choice (good
bad)>
上例的choice元素可选一个good子元素,或bad子元素,且只能从选一个。可选的参数列可以多项,不限于两项。如:
<!ELEMENT choice (one
two
three
four)>
小括号,可用小括号把选项括起来,以表达更丰富的意思,如我们想表示choice元素必须包含一个good子元素,并且必须包含ok子元素或bad子元素的一个。
<!ELEMENT choice (good,(ok
bad))>
混合内容,在一些文档中,一个元素可能既包含子元素,也包含字符串,这些内容叫混合内容。可用以下方式表示:
<!EMEMENT description (#PCDATA
term)* )>
该声明表示description元素可包含已析的字符串和term子元素,且允许出现零次或多次,如:
<description>
this is a <term>dtd</term> test.
</description>
#PCDATA必须在第一位,可选的子元素可任意多项。
空元素,某些元素不用包含任何内容,称之为空元素。写成以/>结束的独立标签。
<!ELEMENT image EMPTY>
示例:
<image src="http://www.xml.com/dtd.jpg" />
ANY,允许元素内包含任意内容。该选项在dtd测试时很有用,在生产系统中尽量不要使用。
<!ELEMENT page ANY>
3.3. 属性声明
一个有效的XML文档,必须对元素的属性进行声明。使用ATTLIST声明来完成,一个ATTLIST可以为一个元素类型声明多个属性。
<!ATTLIST image src CDATA #REQUIRED>
上例声明image元素必须有一个src属性,该属性的值是字符数据。可用ATTLIST声明为一个元素声明多个属性,如:
<!ATTLIST image src CDATA #REQUIRED
width CDATA #REQUIRED
height CDATA #REQUIRED
alt CDATA #IMPLIED
>
上述声明指出src、width、height属性是必须的,alt属性是可选的。