2000年11月13日

什么是文档对象模型?

编辑
Philippe Le Hégaret, W3C
Lauren Wood,SoftQuad Software Inc.,工作组主席
Jonathan Robie,Texcel(用于 DOM Level 1)

引言

文档对象模型(DOM)是一种面向有效 HTML 和符合规范的 XML 文档的应用程序编程接口(API)。它定义了文档的逻辑结构以及访问和操作文档的方式。在 DOM 规范中,“document”(文档)一词使用的是宽泛的含义——XML 正日益被用来表示可存储在各种系统中的许多不同类型的信息,而这些信息传统上更被视为数据而非文档。尽管如此,XML 将这些数据表现为文档,且可以使用 DOM 来管理这些数据。

借助文档对象模型,程序员可以创建文档、遍历其结构,并添加、修改或删除元素和内容。HTML 或 XML 文档中的任何内容都可以使用文档对象模型进行访问、修改、删除或添加,只有少数例外——特别是,XML 的内部子集和外部子集的 DOM interfaces 尚未被指定。

作为 W3C 规范,文档对象模型的一个重要目标是提供一个可在各种环境和 applications 中使用的标准编程接口。DOM 设计为可与任何编程语言一起使用。为了提供精确、与语言无关的 DOM 接口规范,我们选择使用对象管理组(OMG)IDL [OMGIDL],该 IDL 在 CORBA 2.3.1 规范 [CORBA] 中定义。除 OMG IDL 规范外,我们还为 Java [Java] 和 ECMAScript [ECMAScript](一种基于 JavaScript [JavaScript] 和 JScript [JScript] 的行业标准脚本语言)提供 language bindings

注意: OMG IDL 仅作为一种语言无关、实现中立的方式来指定 interfaces。本可使用其他多种 IDL(如 [COM]、[JavaIDL]、[MIDL] 等)。通常,IDL 是为特定计算环境设计的。文档对象模型可以在任何计算环境中实现,不要求使用这些 IDL 通常关联的对象绑定运行时。

文档对象模型是什么

DOM 是面向文档的编程 API。它基于一种对象结构,该结构与它所 models 的文档结构极为相似。例如,考虑下面这张从 HTML 文档中摘取的表格。

      <TABLE>
      <TBODY> 
      <TR> 
      <TD>Shady Grove</TD>
      <TD>Aeolian</TD> 
      </TR> 
      <TR>
      <TD>Over the River, Charlie</TD>        
      <TD>Dorian</TD> 
      </TR> 
      </TBODY>
      </TABLE>
   

下面是该示例表格的 DOM 的图形化表示:


graphical representation of the DOM of the example table
示例表格的 DOM 图形化表示

在 DOM 中,文档具有非常类似树形的逻辑结构;更精确地说,它类似于“森林”或“树丛”,可以包含多个树。每个文档包含零个或一个 doctype 节点、一个根元素节点以及零个或多个注释或处理指令;根元素充当该文档元素树的根。然而,DOM 并未规定文档必须以树或树丛的形式 实现,也未规定对象之间的关系必须如何实现。DOM 是一种逻辑模型,可采用任何方便的方式实现。在本规范中,我们使用术语 structure model 来描述文档的树形表示。当提及通过“树遍历”方法(不包括属性)可以访问的信息项的安排时,也使用“树”一词。DOM 结构模型的一个重要属性是 structural isomorphism:如果使用任意两个 Document Object Model 实现来创建同一文档的表示,它们将生成相同的结构模型,从而符合 XML 信息集 [Infoset]。

注意:根据用于构建 DOM 的解析器不同,可能会出现一些差异。例如,如果解析器丢弃元素内容中的空白字符,则 DOM 中可能不包含这些空白。

之所以选择 “Document Object Model” 这一名称,是因为它在传统面向对象设计意义上是一个 “object model”:文档通过对象进行建模,且该模型不仅涵盖文档的结构,还包括文档的行为以及构成文档的对象。换言之,上图中的节点并不表示数据结构,而是表示具备功能和身份的对象。作为对象模型,DOM 明确了…

SGML 文档的结构传统上是由抽象的 data model 表示,而非对象模型。在抽象的 data model 中,模型围绕数据本身展开。面向对象的编程语言则将数据封装在对象中,隐藏数据本身,防止直接的外部操作。这些对象所关联的函数决定了如何操作对象,它们是对象模型的一部分。

文档对象模型不是

本节旨在通过将 DOM 与其他可能看起来相似的系统区分开来,使读者对 DOM 有更精确的理解。

文档对象模型的来源

DOM 最初作为一种规范出现,旨在使 JavaScript 脚本和 Java 程序在 Web 浏览器之间具有可移植性。“动态 HTML”是文档对象模型的直接前身,最初主要被视为浏览器相关的技术。然而,当 W3C 成立 DOM 工作组时,来自其他领域的厂商也加入进来,包括 HTML/XML 编辑器和文档库等。这些厂商中有些早在 XML 出现之前就已经使用 SGML;因此,DOM 受到了 SGML 树丛(Groves)和 HyTime 标准的影响。一些厂商还为 SGML/XML 编辑器或文档库开发了自己的对象模型,这些模型同样对 DOM 产生了影响。

实体与 DOM 核心

在基本的 DOM 接口中,没有表示实体的对象。数值字符引用以及 HTML 与 XML 中的预定义实体会被对应的单个字符所替代。例如,在下面的例子中:

        <p>This is a dog &amp; a cat</p>        
     

“&amp;” 将被替换为字符 “&”,并且 P 元素中的文本将形成一个连续的字符序列。由于数值字符引用和预定义实体在 CDATA 区段以及 HTML 中的 SCRIPT 与 STYLE 元素内不被识别为实体,它们不会被替换为所指的单个字符。如果上述示例被放在 CDATA 区段中,“&amp;” 将不会被替换为 “&”;同样,<p> 也不会被识别为起始标签。普通实体(内部和外部)的表示在 DOM Level 1 的扩展(XML)接口中定义 [DOM Level 1]。

注意:当文档的 DOM 表示被序列化为 XML 或 HTML 文本时,应用程序需要检查文本数据中的每个字符,判断是否必须使用数值实体或预定义实体进行转义。如果未进行此检查,可能导致生成的 HTML 或 XML 非法。此外,implementations 应注意,如果序列化到的字符集(“charset”)未能完整覆盖 ISO 10646,而标记或 CDATA 区段中出现该字符集不支持的字符,则序列化可能会失败。

符合性

本节说明了 DOM Level 2 的不同合规级别。DOM Level 2 包含 14 个模块。可以整体符合 DOM Level 2,也可以仅符合其中的某个模块。

如果实现支持本文件中定义的 Core 模块(参见 Fundamental Interfaces),则称其为 DOM Level 2 合规实现。如果实现支持某个 DOM Level 2 模块的全部接口及其语义,则认为它符合该模块。

以下是 DOM Level 2.0 的完整模块列表以及它们使用的特性。特性名称不区分大小写。

核心模块
定义特性 “Core”
XML 模块
定义特性 “XML”
HTML 模块
定义特性 “HTML”。(参见 [DOM Level 2 HTML])

注意:截至出版时,该 DOM Level 2 模块尚未成为 W3C 推荐标准。

视图模块
在 [DOM Level 2 Views] 中定义特性 “Views”
样式表模块
在 [DOM Level 2 Style Sheets] 中定义特性 “StyleSheets”
CSS 模块
在 [DOM Level 2 CSS] 中定义特性 “CSS”
CSS2 模块
在 [DOM Level 2 CSS] 中定义特性 “CSS2”
事件模块
在 [DOM Level 2 Events] 中定义特性 “Events”
用户界面事件模块
在 [DOM Level 2 Events] 中定义特性 “UIEvents”
鼠标事件模块
在 [DOM Level 2 Events] 中定义特性 “MouseEvents”
变异事件模块
在 [DOM Level 2 Events] 中定义特性 “MutationEvents”
HTML 事件模块
在 [DOM Level 2 Events] 中定义特性 “HTMLEvents”
范围模块
在 [DOM Level 2 Range] 中定义特性 “Range”
遍历模块
在 [DOM Level 2 Traversal] 中定义特性 “Traversal”

DOM 实现不得在 hasFeature(feature, version) method 中对该特性返回 "true",除非实现符合相应模块。所有在 DOM Level 2.0 中使用的特性的 version 号均为 “2.0”。

DOM 接口与 DOM 实现

DOM 指定了一套可用于管理 XML 或 HTML 文档的接口。需要认识到这些接口是抽象的——类似于 C++ 中的“抽象基类”,它们用于指定访问和操作应用内部文档表示的方式。接口本身并不暗示特定的具体实现。每个 DOM 应用可以使用任何方便的内部表示来维护文档,只要支持本规范中列出的接口即可。一些 DOM 实现可能是已有的程序,这些程序在 DOM 规范出现之前就已经使用 DOM 接口访问软件。因此,DOM 被设计为避免实现上的依赖,尤其是,

  1. IDL 中定义的属性并不暗示必须具备特定数据成员的具体对象——在语言绑定中,它们会被映射为一对 get()/set() 方法,而非数据成员。只读属性在语言绑定中仅提供 get() 方法。
  2. DOM 应用程序可以提供本规范未列出的额外接口和对象,仍可视为符合 DOM 标准。
  3. 因为我们只规范接口,而不规定实际要创建的对象,DOM 无法知道实现时应调用哪些构造函数。一般而言,DOM 使用者会在 Document 类上调用 createX() 方法来创建文档结构,而 DOM 实现则在各自的 createX() 函数实现中自行创建这些结构的内部表示。

Level 1 接口已被扩展,以同时提供 Level 1 与 Level 2 的功能。

除 Java 与 ECMAScript 外的其他语言的 DOM 实现可以选择适合其语言与运行时环境的绑定方式。例如,某些系统可能需要创建一个从 Document 派生、包含新方法和属性的 Document2 类。

DOM Level 2 并未规定多线程机制。