(Step one)利用JAVA进行XML编程

刚接触Java的XML编程,而又无从所起的人,可以参考一下这篇资料,本文来自IBM《利用Java技术进行XML编程,第一部分》,还有第二第三部分,不过暂时没找到,有兴趣的话可以去Google查找一下,还有介绍一下,IBM中国是个不错的Java学习网站。下面开始正文内容的介绍:(由于文章较长,这里分为上下两部分)

 

主菜单(上部分)

一、简介
二、解析器基础
三、文档对象模型(DOM)
四、Simple API for XML(SAX)
五、JDOM
六、结束语

 

-----------------------------------------------------------------------------------------------------

Chapter 1 简介

 

关于本教程

 

    在过去几年中,XML 已经成为一种通用的数据格式。这篇经过修订的教程将向您介绍 Java 语言中处理 XML 文档最常用的编程接口。

    最普通的 XML 处理工作是 解析 XML 文档。解析包括读取 XML 文档并确定其结构和内容。XML 编程的一个好处是可以使用开放源代码的、免费的 XML 解析器读取 XML 文档。本教程主要讨论创建解析器对象、要求解析器处理 XML 文件、处理解析结果。如您所料,可以使用不同的方式完成这类常见的任务;我将分析所涉及到的标准以及什么时候应该使用这种或那种方法。

 

编程接口

    为了简化编写处理 XML 的 Java 程序,已经建立了多种编程接口。这些接口或者由公司定义,或者由标准体或用户组定义,以满足 XML 程序员的需要。本教程将讨论以下接口:

  • Document Object Model (DOM,文档对象模型),Level 2
  • Simple API for XML (SAX), Version 2.0
  • JDOM, Jason Hunter 和 Brett McLaughlin 创立的一种简单 Java API
  • Java API for XML Processing (JAXP)

    这四种接口中前三个(DOM、SAX 和 JDOM)定义了如何访问与表示 XML 文档的内容。JAXP 包含创建解析器对象的类。要创建 DOM 或 SAX 解析器,您需要使用 JAXP。如果使用 JDOM,JDOM 库将在幕后使用 JAXP 为您创建一个解析器。总之:

  • 使用 DOM、SAX 或 JDOM 处理 XML 文档的内容。
  • 如果使用 DOM 或 SAX,则使用 JAXP 创建解析器。
  • 如果使用 JDOM,则 JDOM 库为您创建解析器。

    我将考察上述每种 API 的设计目标、长处和缺点,同时还涉及到一点它们的历史以及创建这些 API 的标准体。

 

关于例子

 

    本教程中包含多个使用 DOM、SAX 和 JDOM API 的示例程序。所有这些程序都使用 XML 标记的莎士比亚十四行诗。十四行诗的结构如下:

<sonnet>
  <author>
    <lastName>
    <firstName>
    <nationality>
    <yearOfBirth>
    <yearOfDeath>
  </author>
  <lines>
    [14 <line> elements]
  </lines>
</sonnet>
          

完整的例子请参阅 和   (下载后使用文本编辑器查看)。

【在以后的文章你会看到我对该例子的具体操作】

 

设置机器

 

    在运行这些例子之前,需要对您的机器作一些设置。(假设您知道如何编译和运行 Java 程序,并了解如何设置 CLASSPATH 变量。)

  1. 首先请访问 Apache XML Project (http://xml.apache.org/xerces2-j/) 上的 Xerces XML 解析器主页。您也可以直接去 下载页面 (http://xml.apache.org/xerces2-j/download.cgi)。
  2. 解压从 Apache 下载的文件。根据解析器版本的不同,这样将会创建名为 xerces-2_5_0 或者类似名称的目录。所需要的 JAR 文件(xercesImpl.jarxml-apis.jar)应该出现在 Xerces 根目录下。
  3. 访问 JDOM 项目站点 并下载最新版本的 JDOM (http://jdom.org/)。
  4. 解压从 JDOM 下载的文件,这样将建立名为 jdom-b9 或者类似名称的目录。所需要的 JAR 文件(jdom.jar)应该在 build 目录中。
  5. 最后请下载本教程的示例压缩文件 ,并解压该文件。
  6. 把当前目录 (.)、xercesImpl.jarxml-apis.jarjdom.jar 添加到 CLASSPATH 变量中。

最笨的家伙

 

 

(这篇传记是作者的女儿 Lily Castle Tidwell 写的。)

我爸爸叫 Doug Tidwell。他有一头黑发,戴着眼镜。他有六英尺高,眼睛是棕色的。

爸爸喜欢和我玩传球游戏。他喜欢跑,跑得很快。他自行车骑得很好,他的自行车是蓝色的。

我爸爸的工作是旅行。他多次到中国。他曾经爬上中国的长城,还得到了证书。

我爱你,爸爸!

附记 每一天中都有一个 d,你真笨。

 

你可以通过 dtidwell@us.ibm.com 和作者 Doug Tidwell 联系。

 

 

---------------------------------------------------------------------------------------

Chapter 2 解析器基础

 

基础

 

XML 解析器是读取 XML 文档并分析其结构的一段代码。这一部分将介绍 XML 解析器是如何工作的。我将讨论不同类型的 XML 解析器以及何时使用它们。

本教程后面的章节将讨论如何创建解析器以及如何处理解析器给出的结果。

 

如何使用解析器

 

我将在后面的章节对此详细讨论,一般而言使用解析器需要以下步骤:

  1. 创建一个解析器对象
  2. 使解析器指向您的 XML 文档
  3. 处理结果

显然第三步最为复杂。一旦知道了 XML 文档的内容,比方说,您可能希望生成一个 Web 页面、创建一个订单或者做一个饼图。考虑到 XML 文档所含数据的多样性,编写一个应用程序处理所有可能的输入是一项艰巨的任务。所幸的是,这里讨论的常见 XML 解析工具使这项工作大大简化了。

 

解析器的类型

 

解析器有不同的分类方法:

  • 验证和非验证解析器
  • 支持一种或多种 XML Schema 语言的解析器
  • 支持 Document Object Model (DOM) 的解析器
  • 支持 Simple API for XML (SAX) 的解析器

验证和非验证解析器

如果您刚刚接触 XML,应该了解有三种不同类型的 XML 文档:

  • 结构良好的文档:这类文档符合 XML 基本规则(属性必须放在引号中、标签必须正确嵌套等等)。
  • 有效文档:这些结构良好的文档同时还符合文档类型定义(DTD)或 XML Schema 所定义的规则。
  • 无效文档:所有其他文档。

比方说,如果您有一个 XML 文档符合 XML 的基本规则,那么它就是一个 结构良好的 文档。如果该文档还满足您的公司所定义的支出帐目文档规则,那么它也是 有效的

如果 XML 解析器发现 XML 文档不是结构良好的,XML Specification 要求解析器报告一个致命错误。但验证是一个不同的问题。验证解析器 在解析时验证 XML 文档,而 非验证解析器 不验证文档。换句话说,如果一个 XML 文档是结构良好的,那么非验证解析器并不关心文档是否符合 DTD 或模式中定义的规则,甚至不关心该文档是否有这样的规则。(多数验证解析器都默认关闭验证功能。)

 

为何使用非验证解析器?

那么为什么要使用非验证解析器呢?有两个很好的理由:速度和效率。XML 解析器读取 DTD 或者模式、建立规则引擎保证 XML 文档中的每个元素和属性都遵循这些规则,需要做大量的工作。如果您确信一个 XML 文档是有效的(比如,可能由一个数据库查询生成),那么就可以完全跳过验证。根据文档规则复杂程度的不同,这样可以节约相当可观的时间和内存。

如果您的代码不够健壮,它从 XML 文档中得到输入数据,并且该代码要求文档遵循特定的 DTD 或者模式,那么您可能就不得不验证所有的内容,不论代价多么高,多么浪费时间。

 

支持 XML Schema 语言的解析器

 

最初,XML 规范定义了 Document Type Definition (DTD,文档类型定义),作为定义何为有效文档的一种方式。多数 DTD 语法都来自 SGML,从发布的角度而非数据类型化的角度关注验证。此外,DTD 的语法不同于 XML 文档,这使得用户理解文档规则的语法非常困难。

为了解决这种局限性,万维网联盟(W3C)创建了 XML Schema 语言。XML Schema 允许以精确得多的方式定义有效的文档应该是什么样子。XML Schema 语言非常丰富,XML Schema 文档可能非常复杂。因此,支持 XML Schema 验证的 XML 解析器往往非常大。

此外,要知道 W3C XML Schema 语言并不是唯一的模式语言。一些解析器支持其他的 XML 模式语言,比如 RELAX NG 或者 Schematron (我将在以后的教程中讨论模式语言。)

 

文档对象模型(Document Object Model,DOM)

文档对象模型(DOM)是正式的 W3C 推荐标准。它定义了一个接口,使程序能够访问和更新 XML 文档的结构。如果一个 XML 解析器声称支持 DOM,就意味着它实现了该标准中定义的接口。

目前,有两个级别的 DOM 是正式的推荐标准,被明智地命名为 DOM Level 1 和 DOM Level 2。预计 DOM Level 3 将在 2004 年初正式发布。本教程中所讨论的 DOM 功能都是 DOM Level 1 的一部分,因此这些示例代码可用于任何 DOM 解析器。

 

从 DOM 解析器中得到什么

当使用 DOM 解析器解析一个 XML 文档时,您得到 一棵结构树,它表示 XML 文档的内容。所有的文本、元素和属性(以及其他的东西——后面简要地讨论)都在这个树结构中。DOM 还提供各种不同的功能,可用于分析和操作树的内容和结构。

要知道,有些事情是解析器 记录的。比如,属性和值之间的空格数量并不保存在 DOM 树中。从解析器的角度来看,下面三个属性是完全相同的:

  • type="common"
  • type =

    "common"
  • type='common'

DOM 没有提供任何方式使您可以了解原始文档是如何编码的。作为另一个例子,XML 解析器不会告诉您空元素是用一个标签还是两个标签编码的。(比如,一个 XHTML 水平线是写成 <hr/> 还是 <hr></hr>?)要求 XML 解析器记录的信息称为 XML Infoset (请参阅 参考资料)。

 

Simple API for XML (SAX)

Simple API for XML (SAX) API 是处理 XML 文档内容的一种替代方法。它的设计目标是更少的内存占用,但是把更多的工作交给了程序员。SAX 和 DOM 是互补的,有各自的适用环境。

作为一个 事实上的 标准,SAX 最初由 David Megginson 开发,吸收了 Internet 上许多用户的想法。完整的 SAX 标准请参阅 参考资料。您的解析器文档可能也描述了 SAX 标准。

 

从 SAX 解析器得到什么

当使用 SAX 解析器解析一个 XML 文档时,解析器在读取文档的过程中会生成一系列的事件。至于如何处理这些事件则取决于您。下面列出了一小部分您在 XML 文档时可能遇到的事件:

  • startDocument 事件。
  • 对于每个元素,在元素开始时有 startElement 事件,元素结束时有 endElement 事件。
  • 如果元素包含内容,对于文本将出现 characters 事件,对于子元素将出现 startElementendElement 事件,依此类推。
  • endDocument 事件。

和 DOM 一样,SAX 解析器也忽略了某些细节,如属性出现的顺序。


JDOM

尽管 SAX 和 DOM 提供了许多有用的功能,对于程序员而言有些任务还是太复杂了。延续开源社群有需要就创建工具的历史传统,Java 技术专家 Jason Hunter 和 Brett McLaughlin 缔造了 JDOM,这个 Java 库极大简化了 XML 文档的处理。

和 DOM 类似,JDOM 也提供一个对象树表示 XML 文档,但是这些对象工作的方式对 Java 程序员更直观。要记住,JDOM 在背后包含使用普通 SAX 或 DOM 解析器的适配器;JDOM 对所有主要的(和几个次要的) Java XML 解析器都提供了适配器,因此不必担心您的 Java XML 解析器是否支持 JDOM。JDOM 在幕后使用一个解析器不需要您的干涉。

 

如何选择解析器

 

我将在后面对此详加讨论,一般说来以下情况应使用 DOM 解析器:

  • 需要详细了解文档的结构
  • 需要改变文档的结构(也许您需要对元素排序、增加新的元素等等)
  • 需要多次引用解析的信息

进一步推广,在以下情况中应使用 SAX 解析器:

  • 内存少(就是说您的 机器 没有太多内存)
  • 只需要 XML 文档中少量元素或属性
  • 解析的信息只使用一次

最后看一看 JDOM API。JDOM 的内存使用比 DOM少,但是不如 SAX 好。此外,如果您希望进行验证(本教程中不再展开讨论),JDOM 要求您设置底层的解析器,JDOM 本身不进行验证。就是说,如果 JDOM 能够完成您所需要的所有功能,而且速度满足您的需要,它可以简化您的编码工作。

 

-------------------------------------------------------------------

Chapter 3 文档对象模型

 

XML 结构的一种通用接口

DOM 是处理 XML 文档结构的一种接口。作为一个 W3C 项目,DOM 的设计目标是提供一组对象和方法,使程序员的工作更轻松。(从技术上讲,DOM 先于 XML;早期的 DOM 研究是对 HTML 文档而言的。)理想情况下,您应该能够编写一个应用程序使用一种 DOM 兼容的解析器处理 XML 文档,然后切换到另外一种 DOM 兼容的解析器而无需改变代码。

当使用 DOM 解析器解析一个 XML 文档时,您得到一个层次化的数据结构(DOM 树),它表示解析器在 XML 文档中发现的所有内容。然后您可以使用 DOM 函数操纵这棵树。您可以搜索树中的内容、移动分支、增加新的分支或者删除树的一部分。

如前所述,有些信息在 XML 解析器中是得不到的。个别解析器可能提供某些函数使您得到关于源文档的更多信息,但是这些函数不是 DOM 的一部分,不一定能用于其他解析器。更多信息请参阅 XML Infoset 标准(参阅 参考资料)。

 

了解 Node

 

您已经知道 DOM 解析器返回一个树状结构,这个 DOM 树包含一些 Node。从 Java 语言的角度看,Node 是一个接口。Node 是 DOM 的基本数据类型,DOM 树中的所有事物都是这种或那种类型的 Node

DOM Level 1 还定义了 Node 接口的几种子接口:

  • Element:表示源文档中的一个 XML 元素。
  • Attr:表示 XML 元素的一个属性。
  • Text:一个元素的内容。这意味着带有文本的元素包含文本节点孩子,元素的文本 不是 元素本身的一个属性。
  • Document:表示整个 XML 文档。解析的每个 XML 文档中有且只有一个 Document 对象。给定一个 Document 对象就可以找到 DOM 树的根,从这个根可以使用 DOM 函数读和操纵树。

其他的节点类型包括:Comment 表示 XML 文件中的注释、ProcessingInstruction 表示处理指令、CDATASection 表示 CDATA 节。您可能不需要这些节点类型,但如果需要它们就在那儿。

注意:“元素”和“标签”这两个词有不同的含义。元素 是指起始元素、结束元素以及两者之间的一切内容,包括属性、文本、注释以及子元素。标签 是一对<尖括号>和两者之间的内容,包括元素名和所有属性。比如 <p class="blue"> 是一个标签,</p> 也是;而 <p class="blue">The quick brown fox</p> 是一个元素。

 

常用 DOM 方法

处理 DOM 经常要用到以下方法:

  • Document.getDocumentElement():返回 DOM 树的根。(该函数是 Document 接口的一个方法,没有定义其他的 Node 子类型。)
  • Node.getFirstChild()Node.getLastChild():返回给定 Node 的第一个和最后一个孩子。
  • Node.getNextSibling()Node.getPreviousSibling():返回给定 Node 的下一个和上一个兄弟。
  • Element.getAttribute(String attrName):对于给定的 Element,返回名为 attrName 的属性的值。如果需要 "id" 属性的值,可以使用 Element.getAttribute("id")。如果该属性不存在,该方法返回一个空字符串 ("")。

第一个示例应用程序

 

第一个应用程序是 DomOne.java,这段简单的 Java 代码完成四件事:

  1. 扫描命令行得到 XML 文件名
  2. 创建一个解析器对象
  3. 告诉解析器解析命令行中给定的 XML 文件
  4. 遍历 DOM 结果树向标准输出打印各种节点的内容

仅此而已!尽管这段代码很难说吸引人,但可以示范基本的 DOM 方法以及如何调用它们。我将在后面讨论较难的技巧。现在我们看一看源代码。

 

第 1 步:扫描命令行

扫描命令行相对而言非常简单。只需要查看一个参数,并假定该参数是一个文件名或 URI。如果命令行中没有参数,则打印一个错误消息并退出:

public static void main(String argv[]) 
{
  if (argv.length == 0 ||
      (argv.length == 1 && argv[0].equals("-help")))
  {
    System.out.println("/nUsage:  java DomOne uri");
    System.out.println("   where uri is the URI of the XML " + 
                       "document you want to print.");
    System.out.println("   Sample:  java DomOne sonnet.xml");
    System.out.println("/nParses an XML document, then writes " + 
                       "the DOM tree to the console.");
    System.exit(1);
  }

  DomOne d1 = new DomOne();
  d1.parseAndPrint(argv[0]);
}

本教程中所有例子都用类似的代码处理命令行,此后我不再讨论这些代码。

[可以到资源下载区寻找该源代码]

 

第 2 步:创建一个解析器对象

假设命令行正确,下一个任务就是创建解析器对象。直接生成 XML 解析器需要实例化一个特定的类。使用 Apache XML 项目的 Xerces 解析器应该实例化 org.apache.xml.parsers.DOMParser 对象,使用其他的解析器需要实例化专用于那个解析器的类。显然,这种方法的缺点是切换解析器意味着您必须改变源代码。对于目前的解析器,您可以使用工厂类向代码隐藏所用的解析器类。

下面的代码说明了先创建一个工厂对象,然后工厂对象创建解析器:

public void parseAndPrint(String uri)
{
  Document doc = null;

  try
  {
   DocumentBuilderFactory dbf = 
      DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
    . . .

DocumentBuilder 对象是您的解析器。它实现了解析和处理 XML 文件所需要的全部 DOM 方法。注意,创建是在一个 try 语句中。创建解析器和解析文档的过程中有很多地方可能出问题,因此需要捕获可能发生的任何错误。

DocumentBuilderFactoryDocumentBuilder 类是在 JAXP 中定义的。我将简要地讨论一下 JAXP,如果您迫切希望了解它,请参阅 关于 JAXP 的简单说明

 

第 3 步:解析 XML 文件

 

现在您已经创建了解析器,告诉它解析哪个文件(或 URI)很简单:

doc = db.parse(uri);

就是这样!在第 2 步中,您可能还记得 doc 是一个 Document 接口的实例。换句话说,解析 XML 文件给您一个 Document 结构,您可以分析和确定 XML 文件包含的内容。

 

第 4 步:打印 DOM 树的内容

 

最后一项任务是打印 DOM 树的内容。因为 DOM 树中的一切事物都是这种或那种类型的 Node,您需要用递归的方法遍历并打印其中的内容。策略是调用该方法打印一个节点。该方法将打印那个节点,并对该节点的每个孩子调用自身。如果这些孩子还有孩子,该方法将对这些孩子调用自身。下面是一个例子:

  if (doc != null)
    printDomTree(doc);
  . . .
}

public void printDomTree(Node node) 
{
  int type = node.getNodeType();
  switch (type)
  {
    // print the document element
    case Node.DOCUMENT_NODE: 
    {
      System.out.println("<?xml version=/"1.0/" ?>");
      printDomTree(((Document)node).getDocumentElement());
      break;
    }

printDomTree 方法以一个 Node 作为参数。如果该 Node 是一个文档节点,就打印一个 XML 声明,然后对文档元素(包含文档其他内容的元素)调用 printDomTree。文档元素基本上总是有其他孩子,因此 printDomTree 也将对这些孩子调用自身。这种递归算法可以遍历整个 DOM 树并把内容打印到命令行中。

以下是 printDomTree 对元素节点的处理:

    case Node.ELEMENT_NODE: 
    {
      System.out.print("<");
      System.out.print(node.getNodeName());

      NamedNodeMap attrs = node.getAttributes();
      for (int i = 0; i < attrs.getLength(); i++)
        printDomTree(attrs.item(i));

      System.out.print(">");

      if (node.hasChildNodes())
      {
        NodeList children = node.getChildNodes();
        for (int i = 0; i < children.getLength(); i++)
          printDomTree(children.item(i));
      }

      System.out.print("</");
      System.out.print(node.getNodeName());
      System.out.print('>');

      break;
    }

对于元素节点,您需要打印一个左尖括号和结点名称。如果该元素有属性,就对每个属性调用 printDomTree。(技术上讲,这里可以使用 Attr.getName()Attr.getValue() 打印属性,我这样做是为了说明 DOM 树中的一切都是 Node。)一旦打印完所有的属性,就可以对该节点所包含的所有子元素再次调用 printDomTree。最后一步是在处理完所有的子元素之后打印结束元素。

处理属性节点和文本节点很简单。对于属性,需要输出一个空格、属性名、等号、开双引号、属性值和闭双引号。(这里简化了,属性值可以使用单引号和双引号,如果愿意您完全可以修正这个问题。)

处理文本节点最简单,只需要输出文本就可以了。以下是这两种节点类型的代码:

    case Node.ATTRIBUTE_NODE:
    {
      System.out.print(" " + node.getNodeName() + "=/"" +
                       ((Attr)node).getValue() + "/"");
      break;
    }

    case Node.TEXT_NODE: 
    {
      System.out.print(node.getNodeValue());
      break;
    }

尽管这里只是打印 DOM 树的内容,但多数围绕着 DOM 建立的 XML 应用程序都使用这种四个步骤的模式,第四步是递归处理例程。

完整的源代码请参阅 。

【源代码请到资源下载区下载】

 

运行 DomOne

毫无疑问,现在您正期待着运行这些代码。我假设您已经下载并安装了所需要的工具,否则请参阅 设置机器

在您解压示例文件的目录下键入:

javac DomOne.java

(记住 Java 语言是区分大小写的。)如果没有任何错误,键入:

java DomOne sonnet.xml

解析并显示文件 sonnet.xml

如果一切都和预期的一样,您应该看到类似这样的内容:

C:/xml-prog-java>java DomOne sonnet.xml
<?xml version="1.0" ?>
<sonnet type="Shakespearean">
  <author>
    <lastName>Shakespeare</lastName>
    <firstName>William</firstName>
    <nationality>British</nationality>
    <yearOfBirth>1564</yearOfBirth>
    <yearOfDeath>1616</yearOfDeath>
  </author>
  <title>Sonnet 130</title>
  <lines>
    <line>My mistress' eyes are nothing like the sun,</line>
    <line>Coral is far more red than her lips red.</line>
    <line>If snow be white, why then her breasts are dun,</line>
    <line>If hairs be wires, black wires grow on her head.</line>
    . . .
  </lines>
</sonnet>
     
     
删除空格
DomOne 生成的结果有很多空格,包括元素之间的空格。许多情况下,您可能并不关心这些空格。比方说,如果只是需要得到十四行诗的每行文本,用于缩进显示每个 <line> 元素的断行和空格并不重要。
要知道整个 DOM 树都是对象,所有的空格节点实际上也是 Java 对象。这些对象要占用内存,创建和销毁它们要花费处理时间,您的代码必须发现并忽略它们。显然,如果能够告诉解析器完全不必创建这类对象,就可以节约时间和内存,这总是值得追求的目标。
有幸的是,JAXP 的 DocumentBuilderFactory 提供了一种忽略不重要的空格的方法。setIgnoringElementContentWhitespace(boolean) 方法如它的名称所示,从内容中删除了空格节点。后面我将讨论它。

     
     
DomTwo
 
DomTwo 的源代码和 DomOne 的源代码相同,只有一个例外——setIgnoringElementContentWhitespace 方法。这是它的 parseAndPrint 方法:
public void parseAndPrint(String uri)
{
  Document doc = null;
  try
  {
    DocumentBuilderFactory dbf = 
    DocumentBuilderFactory.newInstance();
    dbf.setIgnoringElementContentWhitespace(true);
    DocumentBuilder db = dbf.newDocumentBuilder();
    doc = db.parse(uri);
    if (doc != null)
      printDomTree(doc);
    . . . 

注意,setIgnoringElementContentWhitespace()DocumentBuilderFactory 的一个方法,需要在工厂对象中设置该属性,然后要求根据所做的设置创建一个解析器。
如果编译并运行 DomTwo,您将得到一个较短的结果,但和前面相比可读性明显地下降了:
C:/xml-prog-java>java DomTwo sonnet.xml
<?xml version="1.0" ?>
<sonnet type="Shakespearean"><author><lastName>Shakespeare
</lastName><firstName>William</firstName><nationality>Brit
ish</nationality><yearOfBirth>1564</yearOfBirth><yearOfDea
th>1616</yearOfDeath></author><title>Sonnet 130</title><li
nes><line>My mistress' eyes are nothing like the sun,</lin
e><line>Coral is far more red than her lips red.</line><lin
e>If snow be white, why then her breasts are dun,</line><l
. . .

尽管输出结果不容易阅读,在不需要的时候去掉所有空格可以使您的代码更容易。如果您是为机器生成或处理 XML 文档,忽略空格可能是一种很好的方式。另一方面,如果您需要为人们格式化信息,空格可能就很重要。
DomTwo 的源代码请参阅 
      
      。

Document 节点
 

有时候 Document 节点会造成混淆。Document 节点不同于 XML 文档的根。比如,我们的 XML 十四行诗可能看起来是这样:

<?xml version="1.0" ?>
<!-- Does this sonnet have a name other than "Sonnet 130"? -->
<sonnet type="Shakespearean">
  <author>
  . . .
  </author>
  <title>Sonnet 130</title>
  <lines>
  . . .
  </lines>
</sonnet>
<!-- The title of Sting's 1987 album "Nothing Like the Sun" 
     came from this sonnet. -->

在这个例子中,Document 有三个孩子:第一个注释节点、<sonnet> 元素以及最后一个注释。文档根是 <sonnet> 元素,它和 Document 节点本身不同。

多数时候这种区别并不重要,但是要记住两者之间是不同的。

     
     

关于 JAXP 的简单说明

 


在开始讨论 SAX API 之前,我简单地说明一下 JAXP,即 Java API for XML Parsing。JAXP 规定了 DOM 和 SAX 标准没有定义的某些常见任务。具体而言,无论 DOM 还是 SAX 都没有定义创建解析器对象,DOM 也没有定义启用或关闭处理器的特性。

这里只讨论 JAXP 中的 javax.xml.parsers 包。(JAXP 规范的其他部分和转换 XML 文档有关,不在本教程的讨论范围之内。)javax.xml.parsers 包定义了四个类:

DocumentBuilderFactory
创建 DOM 解析器的工厂 API。使用这个工厂 API,您的代码不需要知道实现 DOM 的具体类。如果发现更好的 DOM 解析器,不必修改或重新编译您的代码就可以使用新的解析器。
DocumentBuilder
定义了从 DOM 解析器中获得 DOM Document 对象的 API。
SAXParserFactory
创建 SAX 解析器的工厂 API。和 DocumentBuilderFactory 类似,这个 API 使您不需要了解实现 SAX 解析器的类名。
SAXParser
包装 SAX XMLReader 类的 API。当 XMLReader 读取文件时生成 SAX 事件。

这一部分已经讨论了 DocumentBuilderFactoryDocumentBuilder 类,下一部分我将进一步考察 SAXParserFactorySAXParser

 

【下接……】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值