何时使用 DOM

首先,文档对象模型标准是为文档(例如,文章和书籍)设计的。另外,JAXP 1.4.2 实现支持 XML Schema,这对于任何给定的应用程序都是重要的考虑因素。

另一方面,如果您正在处理简单的数据结构,并且如果 XML Schema 不是计划的主要部分,那么您可能会发现,一种面向对象的标准(例如 JDOM 或 dom4j)更适合于你的 Object。

从一开始,DOM 就旨在与语言无关。因为它是为与 C 和 Perl 之类的语言一起使用而设计的,所以 DOM 没有利用 Java 的面向对象功能。这个事实,除了文档和数据之间的区别外,还有助于说明处理 DOM 与处理 JDOM 或 dom4j 结构不同的方式。

在本节中,我们将检查这些标准所基于的模型之间的差异,以帮助您选择最适合您的应用程序的模型。

文件与数据

DOM 中使用的文档模型与 JDOM 或 dom4j 中使用的数据模型之间的主要区别在于:

  • 层次结构中存在的节点类型

  • 混合内容的能力

构成数据层次结构中“节点”的不同主要是考虑了使用这两种模型进行编程的差异。但是,混合内容的功能比其他任何功能都更能说明标准定义节点的方式。因此,我们首先研究 DOM 的混合内容模型。

Mixed-Content Model

文本和元素可以在 DOM 层次结构中自由混合。这种结构在 DOM 模型中称为混合内容。

混合内容经常出现在文档中。例如,假设您要表示此结构:

<sentence>This is an <bold>important</bold> idea.</sentence>

DOM 节点的层次结构如下所示,其中每一行代表一个节点:

ELEMENT: sentence
   + TEXT: This is an
   + ELEMENT: bold
     + TEXT: important
   + TEXT: idea.

请注意,句子元素包含文本,后跟一个子元素,后跟其他文本。文本和元素的混合定义了混合内容模型。

节点类型

为了提供混合内容的容量,DOM 节点本质上非常简单。在前面的示例中,第一个元素的“内容”(其值)仅标识了它的节点类型。

通常,这个事实会引发 DOM 的首次用户。导航到\<sentence\>节点后,他们询问该节点的“内容”,并期望得到有用的东西。相反,他们只能找到元素名称sentence


注意- DOM 节点 API 定义了nodeValue\(\)nodeType\(\)nodeName\(\)方法。对于第一个元素节点,nodeName\(\)返回sentence,而nodeValue\(\)返回 null。对于第一个文本节点,nodeName\(\)返回\#text,而nodeValue\(\)返回“ This is an”。重要的一点是,元素的 值与其元素的 内容不同。


在上面的示例中,要求句子的“文本”是什么意思?根据您的应用程序,下列任何一项可能都是合理的:

  • 这是一

  • 这是一个主意。

  • 这是一个重要的想法。

  • 这是一个\ 重要\ 的想法。

更简单的模型

使用 DOM,您可以自由创建所需的语义。但是,还要求您执行实现这些语义所必需的处理。另一方面,诸如 JDOM 和 dom4j 之类的标准使执行简单操作变得更加容易,因为层次结构中的每个节点都是一个对象。

尽管 JDOM 和 dom4j 允许包含混合内容的元素,但它们并不是主要为这种情况而设计的。相反,它们针对 XML 结构包含数据的应用程序。

数据结构中的元素通常包含文本或其他元素,但不能同时包含两者。例如,以下是一些 XML,它们表示一个简单的通讯录:

<addressbook>
    <entry>
        <name>Fred</name>
        <email>fred@home</email>
    </entry>
      ...
</addressbook>

注意- 对于像这样的非常简单的 XML 数据结构,您还可以使用 1.4 版 Java 平台中内置的正则表达式包(java\.util\.regex)。


在 JDOM 和 dom4j 中,导航到包含文本的元素后,您将调用诸如text\(\)之类的方法来获取其内容。但是,在处理 DOM 时,必须检查子元素列表以将节点的文本“放在一起”,就像您在前面看到的那样-即使该列表仅包含一项(TEXT 节点)。

因此,对于简单的数据结构(例如地址簿),您可以使用 JDOM 或 dom4j 节省一些工作。即使在技术上“混合”了数据,也可以使用其中一种模型,但是给定节点始终只有一个(只有一个)文本段。

这是这种结构的示例,也可以在 JDOM 或 dom4j 中轻松处理:

<addressbook>
    <entry>Fred
        <email>fred@home</email>
    </entry>
      ...
</addressbook>

在这里,每个条目都有一点标识文本,后跟其他元素。通过这种结构,程序可以导航到一个条目,调用text\(\)找出它属于谁,并处理\<email\>子元素(如果它在正确的节点上)。

增加复杂性

但是,为了使您充分了解在搜索或操作 DOM 时需要进行的处理类型,重要的是要知道 DOM 可以包含的节点类型。

这是一个说明这一点的示例。它是此数据的表示形式:

<sentence>
    The &projectName; <![CDATA[<i>project</i>]]> is
    <?editor: red><bold>important</bold><?editor: normal>.
</sentence>

这句话包含一个“实体引用”-指向在其他地方定义的实体的指针。在这种情况下,实体包含项 Object 名称。该示例还包含一个 CDATA 节(未解释的数据,如 HTML 中的\<pre\>数据)以及 处理指令 (\<?\.\.\.?\>),在这种情况下,该值告诉编辑器呈现文本时使用哪种颜色。

这是该数据的 DOM 结构。它代表了健壮的应用程序应准备处理的结构类型:

+ ELEMENT: sentence
       + TEXT: The
       + ENTITY REF: projectName
        + COMMENT: 
        The latest name we are using
        + TEXT: Eagle
       + CDATA: <i>project</i>
       + TEXT: is
       + PI: editor: red
       + ELEMENT: bold
          + TEXT: important
       + PI: editor: normal

此示例描述了 DOM 中可能出现的节点类型。尽管您的应用程序可能大部分时间都可以忽略其中的大多数,但 true 可靠的实现需要识别并处理它们中的每一个。

同样,导航到节点的过程涉及处理子元素,忽略您不感兴趣的子元素并检查您自己的子元素,直到找到您感兴趣的节点。

一个处理固定的内部生成数据的程序可以做出简化的假设:数据结构中将不存在处理指令,注解,CDATA 节点和实体引用。但是必须准备好处理各种数据(尤其是来自外部世界的数据)的强大应用程序,以处理所有可能的 XML 实体。

(“简单”应用程序仅在 Importing 数据包含其期望的简化 XML 结构时才起作用.但是,没有验证机制可确保不存在更复杂的结构.毕竟,XML 是专门为允许它们而设计的.)

为了更强大,DOM 应用程序必须执行以下操作:

  • 搜索元素时:

  • 忽略 注解,属性和处理说明。

    • 允许子元素未按预期 Sequences 出现的可能性。

    • 如果不进行验证,则跳过包含可忽略空格的 TEXT 节点。

  • 为节点提取文本时:

  • 从 CDATA 节点以及文本节点中提取文本。

    • 收集文本时,请忽略 注解,属性和处理说明。

    • 如果遇到实体引用节点或另一个元素节点,请递归(即,将文本提取过程应用于所有子节点)。

当然,许多应用程序不必担心此类事情,因为它们看到的数据类型将受到严格控制。但是,如果数据可以来自各种外部来源,则应用程序可能需要考虑这些可能性。

本类即将在搜索节点获取节点内容中给出执行这些功能所需的代码。现在,目标只是确定 DOM 是否适合您的应用程序。

选择模型

如您所见,当您使用 DOM 时,即使是简单的操作(例如从节点获取文本)也需要花费一些编程时间。因此,如果您的程序处理简单的数据结构,那么 JDOM,dom4j 甚至 1.4 正则表达式包(java\.util\.regex)可能更适合您的需求。

另一方面,对于成熟的文档和复杂的应用程序,DOM 为您提供了很大的灵 Active。而且,如果您需要使用 XML Schema,那么至少现在还是要使用 DOM。

如果您在开发的应用程序中同时处理文档和数据,那么 DOM 可能仍然是您的最佳选择。毕竟,在编写了用于检查和处理 DOM 结构的代码之后,针对特定 Object 对其进行自定义非常容易。因此,选择在 DOM 中执行所有操作意味着您将只需要处理一组 API,而不是两个。

另外,DOM 标准是内存文档模型的统一标准。它功能强大且健壮,并且具有许多实现。对于许多大型安装而言,这是一个重要的决策因素,尤其是对于需要将 API 更改所导致的成本降至最低的大型应用而言。

最后,即使当今通讯录中的文本可能不允许使用粗体,斜体,颜色和字体大小,但总有一天您可能想要处理这些问题。由于 DOM 几乎可以处理您扔给它的任何内容,因此选择 DOM 可以使您的应用程序更容易过时。