XML DTD基础与安全

约 10 分钟读完

DTD

简介

DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。

DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

DTD构建模块

PCDATA

PCDATA 的意思是被解析的字符数据(parsed character data)。

可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。

PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。

文本中的标签会被当作标记来处理,而实体会被展开。

不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它们。

CDATA

CDATA 的意思是字符数据(character data)。

**CDATA 是不会被解析器解析的文本。**在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。

DTD修饰符号

img

内部声明

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 元素名
    属性名 属性类型 默认行为
    属性名 属性类型 默认行为
    ...
>
  • 元素名:属性所属的元素名称。
  • 属性名:属性的名称。
  • 属性类型:属性的数据类型(如 CDATAIDIDREF 等)。
  • 默认行为:定义属性的默认值或行为(如 #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"
>
  • idID 类型,必须提供值。
  • genderCDATA 类型,可选。
  • 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 属性引用多个 personid

对应的 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 属性必须是 cartruckmotorcycle 之一。
  • 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> 声明属性。
  • 属性类型(如 CDATAIDIDREF 等)决定了属性值的格式。
  • 默认行为(如 #REQUIRED#IMPLIED#FIXED 等)控制属性的使用方式。
  • 属性可以引用实体、枚举值或其他元素。

通过合理使用属性,可以创建结构清晰、语义明确的 XML 文档。

声明一个空标签

dtd中加入

<!ELEMENT root (id)>

xml文件中

<id/>

声明任何元素

image-20250305201606682

<?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 是一个参数实体,定义了 idclass 属性。然后在 personaddress 元素中通过 %common.attributes; 引用这个参数实体,避免了重复定义。

示例2:定义可重用的元素结构

<!ENTITY % person.content "(name, age, address)">

<!ELEMENT person %person.content;>
<!ELEMENT employee %person.content;>

在这个例子中,person.content 是一个参数实体,定义了 personemployee 元素的共同内容结构。然后在 personemployee 元素中通过 %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的设计更加灵活和高效。

总结

image-20250305224246489

image-20250305224310592

← RCE漏洞 DNSlog注入 →