一、简介
DTD:文档类型定义(Document Type Definition),可定义合法的XML文档构建模块。
DTD使用一系列合法的元素来定义文档的结构
DTD可被成行的声明在XML文档中,也可以作为一个外部引用
根据DTD即可写出符合DTD定义的XML文档
为什么使用 DTD?
1、通过 DTD,您的每一个 XML 文件均可携带一个有关其自身格式的描述。
2、通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据。
3、应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据。
4、您还可以使用 DTD 来验证您自身的数据。
二、DTD声明
1、内部声明
**假如DTD被包含在XML源文件中,它应当通过下面的语法包装在
DOCTYPE
声明中**
<!DOCTYPE root-element [element-declarations]>
实例:
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>
以上DTD实例解释:
- !DOCTYPE note (第二行)定义此文档是 note 类型的文档。
- !ELEMENT note (第三行)定义 note 元素有四个元素:”to、from、heading,、body”
- 第四行,第五行,第六行,第七行分别定义 to,from,heading,body 元素为 “#PCDATA” 类型
2、外部声明
**假如DTD被包含在XML源文件外,它应当通过下面的语法包装在
DOCTYPE
声明中**
<!DOCTYPE root-element [element-declarations]>
实例:
xml文件
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
DTD:note.dtd文件
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
三、构建模块
所有XML以及HTML均有以下简单的模块构成
- 元素:是XML和HTML文档的主要构建模块
- 属性:提供有关属性的额外信息
- 实体:用于定义引用普通文本或特殊字符( 等)的快捷方式的变量。
- PCDATA:(parse character data)被解析的字符串。这些文本将被解析器检查实体以及标记。
- CDATA:(character data)字符数据,不会被解析的文本(其中若包含标签,实体也不会被解析)
元素和属性:
<img src="computer.gif" />
img是元素,src是属性
元素和属性使用建议:
- 数据可以在子元素或者属性中存储。
- 通常情况下推荐在子元素在中存储。
- 属性作为元素的唯一标识符,如id,name等,应在属性中存储
- 元数据(描述数据的数据)应该在属性中存储,而数据的本身作为存储元素,如
<messages><note name="description"><description>这是元数据</description></note></messages>
。
四、元素
1、元素的声明格式:
<!ELEMENT element-name category>
或者:
<!ELEMENT element-name (element-content)>
2、元素的类别:
(1). 空元素
通过关键字EMPTY声明:
<!ELEMENT element-name EMPTY>
实例:
<!ELEMENT br EMPTY>
XML example:
<br />
(2). 只有PCDATA的元素
通过圆括号中的PCDATA声明:
<!ELEMENT element-name (#PCDATA)>
实例:
<!ELEMENT from (#PCDATA)>
(3). 带有任何内容的元素
通过类别关键字ANY声明,可包含任何可解析数据的组合:
<!ELEMENT element-name ANY>
实例:
<!ELEMENT note ANY>
(4). 带有子元素(序列)的元素
带有一个或多个子元素的元素通过圆括号中的子元素名进行声明:
<!ELEMENT element-name (child1)>
或
<!ELEMENT element-name (child1,child2,...)>
实例:
<!ELEMENT note (to,from,heading,body)>
注意:当子元素按照由逗号分隔开的序列进行声明时,这些子元素必须按照相同的顺序出现在文档中。在一个完整的声明中,子元素也必须被声明,同时子元素也可拥有子元素。
完整note声明是:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
(5). 声明只出现一次的元素
<!ELEMENT element-name (child-name)>
实例:
<!ELEMENT note (message)>
声明了message 子元素必须出现一次,并且必须只在 "note" 元素中出现一次。
(6). 声明最少出现一次的元素
在子元素名后跟上”+“号:
<!ELEMENT element-name (child-name+)>
实例:
<!ELEMENT note (message+)>
(7). 声明出现0次或者1次的元素
在子元素名后跟上”*”号:
<!ELEMENT element-name (child-name*)>
实例:
<!ELEMENT note (message*)>
(8). 声明”非…既…”类型的内容
在元素之间使用”|“号:
<!ELEMENT element-name (child1,child2,(child3|child4),child5)>
实例:
<!ELEMENT note (to,from,header,(message|body))>
(9). 声明混合型内容
实例:
<!ELEMENT note (#PCDATA|to|from|header|message)*>
上面的例子声明了:”note” 元素可包含出现零次或多次的 PCDATA、”to”、”from”、”header” 或者 “message”。
五、属性
1、属性通过ATTLIST进行声明,语法
<!ATTLIST element-name attribute-name attribute-type attribute-value>
2、属性类型
类型 | 描述 |
---|---|
CDATA | 值为字符数据 (character data) |
(枚举列表:值用竖线隔开) | 此值是枚举列表中的一个值 |
ID | 值为唯一的 id |
IDREF | 值为另外一个元素的 id |
IDREFS | 值为其他 id 的列表 |
NMTOKEN | 值为合法的 XML 名称 |
NMTOKENS | 值为合法的 XML 名称的列表 |
ENTITY | 值是一个实体 |
ENTITIES | 值是一个实体列表 |
NOTATION | 此值是符号的名称 |
xml: | 值是一个预定义的 XML 值 |
3、默认属性值
值 | 解释 |
---|---|
#REQUIRED | 属性值是必需的 |
#IMPLIED | 属性不是必需的 |
#FIXED value | 属性值是固定的 |
4、列举属性值:
如果您希望属性值为一系列固定的合法值之一,请使用列举属性值。语法:
<!ATTLIST element-name attribute-name (en1|en2|..) default-value>
实例:
DTD:
<!ATTLIST payment type (check|cash) "cash">
XML 例子:
<payment type="check" />
或
<payment type="cash" />
六、实体
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
- 实体引用是对实体的引用。
- 实体可在内部或外部进行声明。
注意:一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。
1、内部实体声明
语法:
<!ENTITY entity-name "entity-value">
DTD实例:
<!ENTITY writer "Donald Duck.">
<!ENTITY copyright "Copyright W3CSchool.cc">
XML 实例:
<author>&writer;©right;</author>
2、外部实体声明
语法:
<!ENTITY entity-name SYSTEM "URI/URL">
DTD 实例:
<!ENTITY writer SYSTEM "http://www.w3cschool.cc/entities.dtd">
<!ENTITY copyright SYSTEM "http://www.w3cschool.cc/entities.dtd">
XML 实例:
<author>&writer;©right;</author>
七、DTD验证XML
**使用 Internet Explorer 可根据某个 DTD 来验证您的 XML。
1、通过XML解析器进行验证
当您试图打开某个 XML 文档时,XML 解析器有可能会产生错误。通过访问 parseError 对象,就可以取回引起错误的确切代码、文本甚至所在的行。
注意: load() 方法用于文件,而 loadXML() 方法用于字符串。
实例:
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);
2、关闭验证
通过把 XML 解析器的 validateOnParse 设置为 “false”,就可以关闭验证。
xmlDoc.validateOnParse="false";
3、通用的XML验证器
八、DTD实例演示
根据DTD即可写出对应的XML文档
1. 电视节目表 DTD
<!DOCTYPE TVSCHEDULE [
<!--根元素为:TVSCHEDULE-->
<!ELEMENT TVSCHEDULE (CHANNEL+)>
<!--TVSCHEDULE的子元素CHANNEL至少出现1次-->
<!ELEMENT CHANNEL (BANNER,DAY+)>
<!--CHANNEL的子元素BANNER出现1次,DAY至少出现1次-->
<!ELEMENT BANNER (#PCDATA)>
<!--BANNER元素为PCDATA类型-->
<!ELEMENT DAY (DATE,(HOLIDAY|PROGRAMSLOT+)+)>
<!--DAY元素的不是子元素HOLIDAY出现1次,就是PROGRAMSLOT出现至少1次-->
<!ELEMENT HOLIDAY (#PCDATA)>
<!--HOLIDAY元素为PCDATA类型-->
<!ELEMENT DATE (#PCDATA)>
<!--DATE元素为PCDATA类型-->
<!ELEMENT PROGRAMSLOT (TIME,TITLE,DESCRIPTION?)>
<!--PROGRAMSLOT的子元素TIME(1次),TITLE(1次),DESCRIPTION(可能出现)-->
<!ELEMENT TIME (#PCDATA)>
<!--TIME元素为PCDATA类型-->
<!ELEMENT TITLE (#PCDATA)>
<!--TITLE元素为PCDATA类型-->
<!ELEMENT DESCRIPTION (#PCDATA)>
<!--DESCRIPTION元素为PCDATA类型-->
<!ATTLIST TVSCHEDULE NAME CDATA #REQUIRED>
<!--TVSCHEDULE的属性name的值必填且为字符-->
<!ATTLIST CHANNEL CHAN CDATA #REQUIRED>
<!--CHANNEL的属性CHAN的值必填且为字符-->
<!ATTLIST PROGRAMSLOT VTR CDATA #IMPLIED>
<!--PROGRAMSLOT的属性VTR的值可填可不填,填的值为字符-->
<!ATTLIST TITLE RATING CDATA #IMPLIED>
<!--TITLE的属性RATING的值可填可不填,填的值为字符-->
<!ATTLIST TITLE LANGUAGE CDATA #IMPLIED>
<!--TITLE的属性LANGUAGE的值可填可不填,填的值为字符-->
]>
2. 报纸文章 DTD
<!DOCTYPE NEWSPAPER [
<!ELEMENT NEWSPAPER (ARTICLE+)>
<!ELEMENT ARTICLE (HEADLINE,BYLINE,LEAD,BODY,NOTES)>
<!ELEMENT HEADLINE (#PCDATA)>
<!ELEMENT BYLINE (#PCDATA)>
<!ELEMENT LEAD (#PCDATA)>
<!ELEMENT BODY (#PCDATA)>
<!ELEMENT NOTES (#PCDATA)>
<!ATTLIST ARTICLE AUTHOR CDATA #REQUIRED>
<!ATTLIST ARTICLE EDITOR CDATA #IMPLIED>
<!ATTLIST ARTICLE DATE CDATA #IMPLIED>
<!ATTLIST ARTICLE EDITION CDATA #IMPLIED>
<!ENTITY NEWSPAPER "Vervet Logic Times">
<!ENTITY PUBLISHER "Vervet Logic Press">
<!ENTITY COPYRIGHT "Copyright 1998 Vervet Logic Press">
]>
3. 产品目录 DTD
<!DOCTYPE CATALOG [
<!ENTITY AUTHOR "John Doe">
<!ENTITY COMPANY "JD Power Tools, Inc.">
<!ENTITY EMAIL "jd@jd-tools.com">
<!ELEMENT CATALOG (PRODUCT+)>
<!ELEMENT PRODUCT
(SPECIFICATIONS+,OPTIONS?,PRICE+,NOTES?)>
<!ATTLIST PRODUCT
NAME CDATA #IMPLIED
CATEGORY (HandTool|Table|Shop-Professional) "HandTool"
PARTNUM CDATA #IMPLIED
PLANT (Pittsburgh|Milwaukee|Chicago) "Chicago"
INVENTORY (InStock|Backordered|Discontinued) "InStock">
<!ELEMENT SPECIFICATIONS (#PCDATA)>
<!ATTLIST SPECIFICATIONS
WEIGHT CDATA #IMPLIED
POWER CDATA #IMPLIED>
<!ELEMENT OPTIONS (#PCDATA)>
<!ATTLIST OPTIONS
FINISH (Metal|Polished|Matte) "Matte"
ADAPTER (Included|Optional|NotApplicable) "Included"
CASE (HardShell|Soft|NotApplicable) "HardShell">
<!ELEMENT PRICE (#PCDATA)>
<!ATTLIST PRICE
MSRP CDATA #IMPLIED
WHOLESALE CDATA #IMPLIED
STREET CDATA #IMPLIED
SHIPPING CDATA #IMPLIED>
<!ELEMENT NOTES (#PCDATA)>
]>