探索 DTD 在 XML 中的作用及解析:深入理解文档类型定义
DTD 是文档类型定义(Document Type Definition)的缩写。DTD 定义了 XML 文档的结构以及合法的元素和属性。
为什么使用 DTD
通过使用 DTD,独立的团体可以就数据交换的标准 DTD 达成一致。
应用程序可以使用 DTD 来验证 XML 数据的有效性。
内部 DTD 声明
如果 DTD 在 XML 文件内声明,它必须包裹在 <DOCTYPE>
定义内:
带有内部 DTD 的 XML 文档
<?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>
在 XML 文件中,选择"view source" 以查看 DTD。
上述 DTD 的解释如下:
<!DOCTYPE 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"
外部 DTD 声明
如果 DTD 在外部文件中声明,<!DOCTYPE>
定义必须包含对 DTD 文件的引用:
带有对外部 DTD 引用的 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)>
DTD - XML 构建模块
XML 和 HTML 文档的主要构建模块是元素
XML 文档的构建模块
从 DTD 的角度来看,所有 XML 文档都由以下构建模块组成:
- 元素
- 属性
- 实体
- PCDATA
- CDATA
元素
元素是 XML 和 HTML 文档的主要构建模块。
HTML 元素的示例包括 "body" 和 "table"。XML 元素的示例可能是 "note" 和 "message"。元素可以包含文本、其他元素或为空。空的 HTML 元素的示例包括 "hr"、 "br" 和 "img"。
示例
<body>some text</body>
<message>some text</message>
属性
属性提供有关元素的额外信息。
属性始终位于元素的开始标记内。属性始终以名称/值对的形式出现。以下是具有有关源文件的附加信息的 "img" 元素的示例
<img src="computer.gif" />
实体
一些字符在 XML 中具有特殊含义,例如小于号(<),它定义了 XML 标记的开始。
大多数人都知道 HTML 实体: "
"。这个 "no-breaking-space" 实体用于在 HTML 文档中插入额外的空格。实体在 XML 解析器解析文档时会被展开。
以下实体在 XML 中是预定义的:
<
代表<
>
代表>
&
代表&
"
代表"
'
代表'
PCDATA
PCDATA 表示解析的字符数据。
将字符数据视为 XML 元素的开始标记和结束标记之间找到的文本。
PCDATA 是解析器将解析的文本。解析器将检查文本中的实体和标记。
文本内的标记将被视为标记,并且实体将被展开。
但是,解析的字符数据不应包含任何&、<或>字符;这些需要用分别表示为 &
<
和 >
实体。
CDATA
CDATA 表示字符数据。
CDATA 是解析器将不解析的文本。文本内的标记将不被视为标记,并且实体将不被展开。
DTD - 元素
在 DTD 中,元素通过 ELEMENT 声明进行声明
声明元素
在 DTD 中,XML 元素的声明具有以下语法:
<!ELEMENT element-name category>
或者
<!ELEMENT element-name (element-content)>
空元素
空元素通过 category 关键字 EMPTY
进行声明:
<!ELEMENT element-name EMPTY>
示例
<!ELEMENT br EMPTY>
XML 示例
<br />
具有解析字符数据的元素
仅包含解析字符数据的元素在括号内使用 #PCDATA
进行声明:
<!ELEMENT element-name (#PCDATA)>
示例
<!ELEMENT from (#PCDATA)>
具有任何内容的元素
使用 category 关键字 ANY
声明的元素可以包含任意可解析的数据组合:
<!ELEMENT element-name ANY>
示例
<!ELEMENT note ANY>
具有子元素(序列)的元素
具有一个或多个子元素的元素通过在括号内声明子元素的名称进行声明:
<!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)>
声明元素的仅出现一次
<!ELEMENT element-name (child-name)>
示例
<!ELEMENT note (message)>
上面的示例声明了子元素 "message" 必须在 "note" 元素内出现一次,且仅一次。
声明元素至少出现一次
<!ELEMENT element-name (child-name+)>
示例
<!ELEMENT note (message+)>
上面示例中的+号表示子元素 "message" 必须在 "note" 元素内出现一次或多次。
声明元素出现零次或更多次
<!ELEMENT element-name (child-name*)>
示例
<!ELEMENT note (message*)>
上面示例中的*号表示子元素 "message" 可以在 "note" 元素内出现零次或更多次。
声明元素出现零次或一次
<!ELEMENT element-name (child-name?)>
示例
<!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" 元素可以包含零个或多个解析字符数据、"to"、"from"、"header" 或 "message" 元素的出现。
DTD - 属性
在 DTD 中,使用 ATTLIST 声明来声明属性
声明属性
属性声明具有以下语法:
<!ATTLIST element-name attribute-name attribute-type attribute-value>
DTD 示例
<!ATTLIST payment type CDATA "check">
XML 示例
<payment type="check" />
attribute-type
可以是以下之一:
CDATA
:值是字符数据(en1|en2|..)
:值必须是列举列表中的一个ID
:值是唯一标识符IDREF
:值是另一个元素的标识符IDREFS
:值是其他标识符的列表NMTOKEN
:值是有效的 XML 名称NMTOKENS
:值是有效的 XML 名称的列表ENTITY
:值是实体ENTITIES
:值是实体的列表NOTATION
:值是符号的名称xml:
:值是预定义的 xml 值
attribute-value
可以是以下之一:
value
:属性的默认值#REQUIRED
:属性是必需的#IMPLIED
:属性是可选的#FIXED value
:属性值是固定的
默认属性值
<!ELEMENT square EMPTY>
<!ATTLIST square width CDATA "0">
有效的 XML
<square width="100" />
在上面的示例中,“square”元素被定义为一个带有类型 CDATA 的空元素。如果未指定宽度,则其默认值为 0。
REQUIRED
语法
<!ATTLIST element-name attribute-name attribute-type #REQUIRED>
示例
<!ATTLIST person number CDATA #REQUIRED>
有效的 XML
<person number="5677" />
无效的 XML
<person />
如果没有默认值的选项,但仍希望强制属性存在,请使用 #REQUIRED
关键字。
IMPLIED
语法:
<!ATTLIST element-name attribute-name attribute-type #IMPLIED>
示例
<!ATTLIST contact fax CDATA #IMPLIED>
有效的 XML:
<contact fax="555-667788" />
有效的 XML:
<contact />
如果不想强制作者包含属性,并且没有默认值的选项,请使用 #IMPLIED
关键字。
FIXED
语法:
<!ATTLIST element-name attribute-name attribute-type #FIXED "value">
示例
<!ATTLIST sender company CDATA #FIXED "Microsoft">
有效的 XML:
<sender company="Microsoft" />
无效的 XML:
<sender company="W3Schools" />
当希望属性具有固定值而不允许作者更改时,请使用 #FIXED
关键字。如果作者包含其他值,XML 解析器将返回错误。
列举属性值
语法
<!ATTLIST element-name attribute-name (en1|en2|..) default-value>
示例
<!ATTLIST payment type (check|cash) "cash">
XML 示例
<payment type="check" />
或
<payment type="cash" />
当希望属性值是固定一组合法值之一时,请使用列举属性值。
XML 元素与属性
在 XML 中,没有规定何时使用属性,何时使用子元素。
元素与属性的使用
数据可以存储在子元素中,也可以存储在属性中。
请看以下示例
<person sex="female">
<firstname>Anna</firstname>
<lastname>Smith</lastname>
</person>
<person>
<sex>female</sex>
<firstname>Anna</firstname>
<lastname>Smith</lastname>
</person>
在第一个示例中,sex
是一个属性。在最后一个示例中,sex
是一个子元素。这两个示例提供了相同的信息。
在何时使用属性以及何时使用子元素方面,没有具体的规则。根据我的经验,在 HTML 中使用属性很方便,但在 XML 中应该尽量避免使用。如果信息看起来像是数据,请使用子元素
以下三个 XML 文档包含完全相同的信息:
- 使用了一个
date
属性:
<note date="12/11/2002">
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
- 使用了一个
date
元素:
<note>
<date>12/11/2002</date>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
- 使用了扩展的
date
元素(这是我喜欢的):
<note>
<date>
<day>12</day>
<month>11</month>
<year>2002</year>
</date>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
避免使用属性?
是否应该避免使用属性?
一些使用属性的问题包括:
- 属性不能包含多个值(子元素可以)
- 属性不容易扩展(用于未来更改)
- 属性不能描述结构(子元素可以)
- 属性更难以通过程序代码进行操作
- 属性值不容易与 DTD 进行测试
如果将属性用作数据的容器,最终会得到难以阅读和维护的文档。尽量使用元素来描述数据。仅在提供与数据无关的信息时使用属性。
不要像这样使用 XML(这不是 XML 的正确用法)
<note day="12" month="11" year="2002"
to="Tove" from="Jani" heading="Reminder"
body="Don't forget me this weekend!">
</note>
关于属性规则有一个例外:
有时会为元素分配 ID 引用。这些 ID 引用可以用于访问 XML 元素,方式类似于 HTML 中的 NAME 或 ID 属性。这个例子演示了这一点:
<messages>
<note id="p501">
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
<note id="p502">
<to>Jani</to>
<from>Tove</from>
<heading>Re: Reminder</heading>
<body>I will not!</body>
</note>
</messages>
这些示例中的 ID 只是一个计数器或唯一标识符,用于识别 XML 文件中不同的 note
,并不是 note
数据的一部分。
这里想说的是,元数据(关于数据的数据)应该存储为属性,而数据本身应该存储为元素。
实体声明
实体(Entity)被用来定义对特殊字符的快捷方式。实体可以声明为内部或外部。
内部实体声明
语法
<!ENTITY entity-name "entity-value">
示例
DTD示例
<!ENTITY writer "Donald Duck.">
<!ENTITY copyright "Copyright W3Schools.">
XML示例
<author>&writer;©right;</author>
注意:一个实体由三部分组成:一个 &
符号、一个实体名和一个分号。
外部实体声明
语法
<!ENTITY entity-name SYSTEM "URI/URL">
XML示例
<author>&writer;©right;</author>
DTD示例
电视节目表DTD
<!DOCTYPE TVSCHEDULE [
<!ELEMENT TVSCHEDULE (CHANNEL+)>
<!ELEMENT CHANNEL (BANNER,DAY+)>
<!ELEMENT BANNER (#PCDATA)>
<!ELEMENT DAY (DATE,(HOLIDAY|PROGRAMSLOT+)+)>
<!ELEMENT HOLIDAY (#PCDATA)>
<!ELEMENT DATE (#PCDATA)>
<!ELEMENT PROGRAMSLOT (TIME,TITLE,DESCRIPTION?)>
<!ELEMENT TIME (#PCDATA)>
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT DESCRIPTION (#PCDATA)>
<!ATTLIST TVSCHEDULE NAME CDATA #REQUIRED>
<!ATTLIST CHANNEL CHAN CDATA #REQUIRED>
<!ATTLIST PROGRAMSLOT VTR CDATA #IMPLIED>
<!ATTLIST TITLE RATING CDATA #IMPLIED>
<!ATTLIST TITLE LANGUAGE CDATA #IMPLIED>
]>
报纸文章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">
]>
产品目录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)>
]>
## 最后
为了方便其他设备和平台的小伙伴观看往期文章:
微信公众号搜索:`Let us Coding`,关注后即可获取最新文章推送
看完如果觉得有帮助,欢迎点赞、收藏、关注
探索 DTD 在 XML 中的作用及解析:深入理解文档类型定义的更多相关文章
- 有效的XML: DTD(文档类型定义)介绍(转)
文档类型定义和命名空间 有效(Valid)的XML文档: 首先,XML文档是个格式正规的(Well-formed)XML文档:(见格式正规的XML:语法 属性 实体 处理指令 样式单 CDATA节). ...
- XML之DTD(文档类型定义)
文档类型定义(DTD)可定义合法的XML文档构建模块.它使用一系列合法的元素来定义文档的结构. DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用. 声明元素 在 DTD 中,XML 元素 ...
- 2018.5.14 XML文档类型定义----DTD
1.DTD概述 一个完全意义上的XML文件不仅仅是Well-fromed(格式良好的),而且还应该是使用了一些自定义的标记ValidatingXMl(有效的)文档也就是说他必须遵守文档类型的定义中已声 ...
- HTML文档类型DTD与浏览器怪异模式
虽然在兼容IE6时候经常会注意到两个模式的区别,但是系统的理解起来,还没有认真总结过.看了一些网上的资料.结合自己的理解汇总了一下,放在这里备忘并分享给大家. 浏览器从服务端获取网页后会根据文档的DO ...
- 文档类型DTD,DOCTYPE和浏览器模式
出处:http://blog.csdn.net/freshlover/article/details/11616563 浏览器从服务端获取网页后会根据文档的DOCTYPE定义显示网页,如果文档正确定义 ...
- 从多个XML文档中读取数据用于显示webapi帮助文档
前言: 你先得知道HelpPageConfig文件,不知道说明你现在不需要这个,所以下文就不用看了,等知道了再看也不急.当然如果你很知道这个,下文也不用看了,因为你会了. 方法一: new XmlDo ...
- Doctype文档类型、作用及触发方式
Doctype文档类型 1) 该标签可声明三种 DTD 类型,分别表示严格版本.过渡版本以及基于框架的 HTML 文档. 2) HTML 4.01 规定了三种文档类型:Strict.Transit ...
- doctype(文档类型)的作用是什么?转载
<!DOCTYPE> 声明位于文档中的最前面的位置,处于 <html> 标签之前.此标签可告知浏览器文档使用哪种 HTML 或 XHTML 规范. Document Type ...
- Java解析word,获取文档中图片位置
前言(背景介绍): Apache POI是Apache基金会下一个开源的项目,用来处理office系列的文档,能够创建和解析word.excel.ppt格式的文档. 其中对word文档的处理有两个技术 ...
- XHTML 1.0 的三种 XML 文档类型 DOCTYPE
XHTML 1.0 的三种 XML 文档类型 XHTML 1.0 规定了三种 XML 文档类型 XHTML 1.0 Strict <!DOCTYPE html PUBLIC "-//W ...
随机推荐
- 【Oracle】手动安装和卸载Oracle,这是最全的一篇了!!
写在前面 之前写过一篇在CentOS 7/8上安装Oracle的文章,按照我写的文章安装成功了,但是卸载Oracle时出现了问题.今天,我就整理一篇手动安装和卸载Oracle的文章吧.全文为实战型内容 ...
- Java中关于优先队列PriorityQueue详解
一.优先队列概述 优先队列PriorityQueue是Queue接口的实现,可以对其中元素进行排序, 可以放基本数据类型的包装类(如:Integer,Long等)或自定义的类 对于基本数据类型的包装器 ...
- Hybrid-PSC:基于对比学习的混合网络,解决长尾图片分类 | CVPR 2021
论文提出新颖的混合网络用于解决长尾图片分类问题,该网络由用于图像特征学习的对比学习分支和用于分类器学习的交叉熵分支组成,在训练过程逐步将训练权重调整至分类器学习,达到更好的特征得出更好的分类器的思想 ...
- 大数据hadoop Linux 相关常用命令行操作
bin/zkServer.sh start bin/zkServer.sh stop 启动Hadoop 1 hadoop102 sbin/start-dfs.sh 2 hadoop103 sbin/s ...
- SQL Server表分区-水平分区3
目录 一.常用分区步骤 1.创建文件组 2.创建数据文件到文件组里面 3.使用图形界面向导创建分区表(不推荐) 3.使用T-SQL构建分区函数与分区方案(推荐) [3.1]建表时构造 [3.2]已有表 ...
- SC的板子库~
观前须知 Sugar_Cube的博客园主页 声明 本文所有内容遵循CC BY-NC-SA 4.0 Deed原则 本文包含了笔者常用的OI算法.数据结构的模板 不保证算法最优,但能通过相应的模板题(如果 ...
- 【分享汇总】AIoT 开源科技节暨 OpenHarmony 技术论坛(附链接)
在开源科技 OSTech 和环球资源联手举办的"AIoT 开源科技节暨 OpenHarmony 技术论坛"上,一众技术大咖.开源鸿蒙生态上下游厂商与开发者群体齐聚一堂,畅谈&quo ...
- C#中超链接方法
linkLabel控件:双击事件打开网页:System.Diagnostics.Process.Start("http://www.baidu.com"); 截图:
- RabbitMQ 09 主题模式
主题模式 主题模式结构图: 主题模式实际上就是一种模糊匹配的模式,可以将routingKey以模糊匹配的方式去进行转发. 可以使用*或#来表示: *:任意的一个单词. #:0个或多个单词. 定义配置类 ...
- 元启发式算法库 MEALPY 初体验-遗传算法为例
简介 官网: MealPY官网 开源许可: (GPL) V3 MEALPY简介 官网简介翻译 MEALPY (MEta-heuristic ALgorithms in PYthon) 是一个提供最新自 ...