文档类型定义(DTD)可定义合法的XML文档构建模块
它使用一系列合法的元素来定义文档的结构
优点
通过 DTD,每一个 XML 文件均可携带一个有关其自身格式的描述。
通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据。
而您的应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据。
您还可以使用 DTD 来验证您自身的数据。
声明
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用
内部声明
假如 DTD 被包含在 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:
1 | <!DOCTYPE root-element [element-declarations]> |
例如
1 | <?xml version="1.0"?> |
以上 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 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:
1 | <!DOCTYPE root-element SYSTEM "filename"> |
例如
1 | <?xml version="1.0"?> |
note.dtd
1 | <!ELEMENT note (to,from,heading,body)> |
XML构建模块
XML 和 HTML文档主要的构建模块是元素标签
所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:
元素
元素是 XML 以及 HTML 文档的主要构建模块。
HTML 元素的例子是 “body” 和 “table”。XML 元素的例子是 “note” 和 “message” 。元素可包含文本、其他元素或者是空的。空的 HTML 元素的例子是 “hr”、”br” 以及 “img”
例如:
1
2<body>some text</body>
<message>some text</message>属性
属性可提供有关元素的额外信息。
属性总是被置于某元素的开始标签中。属性总是以名称/值的形式成对出现的。下面的 “img” 元素拥有关于源文件的额外信息:
1
<img src="computer.gif" />
元素的名称是 “img”。属性的名称是 “src”。属性的值是 “computer.gif”。由于元素本身为空,它被一个 “ /“ 关闭
实体
实体是用来定义普通文本的变量。实体引用是对实体的引用。
大多数同学都了解这个 HTML 实体引用:” (破坏实体);”。这个”无折行空格”实体在 HTML 中被用于在某个文档中插入一个额外的空格。
当文档被 XML 解析器解析时,实体就会被展开。
例如:
<(破坏实体);的对应字符为<
>(破坏实体);的对应字符为>
&(破坏实体);的对应字符为&
"(破坏实体);的对应字符为”
&apos(破坏实体);的对应字符为’
PCDATA
PCDATA 的意思是被解析的字符数据(parsed character data)。
可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。
PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
文本中的标签会被当作标记来处理,而实体会被展开。
不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &(破坏实体);、<(破坏实体); 以及 >(破坏实体); 实体来分别替换它们。
CDATA
CDATA 的意思是字符数据(character data)。
CDATA 是不会被解析器解析的文本。在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开
DTD元素
在一个 DTD 中,元素通过元素声明来进行声明
元素声明使用下面的语法:
1 | <!ELEMENT element-name category> |
空元素
通过类别关键词EMPTY进行声明
1 | <!ELEMENT element-name EMPTY> |
只有 PCDATA 的元素通过圆括号中的 #PCDATA 进行声明:
1 | <!ELEMENT element-name (#PCDATA)> |
通过类别关键词 ANY 声明的元素,可包含任何可解析数据的组合:
1 | <!ELEMENT element-name ANY> |
带有一个或多个子元素的元素通过圆括号中的子元素名进行声明:
1 | <!ELEMENT element-name (child1)> |
当子元素按照由逗号分隔开的序列进行声明时,这些子元素必须按照相同的顺序出现在文档中。在一个完整的声明中,子元素也必须被声明,同时子元素也可拥有子元素。”note” 元素的完整声明是:
1 | <!ELEMENT note (to,from,heading,body)> |
声明只出现一次的元素
1 | <!ELEMENT element-name (child-name)> |
上面的例子声明了:message 子元素必须出现一次,并且必须只在 “note” 元素中出现一次
声明最少出现一次的元素
1 | <!ELEMENT element-name (child-name+)> |
上面的例子中的加号(+)声明了:message 子元素必须在 “note” 元素内出现至少一次
声明出现零次或一次的元素
1 | <!ELEMENT element-name (child-name?)> |
上面的例子中的问号(?)声明了:子元素 message 可在 “note” 元素内出现零次或一次
声明出现零次或多次的元素
1 | <!ELEMENT element-name (child-name*)> |
上面的例子中的星号(*)声明了:子元素 message 可在 “note” 元素内出现零次或多次
声明“非···/即···”类型的内容
1 | 实例: |
声明混合型的内容
1 | 实例: |
上面的例子声明了:”note” 元素可包含出现零次或多次的 PCDATA、”to”、”from”、”header” 或者 “message”
DTD属性
在 DTD 中,属性通过 ATTLIST 声明来进行声明
示例:
1 | <!ATTLIST element-name attribute-name attribute-type attribute-value> |
属性的类型
类型 | 描述 | ||
---|---|---|---|
CDATA | 值为字符数据 (character data) | ||
(en1\ | en2\ | ..) | 此值是枚举列表中的一个值 |
ID | 值为唯一的 id | ||
IDREF | 值为另外一个元素的 id | ||
IDREFS | 值为其他 id 的列表 | ||
NMTOKEN | 值为合法的 XML 名称 | ||
NMTOKENS | 值为合法的 XML 名称的列表 | ||
ENTITY | 值是一个实体 | ||
ENTITIES | 值是一个实体列表 | ||
NOTATION | 此值是符号的名称 | ||
xml: | 值是一个预定义的 XML 值 |
默认属性值
可用以下值
值 | 解释 |
---|---|
值 | 属性的默认值 |
#REQUIRED | 属性值是必需的 |
#IMPLIED | 属性不是必需的 |
#FIXED value | 属性值是固定的 |
例如:
1 | DTD: |
在上面的例子中,”square” 被定义为带有 CDATA 类型的 “width” 属性的空元素。如果宽度没有被设定,其默认值为0
#REQUIRED
语法
1 | <!ATTLIST element-name attribute-name attribute-type #REQUIRED>· |
示例:1
2
3
4
5
6
7
8DTD:
<!ATTLIST person number CDATA #REQUIRED>
合法的 XML:
<person number="5677" />
非法的 XML:
<person />
#IMPLED
语法
1 | <!ATTLIST element-name attribute-name attribute-type #IMPLIED> |
示例:
1 | DTD: |
#FIXED
语法
1 | <!ATTLIST element-name attribute-name attribute-type #FIXED "value"> |
实例
1 | DTD: |
列举属性值
语法
1 | <!ATTLIST element-name attribute-name (en1|en2|..) default-value> |
实例
1 | DTD: |
如果您希望属性值为一系列固定的合法值之一,请使用列举属性值。(男|女)
元素&属性
xml中数据可以存储在子元素或属性中
例:
1 | <person sex="female"> |
1 | <person> |
没有特别规定何时使用属性,以及何时使用子元素。
一些属性具有以下问题:
- 属性不能包含多个值(子元素可以)
- 属性不容易扩展(为以后需求的变化)
- 属性无法描述结构(子元素可以)
- 属性更难以操纵程序代码
- 属性值是不容易测试,针对DTD
如果您使用属性作为数据容器,最终的XML文档将难以阅读和维护。 尝试使用元素来描述数据。只有在提供的数据是不相关信息时我们才建议使用属性。
例外:唯一标识符ID
1 | <messages> |
以上实例的XML文件中,ID是只是一个计数器,或一个唯一的标识符,来识别不同的音符,而不是作为数据的一部分。
在这里我想说的是,元数据(关于数据的数据)应当存储为属性,而数据本身应当存储为元素。
实体
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
- 实体引用是对实体的引用。
- 实体可在内部或外部进行声明。
内部声明
语法
1 | <!ENTITY entity-name "entity-value"> |
注意: 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。
外部声明
语法
1 | <!ENTITY entity-name SYSTEM "URI/URL"> |
验证
当您试图打开某个 XML 文档时,XML 解析器有可能会产生错误。通过访问 parseError 对象,就可以取回引起错误的确切代码、文本甚至所在的行。