3838 字
19 分钟
DTD-XML
2026-02-04

DTD笔记#

文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。 DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

声明#

内部的 DOCTYPE 声明#

语法

<!DOCTYPE root-element [element-declarations]>

实例

<?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>

解释

  • !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” 类型

外部文档声明#

语法

<!DOCTYPE root-element SYSTEM "filename">

实例

<?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>

这个 XML 文档和上面的 XML 文档相同,但是拥有一个外部的 DTD。

“note.dtd” 文件

<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>

使用原因#

通过 DTD,每一个 XML 文件均可携带一个有关其自身格式的描述,独立的团体也可一致地使用某个标准的 DTD 来交换数据;应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据,还可以使用 DTD 来验证自身的数据

XML构建模块#

组成#

  • 元素
  • 属性
  • 实体
  • PCDATA
  • CDATA

元素#

元素是 XML 以及 HTML 文档的主要构建模块。 HTML 元素的例子是 “body” 和 “table”。XML 元素的例子是 “note” 和 “message” 。元素可包含文本、其他元素或者是空的。空的 HTML 元素的例子是 “hr”、“br” 以及 “img”。 还可提供其它信息。

实体#

实体是用来定义普通文本的变量

当文档被 XML 解析器解析时,实体就会被展开

实体引用字符
&lt;<
&gt;>
&amp;&
&quot;
&apos;

PCDATA#

PCDATA 的意思是被解析的字符数据,可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。

PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。 文本中的标签会被当作标记来处理,而实体会被展开。 不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它们。

CDATA#

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

DTD元素#

在一个 DTD 中,元素通过元素声明来进行声明

声明一个元素#

语法

<!ELEMENT element-name category>
<!ELEMENT element-name (element-content)>

空元素#

类别关键词EMPTY

<!ELEMENT element-name EMPTY>

只有 PCDATA 的元素#

通过圆括号中的#PCDATA

<!ELEMENT element-name (#PCDATA)>

带有任何内容的元素#

类别关键词ANY

<!ELEMENT element-name ANY>

带有子元素(序列)的元素#

<!ELEMENT element-name (child1)>
<!ELEMENT element-name (child1,child2,...)>

当子元素按照由逗号分隔开的序列进行声明时,这些子元素必须按照相同的顺序出现在文档中。在一个完整的声明中,子元素也必须被声明,同时子元素也可拥有子元素

声明只出现一次的元素#

<!ELEMENT element-name (child-name)>

声明最少出现一次的元素#

<!ELEMENT element-name (child-name+)>

声明出现零次或一次的元素#

<!ELEMENT element-name (child-name?)>

声明出现零次或多次的元素#

<!ELEMENT element-name (child-name*)>

声明”非…/即…”类型的内容#

<!ELEMENT note (to,from,header,(message|body))>

上面的例子声明了:“note” 元素必须包含 “to” 元素、“from” 元素、“header” 元素,以及非 “message” 元素即 “body” 元素。

声明混合型的内容#

<!ELEMENT note (#PCDATA|to|from|header|message)*>

上面的例子声明了:“note” 元素可包含出现零次或多次的 PCDATA、“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" />

属性类型#

以下是 属性类型的选项

类型描述
CDATA值为字符数据 (character data)
(en1|en2|..)此值是枚举列表中的一个值
ID值为唯一的 id
IDREF值为另外一个元素的 id
IDREFS值为其他 id 的列表
NMTOKEN值为合法的 XML 名称
NMTOKENS值为合法的 XML 名称的列表
ENTITY值是一个实体
ENTITIES值是一个实体列表
NOTATION此值是符号的名称
xml:值是一个预定义的 XML 值

默认属性值#

DTD:
<!ELEMENT square EMPTY>
<!ATTLIST square width CDATA "0">
合法的 XML:
<square width="100" />

默认属性值可使用下列值

解释
属性的默认值
#REQUIRED属性值是必需的
#IMPLIED属性不是必需的
#FIXED value属性值是固定的

#REQUIRED#

语法

<!ATTLIST element-name attribute-name attribute-type #REQUIRED>

#IMPLIED#

语法

<!ATTLIST element-name attribute-name attribute-type #IMPLIED>

#FIXED#

语法

<!ATTLIST element-name attribute-name attribute-type #FIXED "value">

列举属性值#

语法

<!ATTLIST element-name attribute-name (en1|en2|..) default-value>

实体#

实体是用于定义引用普通文本或特殊字符的快捷方式的变量。

  • 实体引用是对实体的引用。
  • 实体可在内部或外部进行声明。

一个内部实体声明#

语法

<!ENTITY entity-name "entity-value">

实例

DTD 实例:
<!ENTITY writer "Donald Duck.">
<!ENTITY copyright "Copyright runoob.com">
XML 实例:
<author>&writer;&copyright;</author>

一个外部实体声明+协议#

语法

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

实例

DTD 实例:
<!ENTITY writer SYSTEM "http://www.runoob.com/entities.dtd">
<!ENTITY copyright SYSTEM "http://www.runoob.com/entities.dtd">
XML example:
<author>&writer;&copyright;</author>

外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示

libxml2PHPJava.NET
file

http

ftp
file

http

ftp

php

compress.zlib

compress.bzip2

data

glob

phar
http

https

ftp

file

jar

netdoc

mailto

gopher *
file

http

https

ftp
上述实体(内部和外部)另方面看,其实也可以分为两种:通用实体参数实体

通用实体#

用 &实体名; 引用的实体,他在DTD 中定义,在 XML 文档中引用 示例代码:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE updateProfile [<!ENTITY file SYSTEM "file:///c:/windows/win.ini"> ]>
<updateProfile>
<firstname>Joe</firstname>
<lastname>&file;</lastname>
...
</updateProfile>

通常用于 有回显 的场景。引用它,服务器把内容读出来显示在页面上

参数实体#

<!DOCTYPE note> [
<!ENTITY % b "<!ENTITY b1 "awsl">">
%b;
]>
<note>&b1</note>
<!-- awsl -->

(1)使用 % 实体名(这里面空格不能少) 在 DTD 中定义,并且只能在 DTD 中使用 %实体名; 引用 (2)只有在 DTD 文件中,参数实体的声明才能引用其他实体
(3)和通用实体一样,参数实体也可以外部引用 示例代码:

<!ENTITY % an-element "<!ELEMENT mytag (subtag)>">
<!ENTITY % remote-dtd SYSTEM "http://somewhere.example.org/remote.dtd">
%an-element; %remote-dtd;

通常用于 无回显 的场景。 用法:需要利用参数实体,配合带外数据传输(OOB - Out of Band)。通过参数实体拼接 URL,让服务器把读到的文件内容作为参数,发送到你控制的 VPS 上(例如:http://hacker.com/?data=文件内容

实体类型符号定义位置引用位置主要用途关键特性
通用实体&name;DTDXML 正文最终数据的展示直接替换,用于回显
参数实体%name;DTDDTD 内部数据拼接、带外传输只能在 DTD 区域内使用

XML笔记#

概念#

XML 的全称是 Extensible Markup Language,即可扩展标记语言,它是一种用于存储和传输数据的标记语言,核心特点是可扩展性平台无关性。 和 HTML 不同,HTML 的标签是预定义的(如 <div><p><a>),只能用于展示网页内容;而 XML 的标签是自定义的,可以根据数据的含义来命名,更适合描述数据的结构和语义。

XML元素#

定义#

XML 元素指的是从开始标签直到结束标签的部分。[开始标签,结束标签] 一个元素可以包含:

- 其他元素
- 文本
- 属性
- 或混合以上所有...

命名规则#

  • 名称可以包含字母数字以及其他的字符
  • 名称不能数字或者标点符号开始
  • 名称不能以字母 xml(或者 XML、Xml 等等)开始
  • 名称不能包含空格 命名习惯 描述性、简短性、避免-.:

可扩展性#

可以携带更多的信息

XML 属性#

属性提供有关元素的额外信息——提供额外信息

<img src="computer.gif">
<a href="demo.html">

属性通常提供不属于数据组成部分的信息——通常不提供数组信息

<file type="gif">computer.gif</file>
# 文件类型与数据无关,但是对需要处理这个元素的软件来说却很重要

属性值必须被引号包围,不过单引号和双引号均可使用——必须加引号

<gangster name='George "Shotgun" Ziegler'>
<person sex="female">

元素vs属性

<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 验证#

语法规则#

- XML 文档必须有一个根元素
- XML元素都必须有一个关闭标签
- XML 标签对大小写敏感
- XML 元素必须被正确的嵌套
- XML 属性值必须加引号

验证 XML 文档#

合法的 XML 文档是”形式良好”的 XML 文档,这也符合文档类型定义(DTD)的规则

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE note SYSTEM "Note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

在上面的实例中,DOCTYPE 声明是对外部 DTD 文件的引用

XML DTD#

略,详细看DTD教程

XML Schema#

W3C 支持一种基于 XML 的 DTD 代替者:XML Schema

<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element name="to" type="xs:string"/>
<xs:element name="from" type="xs:string"/>
<xs:element name="heading" type="xs:string"/>
<xs:element name="body" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>

XML命名空间#

命名冲突#

成因 在 XML 中,元素名称是由开发者定义的,当两个不同的文档使用相同的元素名时,就会发生命名冲突。

  • 例子 这个 XML 携带 HTML 表格的信息:
<table>
<tr>
<td>Apples</td>
<td>Bananas</td>
</tr>
</table>

这个 XML 文档携带有关桌子的信息(一件家具):

<table>
<name>African Coffee Table</name>
<width>80</width>
<length>120</length>
</table>

假如这两个 XML 文档被一起使用,由于两个文档都包含带有不同内容和定义的<table>元素,就会发生命名冲突。

前缀避免冲突 该 XML 携带某个 HTML 表格和某件家具的信息:

<h:table>
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
<f:table>
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>

在上面的实例中,不会有冲突,因为两个<table>元素有不同的名称。

xmlns 属性#

当在 XML 中使用前缀时,一个所谓的用于前缀的命名空间必须被定义。 命名空间是在元素的开始标签的 xmlns 属性中定义的。 命名空间声明的语法如下。

xmlns:_前缀_="_URI_"。

默认的命名空间#

为元素定义默认的命名空间可以让我们省去在所有的子元素中使用前缀的工作 语法

xmlns="_namespaceURI_"
  • 例子
这个 XML 携带 HTML 表格的信息:
<table xmlns="http://www.w3.org/TR/html4/">
<tr>
<td>Apples</td>
<td>Bananas</td>
</tr>
</table>
这个XML携带有关一件家具的信息:
<table xmlns="http://www.w3schools.com/furniture">
<name>African Coffee Table</name>
<width>80</width>
<length>120</length>
</table>

实际使用中的命名空间#

XSLT 是一种用于把 XML 文档转换为其他格式的 XML 语言,比如 HTML

XML CDATA#

XML 文档中的所有文本均会被解析器解析,只有 CDATA 区段中的文本会被解析器忽略

略,具体看DTD的笔记

服务器上的XML#

XML 文件是类似 HTML 文件的纯文本文件, XML 能够通过标准的 Web 服务器轻松地存储和生成。

在服务器上存储 XML 文件#

XML 文件在 Internet 服务器上进行存储的方式与 HTML 文件完全相同。 启动 Windows 记事本,并写入以下行:

<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<from>Jani</from>
<to>Tove</to>
<message>Remember me this weekend</message>
</note>

然后用适当的文件名,比如 “note.xml”,在 Web 服务器上保存这个文件。

通过 ASP 生成 XML#

XML 可在不安装任何 XML 软件的情况下在服务器端生成。 如需从服务器生成 XML 响应 - 只需简单地编写以下代码并在 Web 服务器上把它保存为一个 ASP 文件:

<%
response.ContentType="text/xml"
response.Write("<?xml version='1.0' encoding='ISO-8859-1'?>")
response.Write("<note>")
response.Write("<from>Jani</from>")
response.Write("<to>Tove</to>")
response.Write("<message>Remember me this weekend</message>")
response.Write("</note>")
%>

请注意,此响应的内容类型必须设置为 “text/xml”。

通过 PHP 生成 XML#

如需使用 PHP 从服务器上生成 XML 响应,请使用下面的代码:

<?php
header("Content-type: text/xml");
echo "<?xml version='1.0' encoding='ISO-8859-1'?>";
echo "<note>";
echo "<from>Jani</from>";
echo "<to>Tove</to>";
echo "<message>Remember me this weekend</message>";
echo "</note>";
?>

请注意,响应头部的内容类型必须设置为 “text/xml”。

从数据库生成 XML#

XML 可在不安装任何 XML 软件的情况下从数据库生成。 如需从服务器生成 XML 数据库响应,只需简单地编写以下代码,并把它在 Web 服务器上保存为 ASP 文件:

<%
response.ContentType = "text/xml"
set conn=Server.CreateObject("ADODB.Connection")
conn.provider="Microsoft.Jet.OLEDB.4.0;"
conn.open server.mappath("/db/database.mdb")
sql="select fname,lname from tblGuestBook"
set rs=Conn.Execute(sql)
response.write("<?xml version='1.0' encoding='ISO-8859-1'?>")
response.write("<guestbook>")
while (not rs.EOF)
response.write("<guest>")
response.write("<fname>" & rs("fname") & "</fname>")
response.write("<lname>" & rs("lname") & "</lname>")
response.write("</guest>")
rs.MoveNext()
wend
rs.close()
conn.close()
response.write("</guestbook>")
%>

在服务器上通过 XSLT 转换 XML#

下面的 ASP 代码在服务器上把 XML 文件转换为 XHTML:

<%
'Load XML
set xml = Server.CreateObject("Microsoft.XMLDOM")
xml.async = false
xml.load(Server.MapPath("simple.xml"))
'Load XSL
set xsl = Server.CreateObject("Microsoft.XMLDOM")
xsl.async = false
xsl.load(Server.MapPath("simple.xsl"))
'Transform file
Response.Write(xml.transformNode(xsl))
%>

实例解释

  • 第一个代码块创建微软 XML 解析器的实例(XMLDOM),并把 XML 文件载入内存。
  • 第二个代码块创建解析器的另一个实例,并把 XSL 文件载入内存。
  • 最后一个代码使用 XSL 文档来转换 XML 文档,并把结果以 XHTML 发送到您的浏览器。

通过 ASP 把 XML 保存为文件#

这个 ASP 实例会创建一个简单的 XML 文档,并把该文档保存到服务器上:

<%
text="<note>"
text=text & "<to>Tove</to>"
text=text & "<from>Jani</from>"
text=text & "<heading>Reminder</heading>"
text=text & "<body>Don't forget me this weekend!</body>"
text=text & "</note>"
set xmlDoc=Server.CreateObject("Microsoft.XMLDOM")
xmlDoc.async=false
xmlDoc.loadXML(text)
xmlDoc.Save("test.xml")
%>

XML DOM#

定义了访问和操作 XML 文档的标准方法。XML DOM 把 XML 文档作为树结构来查看。 所有元素可以通过 DOM 树来访问。可以修改或删除它们的内容,并创建新的元素。元素,它们的文本,以及它们的属性,都被认为是节点。

加载一个 XML 字符串#

实例 把 XML 字符串解析到 XML DOM 对象中,然后通过JavaScript提取一些信息

<html>
<body>
<h1>W3Schools Internal Note</h1>
<div>
<b>To:</b> <span id="to"></span><br />
<b>From:</b> <span id="from"></span><br />
<b>Message:</b> <span id="message"></span>
</div>
<script>
txt="<note>";
txt=txt+"<to>Tove</to>";
txt=txt+"<from>Jani</from>";
txt=txt+"<heading>Reminder</heading>";
txt=txt+"<body>Don't forget me this weekend!</body>";
txt=txt+"</note>";
if (window.DOMParser)
{
parser=new DOMParser();
xmlDoc=parser.parseFromString(txt,"text/xml");
}
else // Internet Explorer
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async=false;
xmlDoc.loadXML(txt);
}
document.getElementById("to").innerHTML=
xmlDoc.getElementsByTagName("to")[0].childNodes[0].nodeValue;
document.getElementById("from").innerHTML=
xmlDoc.getElementsByTagName("from")[0].childNodes[0].nodeValue;
document.getElementById("message").innerHTML=
xmlDoc.getElementsByTagName("body")[0].childNodes[0].nodeValue;
</script>
</body>
</html>

获取元素的值#

eg:检索第一个 <title> 元素的文本值

txt=xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue;

获取属性的值#

eg:检索第一个 <title> 元素的 “lang” 属性的文本值

txt=xmlDoc.getElementsByTagName("title")[0].getAttribute("lang");

改变元素的值#

改变第一个 <title> 元素的文本值

x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
x.nodeValue="Easy Cooking";

元素#

创建元素#

  • XML DOM 的 createElement() 方法创建一个新的元素节点。

  • XML DOM 的 createTextNode() 方法创建一个新的文本节点。

  • XML DOM 的 appendChild() 方法向节点添加子节点(在最后一个子节点之后)。

删除元素#

删除第一个 <book> 元素的第一个节点

x=xmlDoc.getElementsByTagName("book")[0];
x.removeChild(x.childNodes[0]);
DTD-XML
https://fuwari.vercel.app/posts/dtd-xml/
作者
BIG熙
发布于
2026-02-04
许可协议
CC BY-NC-SA 4.0