为什么使用 DTD
1,DTD 用来描述 XML 文档的结构。
2,通过 DTD,您的每一个 XML 文件均可携带一个有关其自身格式的描述。
3,通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据。
4,而您的应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据。
5,您还可以使用 DTD 来验证您自身的数据。
DTD文档组成
1,元素 ( ELEMENT ) 的定义规则。
2,元素之间的关系规则。
3,属性 ( ATTLIST ) 的定义规则。
4,可使用的实体 ( ENTITY ) 或符号 ( NOTATION ) 规则。
内部的 DOCTYPE 声明
假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:<!DOCTYPE 根元素 [DTD声明]>.dtd 文件中是不能使用 DOCTYPE 的带有 DTD 的 XML 文档实例:
-
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)><!--声明根元素note有4个子元素-->
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<!--这里所有定义的子元素都要被使用1次,使用顺序按照定义的顺序--><to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
!DOCTYPE note (第二行)定义此文档是 note 类型的文档,note是根元素的名称。!ELEMENT note (第三行)定义 note 元素有四个子元素:"to、from、heading、body" 。!ELEMENT to (第四行)定义 to 子 元素 的 数据类型 为 "#PCDATA" 。!ELEMENT from (第五行)定义 from 子 元素 的 数据类型 为 "#PCDATA" 。!ELEMENT heading (第六行)定义 heading 子 元素 的 数据类型 为 "#PCDATA" 。!ELEMENT body (第七行)定义 body 子 元素 的 数据类型 为 "#PCDATA" 。注意:例子中的定义关键字一定要大写,如DOCTYPE、ELEMENT、#PCDATA,且元素名称与数据类型之间也要有空格。
外部文档声明:
假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:<!DOCTYPE 根元素 SYSTEM "DTD文件路径">例:F:/dream/圣思园/Web.Service/note.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note SYSTEM "F:/dream/圣思园/Web.Service/note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
公用DTD:有一种外部DTD,是由某个权威机构制定,供特定行业或公司,这种DTD又被称为公用DTD<!DOCTYPE 根元素名 PUBLIC “DTD-NAME” “DTD-URL”>公用DTD与外部DTD区别在于:公用DTD使用PUBLIC代替了原来的SYSTEM,并增加了DTD标识名。
内外部DTD文档结合
<!DOCTYPE 根元素 SYSTEM "DTD文件路径" [DTD声明内容]>F:/dream/圣思园/Web.Service/note.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note SYSTEM "F:/dream/圣思园/Web.Service/note.dtd"[
<!ELEMENT note (to,from,heading,body,name)>
<!ELEMENT name (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
<name>z</name>
</note>
XML 文档构建模块
XML 以及 HTML 文档的主要构建模块是类似 <body>....</body> 这样的标签。所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:元素,属性,实体,PCDATA ,CDATA
下面是每个构建模块的简要描述。元素元素是 XML 以及 HTML 文档的主要构建模块。HTML 元素的例子是 "body" 和 "table"。XML 元素的例子是 "note" 和 "message" 。元素可包含文本、其他元素或者是空的。空的 HTML 元素的例子是 "hr"、"br" 以及 "img"。例:<body>body text in between</body><message>some message in between</message>
属性属性可提供有关元素的额外信息。属性总是被置于某元素的开始标签中。属性总是以名称/值的形式成对出现的。下面的 "img" 元素拥有关于源文件的额外信息:<img src="computer.gif" />元素的名称是 "img"。属性的名称是 "src"。属性的值是 "computer.gif"。由于元素本身为空,它被一个 " /" 关闭。
实体实体是用来定义普通文本的变量。实体引用是对实体的引用。大多数同学都了解这个 HTML 实体引用:" "。这个“无折行空格”实体在 HTML 中被用于在某个文档中插入一个额外的空格。当文档被 XML 解析器解析时,实体就会被展开。下面的实体在 XML 中被预定义:
实体引用 字符 < < > > & & " " ' '
PCDATA(用于元素) 的意思是被解析的字符数据(parsed character data)。可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。文本中的标签会被当作标记来处理,而实体会被展开。不过, 被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它们。CDATA(用于属性)CDATA 的意思是字符数据(character data)。CDATA 是不会被解析器解析的文本。在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。
DTD - 元素
在 DTD 中,XML 元素通过元素声明来进行声明。元素声明使用下面的语法:<!ELEMENT 元素名称 类别> 或者 <!ELEMENT 元素名称 (元素内容)>元素类别:
EMPTY-该元素不能包含子元素和文本,但可以有属性-(空元素)
ANY-该元素可以包含任何在DTD中定义的元素内容
#PCDATA-可以包含任何字符数据,但是不能在其中包含任何子元素
纯元素类型-只包含子元素,并且这些子元素外没有文本
混合类型-包含子元素和文本数据的混合
空元素空元素通过类别关键词EMPTY进行声明:<!ELEMENT 元素名称 EMPTY>例: <!ELEMENT br EMPTY>XML例子: <br />只有 PCDATA 的元素只有 PCDATA 的元素通过圆括号中的 #PCDATA 进行声明:<!ELEMENT 元素名称 (#PCDATA)>例: <!ELEMENT from (#PCDATA)>带有任何内容的元素通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合:<!ELEMENT 元素名称 ANY>例: <!ELEMENT note ANY>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ELEMENT note (to,from*)>
<!ELEMENT to ANY>
<!ELEMENT from (#PCDATA)>
]>
<note>
<to><from>X</from></to>
</note>
带有子元素(序列)的元素带有一个或多个子元素的元素通过圆括号中的子元素名进行声明:<!ELEMENT 元素名称 (子元素名称 1)>或者<!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)>例: <!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)>
声明只出现一次的元素<!ELEMENT 元素名称 (子元素名称)>例: <!ELEMENT note (message)>上面的例子声明了:message 子元素必须出现一次,并且必须只在 "note" 元素中出现一次。声明最少出现一次的元素<!ELEMENT 元素名称 (子元素名称+)>例: <!ELEMENT note (message+)>上面的例子中的加号声明了:message 子元素必须在 "note" 元素内出现至少一次。声明出现零次或多次的元素<!ELEMENT 元素名称 (子元素名称*)>例: <!ELEMENT note (message*)>上面的例子中的星号声明了:子元素 message 可在 "note" 元素内出现零次或多次。声明出现零次或一次的元素<!ELEMENT 元素名称 (子元素名称?)>例: <!ELEMENT note (message?)>上面的例子中的问号声明了:子元素 message 可在 "note" 元素内出现零次或一次。声明“非.../既...”类型的内容例: <!ELEMENT note (to,from,header,(message|body))>上面的例子声明了:"note" 元素必须包含 "to" 元素、"from" 元素、"header" 元素,以及非 "message" 元素既 "body" 元素。声明混合型的内容例: <!ELEMENT note (#PCDATA|to|from|header|message)*>上面的例子声明了:"note" 元素可包含出现零次或多次的 PCDATA、"to"、"from"、"header" 或者 "message"。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ELEMENT note (#PCDATA|to|from|header|message)*>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT header (#PCDATA)>
<!ELEMENT message (#PCDATA)>
]>
<note>
abc
<to>to</to>
<from>from</from>
def
</note>
符号
用途
示例
示例说明
( )
用来给元素分组
(古龙|金庸|梁羽生),(王朔|余杰),毛毛
分成三组
|
在列出的对象中选择一个
(男人|女人)
表示男人或者女人必须出现,两者选一
+
该对象最少出现一次,可以出现多次 (1或多次)
(成员+)
表示成员必须出现,而且可以出现多个成员
*
该对象允许出现零次到任意多次(0到多次)
(爱好*)
爱好可以出现零次到多次
?
该对象可以出现,但只能出现一次 (0到1次)
(菜鸟?)
菜鸟可以出现,也可以不出现,如果出现的话,最多只能出现一次
,
对象必须按指定的顺序出现
(西瓜,苹果,香蕉)
表示西瓜、苹果、香蕉必须出现,并且按这个顺序出现
DTD - 属性
在 DTD 中,属性通过 ATTLIST 声明来进行声明。属性声明使用下列语法:<!ATTLIST 元素名称 属性名称 属性类型 默认值>DTD 实例:<!ATTLIST payment type CDATA "check">XML 实例:<payment type="check" />以下是属性类型的选项:
类型 描述 CDATA 值为字符数据 (character data) (en1|en2|..) 此值是枚举列表中的一个值 ID 值为唯一的 id IDREF 值为另外一个元素的 id IDREFS 值为其他 id 的列表,以空格分隔 NMTOKEN 值为合法的 XML 名称,NMTOKEN是CDATA的一个子集,表示属性值必须是英文字母、数字、句号、破折号、下划线或冒号,属性值不能含有空格 NMTOKENS 值为合法的 XML 名称的列表,NMTOKENS与NMTOKEN类似,包含多个由空格分隔的字符 ENTITY 值是一个实体 ENTITIES 值是一个实体列表 属性的默认值
值 解释 值 属性的默认值 #REQUIRED 属性值是必需的 #IMPLIED 属性不是必需的 #FIXED value 属性值是固定的 规定一个默认的属性值例:DTD:<!ELEMENT square EMPTY><!ATTLIST square width CDATA "0">合法的 XML: <square width="100" />在上面的例子中,"square" 被定义为带有 CDATA 类型的 "width" 属性的空元素。如果宽度没有被设定,其默认值为0 。#IMPLIED语法: <!ATTLIST 元素名称 属性名称 属性类型 #IMPLIED>例:DTD: <!ATTLIST contact fax CDATA #IMPLIED>合法的 XML: <contact fax="555-667788" />合法的 XML: <contact />假如您不希望强制作者包含属性,并且您没有默认值选项的话,请使用关键词 #IMPLIED。#REQUIRED语法: <!ATTLIST 元素名称 属性名称 属性类型 #REQUIRED>例DTD: <!ATTLIST person number CDATA #REQUIRED>合法的 XML: <person number="5677" />非法的 XML: <person />假如您没有默认值选项,但是仍然希望强制作者提交属性的话,请使用关键词 #REQUIRED。#FIXED语法: <!ATTLIST 元素名称 属性名称 属性类型 #FIXED "value">例DTD: <!ATTLIST sender company CDATA #FIXED "Microsoft">合法的 XML: <sender company="Microsoft" />非法的 XML: <sender company="W3School" />如果您希望属性拥有固定的值,并不允许改变这个值,请使用 #FIXED 关键词。如果使用了不同的值,XML 解析器会返回错误。列举属性值语法: <!ATTLIST 元素名称 属性名称 (en1|en2|..) 默认值>DTD : <!ATTLIST payment type (check|cash) "cash">XML : <payment type="check" /> 或者 <payment type="cash" />如果您希望属性值为一系列固定的合法值之一,请使用列举属性值。定义ENTITY和ENTITIES类型的属性其属性值只能是未解析的实体,与外部数据相连。如图像文件,音像文件等。注意:一旦声明某个属性的类型是entity或entities,就意味着该属性值只能是一个或多个未解析的实体,而不是已经解析的实体。对于未解析的实体而言,不能通过普通实体引用方式去引用,他们只能作为entity或entities类型的属性值。
DTD - 实体
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。实体是包含了文档片段的虚拟存储单元,可用来存储XML声明、DTD、其他形式的文本及二进制数据等。简单来讲就是一段代码或数据的代称,这个代称即为实体 的名字。当需要在文档中引用某段代码或数据时,可以引用与段代码或数据相对应的实体名称来代替实体的具体内容。具有正确性检查功能的XML处理器在提交文档给最终应用程序之前或在显示文档以前,将先把所有不同的实体引用替换为与其对应的具体内容,从而构成一个结构完整的文档。
按照实体的具体内容来分类,实体可分为可解析与不可解析两类。可解析实体的具体内容为简单的字符、数字、文本块,而不可解析实体的具体内容则为图片、声音等二进制文件。按照逻辑存储来分类,实体可分为内部实体与外部实体两类。内部实体的内容是在文档内部设定的;而外部实体则是一个外部独立的物理存储对象,如某个外部文件。按照使用的范围来分类,实体可分为一般实体与参数实体两类。一般实体都用来构成文档的具体内容,可出现在XML文档中,也可出现在DTD中;而参数实体只能出现在DTD中,不能出现在XML文档中实体引用是对实体的引用。实体可在内部或外部进行声明。一个内部实体声明语法: <!ENTITY 实体名称 "实体的值">例: DTD:<!ENTITY writer "Bill Gates"><!ENTITY copyright "Copyright W3School.com.cn">XML: <author>&writer;©right;</author>注释: 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。一个外部实体声明语法: <!ENTITY 实体名称 SYSTEM "URI/URL">例子:DTD 例子:<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd"><!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">XML 例子:<author>&writer;©right;</author>
类型
普通实体
参数实体
使用场合
用在XML文档中
只用在DTD中元素和属性的声明中
声明方式
内部
<!ENTITY 实体名 "文本内容">
<!ENTITY % 实体名 "文本内容">
外部
<!ENTITY 实体名 SYSTEM"外部文件URL地址">
<!ENTITY % 实体名 SYSTEM "外部文件URL地址">
引用方式
&实体名;
%实体名;
参数实体F:\dream\圣思园\Web.Service\note.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % p "to">
<!ELEMENT %p; (#PCDATA)>
<!ATTLIST %p; addr CDATA #FIXED 'sp'>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note SYSTEM "F:\dream\圣思园\Web.Service\note.dtd"[
<!ELEMENT note (to) >
]>
<note>
<to addr = "sp">nn</to>
</note>
DTD - 符号
NOTATION 主要是用来表明文档中需要来自外部源的数据,而该数据XML本身是不能进行解析的,比如各种格式的二进制文件(比如图形文件、声音文件等),需要外部的应用程序进行处理。NOTATION 声明的语法格式如下:<!NOTATION NAME ExternalID>需要注意的是NAME必须由字母、数字、句点、破折号或冒号组成,并且第一个字符必须为字母或者是下划线。下面的例子表示GIF图象作为不解析的外部内容。
<?xml version="1.0" encoding="UTF-8"?>
<!NOTATION gif SYSTEM "iexplore.exe">
<!ENTITY logo SYSTEM "http://web/category/sg.gif" NDATA gif>
<!-- 这里NDATA表示XML不解析该数据 -->
<!ELEMENT PIC EMPTY>
<!ATTLIST PIC loc ENTITY #REQUIRED>
然后,在具体的实例化文档中包含下面一行代码:<PIC loc="&logo;" />根据DTD定义,loc属性值是一个不解析的实体。解析器可以根据DTD定义知道这一点,然后它就不对其进行解析,也不会象解析实体一样把它包括到XML文档里面。同时,XML解析器将通知iexplore.exe该引用的存在。