[原]用DTD规范XML文档

    DTD全称为Document Type Definition,即文档类型定义。DTD是一套关于标记符的语法规则,它是XML 1.0版规范的一部分,也是XML文档的一个组成部分,它为XML文档提供了验证机制。DTD是一种保证XML文档格式正确的有效方法,可以通过比较XML文档和DTD文件来检查文档是否符合规范,以及元素和属性的使用方法是否正确。
    XML文档为应用程序提供了一种数据交换的格式,DTD则让XML文档能够成为数据交换的标准。只需定义好标准的DTD,不同用户都按照DTD来创建XML文档并进行验证,这样就可以轻松地建立标准并进行数据交换,以实现数据共享。

一、内部DTD与外部DTD
若要通过DTD对XML文档格式进行验证,就需要在XML文档中引入DTD。既可以直接在XML文档中定义DTD(内部DTD),也可以通过URI引用外部DTD文件,两者可以同时使用。
使用内部DTD的优点是,DTD声明与XML文档正文包含在同一个文件中,在阅读时可以相互对照,比较直观,而且便于修改。外部DTD可适用于,使用相同的DTD对多个XML文档进行检查,可以把DTD声明存储在一个单独的文件中,然后在XML文档中引入。
1、内部DTD
使用内部DTD时,应将DTD声明放在XML文档声明之后、根元素的开始标记之前:

<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE rootelement [
元素声明、属性声明和实体声明
]>
XML文档正文部分

其中,“<!DOCTYPE”表示DTD声明开始,关键字DOCTYPE必须大写。rootelement表示根元素的名称。DTD声明序列用来对XML文档中使用的元素、属性和实体进行声明。

2、外部DTD
把DTD定义写到一个独立的文本文件中,其文件扩展名为.dtd,文件中还可以加入使用注释。
根据性质不同,外部DTD可以分为:

引用
a、私有DTD:指未公开的DTD文件,通常属于某个组织或个人所有;
b、公共DTD:指由某一应用领域或行业制定的,被国际上的标准组织等认可的、公开的、标准的DTD文件。

若要在一个XML文档中引入外部DTD,需要把standalone属性更改为no,然后在文档序言区域添加引用。
对于私有DTD文件,格式为:

<!DOCTYPE rootelement SYSTEM "URI">

对于公共DTD文件,格式为:

<!DOCTYPE rootelement PUBLIC "DTD_name" "URI">

其中,各关键字必须大写。DTD_name表示公共DTD文件的逻辑名称。公共DTD文件都有一个逻辑名称,也称为公共标识符。具体使用,可参考:[转]使用正确的DOCTYPE 声明

二、DTD元素声明
在XML文档中,一个元素的内容可以是各种各样的,既可以为空,也可以包含字符数据等。通过在DTD中对该文档使用的每个元素进行声明,以定义元素的名称、元素内容的数据类型、允许元素包含的子元素及其出现顺序等规范XML文档。
DTD对元素进行声明决定了整个XML文档的逻辑结构。语法格式:

<!ELEMENT element_name element_definition>

其中,“<!ELEMENT ”表示元素声明的开始,关键字ELEMENT必须大写。element_name表示要声明的元素名称。element_definition表示对该元素内容的定义,用来规定该元素可以包含哪些内容。在元素名称与内容定义之间必须包含空格。
一个XML元素可以不包含任何内容,也可以包含字符数据或子元素,也可以包含字符数据和子元素,还可以包含任何形式的内容。
1、声明空元素
若一个元素既不包含字符数据,也不包含子元素,就是空元素。声明为:

<!ELEMENT 元素名称 EMPTY>

2、声明元素包含字符数据
若一个元素仅包含字符数据,而不包含任何子元素,可声明为:

<!ELEMENT 元素名称 (#PCDATA)>

3、声明元素包含子元素
一个元素可以包含若干个子元素,这些子元素可以按照指定顺序依次出现,或者多个子元素只能出现其中的一个。
若在一个元素中系列子元素只能按指定顺序出现,可声明为:

<!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,…..)>

若在一个元素中系列子元素只能出现其中之一,可声明为:

<!ELEMENT 元素名称 (子元素名称 1|子元素名称 2|…..)>

以上介绍了顺序子元素和互斥子元素。默认情况下,这些子元素在其父元素中都只能出现一次。若要指定一个子元素在其父元素中出现的次数,则可以通过在子元素名称之后附件以下元组运算符来实现。

引用
加号(+):指定子元素可以出现一次或多次;
星号(*):指定子元素可以出现零次或多次;
问号(?):指定子元素可以出现零次或一次。

例如:

<!ELEMENT student (studentno,name,email*,mobilephone?,interest+)>

除了使用元组运算符指定子元素出现的次数外,还可以使用圆括号把若干个子元素括起来,把它们作为一个元素组来处理。在该元素组中可以包含若干个顺序子元素,也可以包含若干个互斥子元素。对于元素组,可以使用元组运算符来控制其出现的次数。
例如:

<!ELEMENT customer (name,homeaddress?,(phone|mobilephone))>

4、声明元素包含字符数据和子元素
若一个元素中可以包含字符数据以及零个或多个子元素,可以声明为:

<!ELEMENT 元素名称 (#PCDATA|子元素名称 1|子元素名称 2|…)*>

声明包含混合内容的元素时,应注意以下几点:

引用
a、#PCDATA关键字必须是圆括号中的第一项;
b、在圆括号中可以使用短竖线,但不能使用逗号、问号或加号;
c、在圆括号中虽然使用了短竖线,但并不表明各个并列项之间存在互斥关系;
d、在圆括号后面必须添加星号,即混合内容必须声明为零个或多个。

5、声明元素包含任意内容
若一个元素可以包含任意内容,可声明为:

<!ELEMENT 元素名称 ANY>

ANY关键字表示该元素可以包含字符数据,也可以包含子元素。
若把一个元素声明为ANY类型,则对该元素几乎没有任何约束;这不符合DTD的设计目标。因此,在实际应用中,应尽量避免声明ANY元素。

三、DTD属性声明
若要创建有效的XML文档,不仅要在DTD中对该文档中的所有元素进行声明外,还要在DTD中对元素的所有属性进行声明,以设置元素所拥有的每个属性的名称、数据类型、是必选或可选等。
在有效的XML文档中,应将在DTD中声明的属性名称和属性值包含在元素的开始标记中。
声明元素属性的语法格式如下:

<!ATTLIST 元素名称 属性名称 属性类型 声明值>

若要声明多个属性,可以把这些属性放在不同行上,也可以放在同一行上并用空格分隔。

在XML规范中,允许为元素属性指定一下类型:

引用
CDATA:值为字符数据 (character data)
Enumerated:此值是枚举列表中的一个值,各个值之间用短竖线分隔,(en1|en2|..)
ID: 值为唯一的 id
IDREF: 值为另外一个元素的 id
IDREFS: 值为其他 id 的列表
NMTOKEN: 值为合法的 XML 名称
NMTOKENS: 值为合法的 XML 名称的列表
ENTITY: 值是一个实体
ENTITIES: 值是一个实体列表
NOTATION: 此值是符号的名称
xml: 值是一个预定义的 XML 值

声明值是可选的,有以下4种情况:

引用
值: 属性的默认值
#REQUIRED:属性值是必需的
#IMPLIED: 属性不是必需的
#FIXED value: 属性值是固定的

四、DTD实体声明
在DTD中,可以把XML声明、XML元素、DTD或其他类型的数据事先定义为一个实体的单元,然后在DTD内部或XML文档中通过实体的名称来引用实体的具体内容。这样可以实现一次编写重复使用的目的,每当在实体声明中修改实体内容时,所有引用该实体的DTD或XML文档就会自动更新。
1、内部实体
在XML文档中声明的实体称为内部实体,它只能在该文档内部引用。语法是:

<!ENTITY 实体名称 "实体的值">

在文档中引用内部实体的语法是:

&实体名称;

※ 注意,除了在XML文档中引用实体外,也可以再DTD中声明实体时引用已经声明的其他实体,但不能在元素和属性声明中引用实体。

2、外部实体
外部实体存储在一个独立的外部文件中,可以在多个XML文档中引用。语法为:

<!ENTITY 实体名称 SYSTEM "URI/URL">

引用外部实体的语法格式与引用内部实体时相同。但引用外部实体时,要记住把XML文档声明中的standalone属性设置为“no”。

3、内部参数实体
内部参数实体是指在独立的DTD文件内部定义的实体,并且该实体只能在这个DTD文档内部引用,而不能在XML文档中引用。语法是:

<!ENTITY % name "content">

百分号(%)表示这是一个参数实体;name表示要声明的实体名称,contenet表示该实体的具体内容。
在DTD中引用内部参数实体的语法格式为:

%name;

4、外部参数实体
还可以引用在其他独立DTD文件中声明的实体,语法是:

<!ENTITY % name SYSTEM "URI">

在DTD中引用外部参数实体与引用内部参数实体的语法相同。

四、通过 XML 解析器进行验证
当您试图打开某个 XML 文档时,XML 解析器有可能会产生错误。通过访问 parseError 对象,就可以取回引起错误的确切代码、文本甚至所在的行。

var xmlDoc = new ActiveXObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.validateOnParse="true"
xmlDoc.load("note_dtd_error.xml")

document.write("<br>Error Code: ")
document.write(xmlDoc.parseError.errorCode)
document.write("<br>Error Reason: ")
document.write(xmlDoc.parseError.reason)
document.write("<br>Error Line: ")
document.write(xmlDoc.parseError.line)

注释:load( ) 方法用于文件,而 loadXML( ) 方法用于字符串。通过把 XML 解析器的 validateOnParse 设置为 "false",就可以关闭验证。

五、参考文档
DTD 教程
解码 XML 和 DTD

用XSLT转换XML
[转]XML Schema 与 XML DTD的技术比较与分析
用Schema规范XML文档
XML文档规则

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/105105.html

(0)
上一篇 2021年8月25日
下一篇 2021年8月25日

相关推荐

发表回复

登录后才能评论