DOM(Document Object Model)是XML文档的应用程序接口,它定义了对XML文档进行随机访问与操作的方法。DOM是一个与语言无关、与平台无关的标准接口规范。利用DOM,程序开发人员可以动态地创建XML文档,遍历文档结构,添加、修改、删除文档内容,改变文档的显示方式等。可以这样说,文档代表的是数据,而DOM则代表了如何去处理这些数据。

      DOM把一个XML文档映射成一个分层对象模型,而这个层次的结构,是一棵根据XML文档生成的节点树。DOM在对XML文档进行分析之后,不管这个文档有多简单或多复杂,其中的信息都会被转化成一棵对象节点树。在这棵节点树中,有一个根节点,其他所有的节点都是根节点的子节点。节点树生成之后,就可以通过DOM接口访问、修改、添加、删除树中的节点或内容了。

      对DOM树的操作,主要通过以下几个接口。

    1.Node接口

      Node接口在整个DOM树中具有举足轻重的地位,DOM接口中有很大一部分接口是从Node接口继承过来的,例如Document(根节点)、Element(元素)、Attr(属性)、Comment(注释)、Text(元素或属性的文本内容)等接口都是从Node继承过来的。在DOM树中,Node接口代表了树中的一个节点。Node接口的常用方法如下。

    • NodeList getChildNodes()

      返回此节点的所有子节点的NodeList。

    • Node getFirstChild()

      返回此节点的第一个子节点。

      返回此节点的最后一个子节点。

    • Node getNextSibling()

      返回此节点之后的节点。

    • Node getPreviousSibling()

      返回此节点之前的节点。

    • Document getOwnerDocument()

      返回与此节点相关的Document对象。

    • Node getParentNode(

      返回此节点的父节点。

    • short getNodeType()

      返回此节点的类型。

    • String getNodeName()

      根据此节点类型,返回节点名称。

    • String getNodeValue()

      前面已经提到,DOM中很多接口都是从Node接口继承的,所以Node接口拥有的方法这些接口都可以使用。但是这些从Node接口继承下来的接口又都各有特性,所以Node接口拥有的方法在各个子接口上的返回值含义不尽相同。例如,对于Element(元素接口)的getNodeType()的返回值为Node.ELEMENT_NODE常量,getNodeName()的返回值为标签名称,getNodeValue()的返回值为null。表4.1列出了nodeName、nodeValue 和 attributes 的值将根据接口类型的不同而不同,这对于XML解析的初学者而言是个难点,请大家务必结合后面的例子,深刻理解。

    表4.1 Node子接口属性值

    • String getTextContent()

      返回此节点的文本内容。

      根据此节点类型,设置节点值。

    • void setTextContent(String textContent)

      设置此节点的文本内容。

    • Node appendChild(Node newChild)

      将节点newChild添加到此节点的子节点列表的末尾。

    • Node insertBefore(Node newChild,Node refChild)

      在现有子节点refChild之前插入节点newChild。

    • Node removeChild(Node oldChild)

      从子节点列表中移除oldChild所指示的子节点,并将其返回。

    • Node replaceChild(Node newChild, oldChild)

      将子节点列表中的子节点oldChild替换为newChild,并返回oldChild节点。

    2.Document接口

      Document接口表示DOM树中的根节点,即对XML文档进行操作的入口节点。通过Document节点,可以访问到文档中的其他节点。Document接口的常用方法如下:

    • Element getDocumentElement()

      返回代表这个DOM树根节点的Element对象。

    • NodeList getElementsByTagName(String tagname)

      按文档顺序返回包含在文档中且具有给定标记名称的所有Element的NodeList。

    3.NodeList接口

      NodeList接口提供了对节点集合的抽象定义,包含了一个或多个节点(Node)的有序集合。NodeList接口的常用方法如下。

    • int getLength()

      返回有序集合中的第index个项。

      使用DOM解析XML文档的步骤如下。

      (1)创建解析器工厂,即DocumentBuilderFactory对象。

      (2)通过解析器工厂获得DOM解析器,即DocumentBuilder对象。

      (3)解析指定XML文档,得到DOM节点树。

      (4)对DOM节点树进行操作,完成对XML文档的增删改查。

      下面使用DOM对之前编写的用于存放“租车系统”车辆信息的vehicles.xml文档进行解析,并输出“租车系统”中有几种类型的车,“租车系统”中有几辆卡车,并详细输出每辆卡车的id属性及详细信息,程序运行结果如图4.8所示。


    图4.8 使用DOM解析vehicles.xml

      具体代码如下(需要大家认真阅读代码中的注释,理解含义):

      在上面的代码中,用到了根节点、属性节点、元素节点和文本节点,它们的nodeName、nodeValue和attributes 的值含义各不相同,需要注意。

      相比于DOM,SAX(Simple API for XML)是一种速度更快、更有效的解析XML文档的方法。它不需要一次性建立一个完整的DOM树,而是读取文档时激活事件进行处理。

      DOM是W3C标准,提供的是标准的解析方式,但其解析效率一直不尽如人意。这是因为DOM解析XML文档时,把所有内容一次性装载入内存,并构建一个驻留在内存中的节点树。如果需要解析的XML文档过大,或者只对该文档中的一部分内容感兴趣,这种做法就会引起性能问题。