# 何时使用 DOM

> 原文： [https://docs.oracle.com/javase/tutorial/jaxp/dom/when.html](https://docs.oracle.com/javase/tutorial/jaxp/dom/when.html)

最重要的是，文档对象模型标准是为文档（例如，文章和书籍）而设计的。此外，JAXP 1.4.2 实现支持 XML Schema，这可能是任何给定应用程序的重要考虑因素。

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

从一开始，DOM 就意味着语言中立。因为它设计用于 C 和 Perl 等语言，所以 DOM 不利用 Java 的面向对象功能。除了文档和数据之间的区别之外，这一事实还有助于解释处理 DOM 与处理 JDOM 或 dom4j 结构的方式不同。

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

## 文件和数据

DOM 中使用的文档模型与 JDOM 或 dom4j 中使用的数据模型之间的主要出发点在于：

*   层次结构中存在的节点类型
*   混合内容的容量

数据层次结构中“节点”的构成差异主要在于这两个模型的编程差异。但是，混合内容的容量比其他任何因素都更能说明标准定义节点的方式的差异。因此，我们首先检查 DOM 的混合内容模型。

## 混合内容模型

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

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

`&lt;sentence&gt;This is an &lt;bold&gt;important&lt;/bold&gt; idea.&lt;/sentence&gt;`

DOM 节点的层次结构看起来像这样，其中每一行代表一个节点：

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

```

请注意，句子元素包含文本，后跟子元素，后跟其他文本。它是定义混合内容模型的文本和元素的混合。

## 节点类型

为了提供混合内容的容量，DOM 节点本质上非常简单。在前面的例子中，第一个元素的“内容”（它的值）只是简单地标识它的节点类型。

这个事实通常会引发 DOM 的首次使用者。导航到`&lt;句子&gt;之后`节点，他们要求节点的“内容”，并希望得到一些有用的东西。相反，他们所能找到的只是元素的名称，`句子`。

* * *

**注 -** DOM 节点 API 定义 `nodeValue（）`， `nodeType（）`和 `nodeName（）`方法。对于第一个元素节点， `nodeName（）`返回`句子`，而 `nodeValue（）`返回 null。对于第一个文本节点， `nodeName（）`返回 `#text` ， `nodeValue（）`返回“`这是`”。重要的是元素的**值**与**含量**不同。

* * *

在上面的例子中，要求句子的“文本”是什么意思？根据您的应用，以下任何一项都可能是合理的：

*   这是个
*   这是一个想法。
*   这是一个重要的想法。
*   这是&lt; bold&gt;重要&lt; / bold&gt;理念。

## 一个更简单的模型

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

尽管 JDOM 和 dom4j 允许具有混合内容的元素，但它们并非主要针对此类情况而设计。相反，它们的目标是 XML 结构包含数据的应用程序。

数据结构中的元素通常包含文本或其他元素，但不包含两者。例如，这里有一些表示简单地址簿的 XML：

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

```

* * *

**注 -** 对于非常简单的 XML 数据结构，您也可以使用版本 1.4 中 Java 平台内置的 regular-expression 包（ `java.util.regex` ）。

* * *

在 JDOM 和 dom4j 中，导航到包含文本的元素后，可以调用 `text（）`等方法来获取其内容。但是，在处理 DOM 时，必须检查子元素列表，以便将节点文本“放在一起”，如前所述 - 即使该列表只包含一个项目（TEXT 节点）。

因此，对于简单的数据结构（如地址簿），您可以使用 JDOM 或 dom4j 来节省一些工作。即使数据在技术上“混合”但是对于给定节点总是存在一个（且仅一个）文本段，使用这些模型中的一个可能是有意义的。

以下是这种结构的示例，它也可以在 JDOM 或 dom4j 中轻松处理：

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

```

在这里，每个条目都有一些识别文本，后跟其他元素。利用这种结构，程序可以导航到一个条目，调用 `text（）`以找出它所属的人，并处理`&lt; email&gt;` 子元素，如果它在正确的节点上。

## 增加复杂性

但是，为了让您充分了解在搜索或操作 DOM 时需要执行的处理类型，了解 DOM 可以包含的节点种类非常重要。

这是一个说明这一点的例子。它代表了这些数据：

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

```

该句子包含**实体引用** - 指向其他地方定义的实体的指针。在这种情况下，实体包含项目的名称。该示例还包含 CDATA 部分（未解释的数据，如 HTML 中的`&lt; pre&gt;` 数据）以及**处理指令**（`&lt;？...？&gt;` ），在这种情况下告诉编辑器在渲染文本时使用哪种颜色。

这是该数据的 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 中可能出现的节点类型。虽然您的应用程序可能在大多数情况下可以忽略其中的大多数，但真正强大的实现需要识别并处理它们中的每一个。

类似地，导航到节点的过程涉及处理子元素，忽略您不感兴趣的子元素并检查您所属的元素，直到找到您感兴趣的节点为止。

处理固定的内部生成数据的程序可以简化假设：数据结构中不存在处理指令，注释，CDATA 节点和实体引用。但是，真正强大的应用程序可以处理各种数据 - 尤其是来自外部世界的数据 - 必须准备好处理所有可能的 XML 实体。

（只要输入数据包含它所期望的简化 XML 结构，“简单”应用程序就会起作用。但是没有验证机制来确保不存在更复杂的结构。毕竟，XML 是专门为允许它们而设计的。 ）

为了更健壮，DOM 应用程序必须执行以下操作：

1.  搜索元素时：
    1.  忽略注释，属性和处理指令。
    2.  允许子元素不按预期顺序出现的可能性。
    3.  如果没有验证，则跳过包含可忽略空白区域的 TEXT 节点。
2.  为节点提取文本时：
    1.  从 CDATA 节点和文本节点中提取文本。
    2.  收集文本时忽略注释，属性和处理指令。
    3.  如果遇到实体引用节点或另一个元素节点，则递归（即，将文本提取过程应用于所有子节点）。

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

在[搜索节点](readingXML.html#ggdwa)和[获取节点内容](readingXML.html#ggdxv)的课程结束时，您需要执行这些功能所需的代码。目前，目标只是确定 DOM 是否适合您的应用程序。

## 选择你的模特

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

另一方面，对于完全成熟的文档和复杂的应用程序，DOM 为您提供了很大的灵活性。如果你需要使用 XML Schema，那么再次使用 DOM 是至关重要的 - 现在，至少。

如果您在开发的应用程序中处理文档和数据，那么 DOM 可能仍然是您的最佳选择。毕竟，在编写了用于检查和处理 DOM 结构的代码之后，为特定目的定制它是相当容易的。因此，选择在 DOM 中执行所有操作意味着您只需要处理一组 API，而不是两个。

此外，DOM 标准是内存文档模型的编码标准。它功能强大且功能强大，并且具有许多实现。对于许多大型安装而言，这是一个重要的决策因素，特别是对于需要最大限度地降低 API 更改所带来的成本的大型应用程序。

最后，即使地址簿中的文本今天可能不允许使用粗体，斜体，颜色和字体大小，有一天您可能想要处理这些事情。因为 DOM 几乎可以处理任何内容，所以选择 DOM 可以更容易地为您的应用程序提供面向未来的功能。