探索 DTD 在 XML 中的作用及解析:深入理解文档类型定义

这篇具有很好参考价值的文章主要介绍了探索 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 实体: "&nbsp;"。这个 "no-breaking-space" 实体用于在 HTML 文档中插入额外的空格。实体在 XML 解析器解析文档时会被展开。

以下实体在 XML 中是预定义的:

  • &lt; 代表 <
  • &gt; 代表 >
  • &amp; 代表 &
  • &quot; 代表 "
  • &apos; 代表 '

PCDATA

PCDATA 表示解析的字符数据。

将字符数据视为 XML 元素的开始标记和结束标记之间找到的文本。

PCDATA 是解析器将解析的文本。解析器将检查文本中的实体和标记。

文本内的标记将被视为标记,并且实体将被展开。

但是,解析的字符数据不应包含任何&、<或>字符;这些需要用分别表示为 &amp; &lt;&gt; 实体。

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 文档包含完全相同的信息:

  1. 使用了一个 date 属性:
<note date="12/11/2002">
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>
  1. 使用了一个 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>
  1. 使用了扩展的 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;&copyright;</author>

注意:一个实体由三部分组成:一个 & 符号、一个实体名和一个分号。

外部实体声明

语法

<!ENTITY entity-name SYSTEM "URI/URL">

XML示例

<author>&writer;&copyright;</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文章来源地址https://www.toymoban.com/news/detail-859192.html

<!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 中的作用及解析:深入理解文档类型定义的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • jvm深入研究文档--java中的堆--详解!--jvm底层探索(1)

    JVM的内存分区包括以下几个部分: 堆区(Heap) - 这是JVM的主要部分,用于存储实例对象和大多数Java对象,如数组和用户定义的类。 方法区(Method Area) - 这是线程私有的,用于存放类对象(加载好的类)。 栈区(Stack) - 这是线程私有的,包括虚拟机栈和本地方法栈。虚拟

    2024年02月07日
    浏览(51)
  • Spring-1-深入理解Spring XML中的依赖注入(DI):简化Java应用程序开发

    前两篇文章我们介绍了什么是Spring,以及Spring的一些核心概念,并且快速快发一个Spring项目,以及详细讲解IOC,今天详细介绍一些DI(依赖注入) 能够配置setter方式注入属性值 能够配置构造方式注入属性值 能够理解什么是自动装配 思考:向一个类中传递数据的方式有几种?(给类

    2024年02月13日
    浏览(50)
  • XML—DTD、 Schema

    目录 DTD是什么? DTD有什么用途? DTD与XML有什么联系? DTD原理图 外部DTD DTD文件book.dtd: 使用外部DTD文件的XML文件 PCDATA XML 文档构建模块 一、元素 1、元素声明 ①、有元素: ②、空元素: ③、ANY带有任何内容元素: 2、定义某个标签内元素个数(利用一些符号标识) 声明只出

    2024年02月10日
    浏览(36)
  • Docker 核心概念深度解析:探索容器、镜像和仓库在Docker生态系统中的重要作用和 应用

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月16日
    浏览(48)
  • 深入理解C++中的堆与栈:内存管理的关键区别与实例解析

      概述: C++中,堆和栈是两种不同的内存分配方式。栈自动分配、释放内存,适用于短生命周期变量;堆需要手动管理,适用于动态分配内存,但需要显式释放以防内存泄漏。通过清晰的示例源代码,演示了它们在变量生命周期、访问方式等方面的区别。 C++中的堆(heap)和

    2024年02月22日
    浏览(67)
  • 深入理解作用域、作用域链和闭包

     ​ 🎬 岸边的 风 :个人主页  🔥  个人专栏  :《 VUE 》 《 javaScript 》 ⛺️  生活的理想,就是为了理想的生活 ! ​ 目录  📚 前言  📘 1. 词法作用域 📖 1.2 示例 📖 1.3 词法作用域的应用场景  📘 2. 作用域链 📖 2.1 概念 📖 2.2 示例 📖 2.3 作用域链的应用场景  📘

    2024年02月10日
    浏览(41)
  • 【XML技术】web杂谈(3)之深入理解什么是XML、XML的语法详解

    什么是 XML,XML的特征,XML的基本语法及应用,应用程序接口(DOMSAX),XML的文档的显示,深入了解XML技术。 原创于:CSDN博主-《拄杖盲学轻声码》,更多内容可去其主页关注下哈,不胜感激 Web 上的文档组织包含了服务器端文档的存储方式、客户端页面的浏览方式以及传输方

    2024年02月11日
    浏览(43)
  • 深入理解注解驱动配置与XML配置的融合与区别

    摘要: 本文旨在深入探讨Spring框架的注解驱动配置与XML配置,揭示两者之间的相似性与差异。 本文分享自华为云社区《Spring高手之路2——深入理解注解驱动配置与XML配置的融合与区别》,作者:砖业洋__ 。 本文旨在深入探讨Spring框架的注解驱动配置与XML配置,揭示两者之间

    2024年02月08日
    浏览(45)
  • 深入理解Spring @RequestBody注解的用法与作用

    当我们使用 Spring Boot 框架处理客户端提交的 HTTP 请求时,常常需要获取请求参数并将其转换为相应的 Java 对象。@RequestBody 注解可以帮助我们实现这个目标,它用于从 HTTP 请求体中获取请求参数,并将其转换为指定的 Java 对象。本篇博客将介绍 @RequestBody 注解的基本用法和注意

    2024年02月15日
    浏览(46)
  • 【深入理解ES6】块级作用域绑定

    提升(Hoisting)机制:通过var声明的变量,都会被当成在当前作用域顶部生命的变量。 JavaScript引擎会将上面的getValue函数修改为下面这样。变量value的声明被提升至函数顶部,初始化操作依旧保留在原处执行。为此,ES6引入了块级作用域来强化对变量声明周期的控制。

    2024年02月12日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包