XML DTD基础与安全
DTD
简介
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
DTD构建模块
PCDATA
PCDATA 的意思是被解析的字符数据(parsed character data)。
可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。
PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
文本中的标签会被当作标记来处理,而实体会被展开。
不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它们。
CDATA
CDATA 的意思是字符数据(character data)。
**CDATA 是不会被解析器解析的文本。**在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。
DTD修饰符号

内部声明
DTD文件包含在XML源文件中
代码示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE class [
<!ELEMENT class (student,teacher)>
<!ELEMENT student (#PCDATA)>
<!ELEMENT teacher (#PCDATA)>
]>
<class>
<student>mali</student>
<teacher>zhang</teacher>
</class>#PCDATA 可解析内容
<,>,",',&等使用引用实体
#CDATA不被解析
<,>,",',&等直接使用
外部声明
在同目录下建立文件test.xml和test.dtd文件,分别写入
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root SYSTEM "test.dtd" >
<root>
<student>zhang</student>
<teacher>li</teacher>
</root><!ELEMENT root (student,teacher)>
<!ELEMENT student (#PCDATA)>
<!ELEMENT teacher (#PCDATA)>DTD属性
DTD 属性(Attributes)详细介绍
在 DTD(文档类型定义)中,属性用于为元素提供附加信息。属性定义在 <!ATTLIST> 声明中,指定元素的名称、属性名称、属性类型和默认行为。属性可以增强 XML 文档的灵活性和表达能力。
1. 属性声明语法
属性的声明使用 <!ATTLIST> 关键字,语法如下:
<!ATTLIST 元素名
属性名 属性类型 默认行为
属性名 属性类型 默认行为
...
>- 元素名:属性所属的元素名称。
- 属性名:属性的名称。
- 属性类型:属性的数据类型(如
CDATA、ID、IDREF等)。 - 默认行为:定义属性的默认值或行为(如
#REQUIRED、#IMPLIED、#FIXED等)。
2. 属性类型
DTD 支持多种属性类型,以下是一些常见的类型:
| 属性类型 | 描述 |
|---|---|
| CDATA | 字符数据,可以包含任意文本。 |
| ID | 唯一标识符,用于标识元素。 |
| IDREF | 引用同一文档中的 ID 类型的属性值。 |
| IDREFS | 引用多个 ID 类型的属性值,用空格分隔。 |
| NMTOKEN | 名称令牌,由字母、数字、点、连字符、下划线和冒号组成。 |
| NMTOKENS | 多个 NMTOKEN,用空格分隔。 |
| ENTITY | 引用一个实体。 |
| ENTITIES | 引用多个实体,用空格分隔。 |
| NOTATION | 引用一个符号(notation)。 |
| 枚举类型 | 列出可能的取值,用竖线 ` |
3. 默认行为
默认行为定义了属性的默认值或是否必须提供值:
| 默认行为 | 描述 |
|---|---|
| #REQUIRED | 属性必须提供值。 |
| #IMPLIED | 属性是可选的,可以不提供值。 |
| #FIXED 值 | 属性值是固定的,不能更改。 |
| 默认值 | 如果未提供属性值,则使用默认值。 |
4. 属性用法示例
以下是一些常见的属性用法示例:
示例 1:基本属性
<!ELEMENT person (name, age)>
<!ATTLIST person
id ID #REQUIRED
gender CDATA #IMPLIED
status (active|inactive) "active"
>id是ID类型,必须提供值。gender是CDATA类型,可选。status是枚举类型,默认值为active。
对应的 XML 文档:
<person id="p1" gender="male">
<name>John Doe</name>
<age>30</age>
</person>示例 2:引用属性(ID 和 IDREF)
<!ELEMENT person (name, age)>
<!ATTLIST person
id ID #REQUIRED
>
<!ELEMENT company (employee*)>
<!ATTLIST company
employee IDREFS #IMPLIED
>person元素的id是唯一的。company元素的employee属性引用多个person的id。
对应的 XML 文档:
<person id="p1">
<name>John Doe</name>
<age>30</age>
</person>
<person id="p2">
<name>Jane Smith</name>
<age>25</age>
</person>
<company employee="p1 p2" />示例 3:固定属性值
<!ELEMENT book (title, author)>
<!ATTLIST book
language CDATA #FIXED "English"
category CDATA #IMPLIED
>language属性值是固定的,不能更改。category属性是可选的。
对应的 XML 文档:
<book language="English" category="Fiction">
<title>The Great Novel</title>
<author>John Author</author>
</book>示例 4:枚举类型
<!ELEMENT vehicle (model, year)>
<!ATTLIST vehicle
type (car|truck|motorcycle) #REQUIRED
color CDATA #IMPLIED
>type属性必须是car、truck或motorcycle之一。color属性是可选的。
对应的 XML 文档:
<vehicle type="car" color="red">
<model>Sedan</model>
<year>2020</year>
</vehicle>示例 5:实体引用
<!ENTITY companyName "Tech Corp">
<!ELEMENT employee (name, position)>
<!ATTLIST employee
company CDATA #FIXED "&companyName;"
id ID #REQUIRED
>company属性值是固定的,引用了实体companyName。id属性是唯一的。
对应的 XML 文档:
<employee company="Tech Corp" id="e1">
<name>Alice</name>
<position>Developer</position>
</employee>5. 总结
DTD 属性为 XML 元素提供了附加信息,增强了 XML 文档的表达能力。通过属性类型和默认行为的组合,可以定义灵活且严格的文档结构。以下是关键点:
- 使用
<!ATTLIST>声明属性。 - 属性类型(如
CDATA、ID、IDREF等)决定了属性值的格式。 - 默认行为(如
#REQUIRED、#IMPLIED、#FIXED等)控制属性的使用方式。 - 属性可以引用实体、枚举值或其他元素。
通过合理使用属性,可以创建结构清晰、语义明确的 XML 文档。
声明一个空标签
dtd中加入
<!ELEMENT root (id)>
xml文件中
<id/>
声明任何元素

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root SYSTEM "test.dtd" >
<root>
<student>zhang</student>
<teacher>li</teacher>
<br/>
<name>
aisduh
<student>wang</student>
</name>
</root><!ELEMENT root (student,teacher,br,name)>
<!ELEMENT student (#PCDATA)>
<!ELEMENT teacher (#PCDATA)>
<!ELEMENT name ANY>
<!ELEMENT br EMPTY>DTD实体
内部引用:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root-element [
<!ENTITY write "value">
]>
<root-element>
&write;
</root-element>浏览器显示:
<root-element> value </root-element>
外部引用
参数实体(Parameter Entities)详细介绍
参数实体是DTD(文档类型定义)中的一种特殊实体,主要用于在DTD内部定义可重用的片段。参数实体只能在DTD中使用,不能在XML文档中使用。它们通常用于简化复杂DTD的结构,避免重复定义,提高DTD的可维护性和可读性。
参数实体的定义语法
参数实体的定义使用 <!ENTITY % 开头,后面跟实体名和实体内容。
<!ENTITY % 实体名 "实体内容">- 实体名:参数实体的名称,遵循XML命名规则。
- 实体内容:参数实体的内容,可以是文本、属性列表、元素声明等。
参数实体的使用语法
在DTD中,参数实体通过 %实体名; 来引用。
%实体名;参数实体的应用场景
- 定义可重用的属性列表:将常用的属性列表定义为参数实体,然后在多个元素中引用。
- 定义可重用的元素结构:将常用的元素结构定义为参数实体,然后在多个地方引用。
- 简化复杂DTD:通过参数实体将复杂的DTD分解为多个可管理的部分。
参数实体的示例
示例1:定义可重用的属性列表
<!ENTITY % common.attributes "id ID #IMPLIED class CDATA #IMPLIED">
<!ELEMENT person (name, age)>
<!ATTLIST person %common.attributes;>
<!ELEMENT address (street, city, zip)>
<!ATTLIST address %common.attributes;>在这个例子中,common.attributes 是一个参数实体,定义了 id 和 class 属性。然后在 person 和 address 元素中通过 %common.attributes; 引用这个参数实体,避免了重复定义。
示例2:定义可重用的元素结构
<!ENTITY % person.content "(name, age, address)">
<!ELEMENT person %person.content;>
<!ELEMENT employee %person.content;>在这个例子中,person.content 是一个参数实体,定义了 person 和 employee 元素的共同内容结构。然后在 person 和 employee 元素中通过 %person.content; 引用这个参数实体,简化了元素定义。
示例3:模块化DTD
假设有一个复杂的DTD,可以将其分解为多个部分,并使用参数实体引用这些部分。
<!-- common.dtd -->
<!ENTITY % common.attributes "id ID #IMPLIED class CDATA #IMPLIED">
<!ENTITY % person.content "(name, age, address)">
<!-- main.dtd -->
<!ENTITY % common SYSTEM "common.dtd">
%common;
<!ELEMENT person %person.content;>
<!ATTLIST person %common.attributes;>
<!ELEMENT employee %person.content;>
<!ATTLIST employee %common.attributes;>在这个例子中,common.dtd 文件定义了常用的参数实体,然后在 main.dtd 文件中通过 %common; 引用 common.dtd 文件,实现了DTD的模块化管理。
总结
参数实体是DTD中非常有用的工具,可以帮助简化复杂DTD的结构,避免重复定义,提高DTD的可维护性和可读性。通过定义可重用的属性列表、元素结构和模块化DTD,参数实体使得DTD的设计更加灵活和高效。
总结

