本文介绍了DOM(文档对象模型)的结构和常规使用方法。通过本文,读者可以学会用DOM来对XML文档进行常见的处理。本文不讨论DOM的设计和实现技巧。
关键词:
XML DOM
概述
DOM(文档对象模型)是对XML数据的描述体系,它用树型结构的文档来保存XML数据。此外,DOM也包括了解析、处理XML数据的API。
在开始使用DOM之前,首先来了解一下它的结构。DOM整体上的结构是一个Composite模式。所有的XML单元,无论是文档、元素还是属性、文本,在DOM中都是一个Node(节点)。按照Composite模式的定义,每个Node都可以包容其他的Node,于是很轻松地就构成了一个树型结构。举一个简单的例子,下面的XML文档
<Book>
<Title>Effective C++</Title>
<Author>
<Name>Scott Meyers</Name>
<Gender>Male</Gender>
<Nationality>USA</Nationality>
</Author>
<Publisher>Addison-Wesley</Publisher>
</Book>
在DOM中的存储形式就会是这样:
既然已经了解了DOM文档的结构,下面就该学习如何操作DOM文档了。对于这样一个树型结构,比较重要的操作有文档生成、文档遍历、节点内容的处理(读取、修改等等)、节点本身的操作(插入、删除、替换等等)以及文档的序列化。下面,我们将逐个学习这些操作。
DOM文档的生成
用DOM处理XML数据,首先需要以下三个步骤:
1. 创建DocumentBuilderFactory。该对象将创建DocumentBuilder。
2. 创建 DocumentBuilder。 DocumentBuilder将对输入实际进行解析以创建Document对象。
3. 解析输入的XML,创建Document对象。
DocumentBuilderFactory是一个Singleton,所以不能直接new出来,应该调用DocumentBuilderFactory.newInstance()来得到DocumentBuilderFactory的实例。此外,DocumentBuilderFactory也是一个对象工厂(从名字就能看出),可以用它来创建DocumentBuilder。
通常会使用DocumentBuilder的parse方法返回一个Document对象(需要插一句:Document只是一个接口,用javax.xml.parsers.DocumentBuilder的parse方法得到的实际上是org.apache.crimson.tree.XmlDocument对象)。parse方法接受很多输入参数,包括File、InputStream、InputSource、String型的URI等等。parse方法会把输入源进行解析,在内存中生成一个DOM的树型结构——Document对象。
上面这三个步骤的常用代码如下:
File docFile = new File("orders.xml");
Document doc = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(docFile);
} catch (Exception e) { System.out.print("Problem parsing the file."); }
parse方法可能会抛出IOException或者SAXException,分别表示输入异常和解析异常。
在创建DocumentBuilder之前,可以为DocumentBuilder设置一些参数,调节它在生成Document时的行为方式。可控的参数包括:
l setCoalescing:确定解析器是否将 CDATA 节点转成文本,并将 CDATA 节点与其周围的文本节点合并(如果合适)。缺省值是 false。
l setExpandEntityReferences:确定是否扩展外部实体引用。如果为 true,则将外部数据插入文档。缺省值是 true。
l setIgnoringcomments:确定是否忽略文件中的注释。缺省值是 false。
l setIgnoringElementContentWhitespace:确定是否忽略元素内容中的空白(类似于浏览器处理 HTML 的方式)。缺省值是 false。
l setNameSpaceAware:确定解析器是否注意名称空间信息。缺省值是 false。
l setValidating:缺省情况下,解析器将不验证文档。将该参数设置为 true 以打开验证。
设置参数的语句如下:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(true);
DocumentBuilder db = dbf.newDocumentBuilder();
DOM文档的遍历
DOM采用了Composite模式。Node类是所有XML单元的基类,Element、Attr、Document等等都是Node的派生类。每个Node都可以包容其他的Node,也可以包容文本格式的内容。所以,DOM文档的遍历相当简单。
首先要获取文档的根节点。用Document.getDocumentElement()方法可以得到一个Element类型的对象,它就是文档的根节点。对于一个HTML文档,getDocumentElement()方法得到的就是<html>节点。
只要得到根节点,就可以用Node.getChildNodes()方法得到该节点的所有直接子节点,从而遍历整个树型结构。另外,可以用Node.hasChildNodes()方法判断一个节点是否叶节点,从而得到遍历算法的结束条件。getChildNodes()方法的返回值是NodeList对象,NodeList有两个方法:int getLength()和Node item(int),可以使用这两个方法来安全地访问其中的每个元素。
上面这种方法是深度优先的遍历(采用迭代算法),还有一种方法是广度优先的遍历算法,要使用的方法是getFirstChild()(获取第一个孩子节点)和getNextSibling()(获取下一个兄弟节点)。
处理元素的内容
首先必须搞清楚“节点(node)”和“元素(element)”的概念:在DOM中节点和元素不是等价的。“元素”是指一对标记(tag)及其内部包含的字符串值的总和,例如下面这就是一个元素:
<Country>
China
</Country>
但是它却不是一个节点,而是两个。第一个节点是<Country>节点,它的值是null;第二个节点是一个文本节点(节点名是#text),它的值是"China\n"。文本节点是<Country>节点的子节点。
所以,要处理一个元素的内容时,需要两个步骤:
1. 找到代表该元素的节点;
2. 处理该节点的第一个子节点;
只要知道某个元素的名称,就可以用Element.getElementsByTagName(String name)方法来找到所有代表该元素的节点。getElementsByTagName方法会自动遍历整个树型结构,将找到的节点全部保存在一个NodeList中返回。由于DOM的树型结构是建立在内存中的,所以这个操作不会太慢。找到节点之后,用Node.getFirstChild()方法就可以得到代表该元素值的文本节点,用Node.setNodeValue(String)方法就可以修改节点的值。
处理其他类型节点的内容
如果要访问的节点是属性节点(Node.getNodeType()==ATTRIBUTE_NODE),则可以通过getAttributes()方法获得节点中所有的属性。getAttributes方法会返回一个NamedNodeMap型的对象,这是一个名-值映射表,可以通过String型的名称来随机访问,也可以通过int型的顺序号来顺序访问。Attr类(属性节点)有getValue()和setValue()两个accessor,用于访问属性的值。
节点共有12种不同的类型,这里只介绍了元素节点和属性节点这两种最常用的,其他的就要自己查帮助了。Node有一个getNodeType()方法,会返回short型值,从而判断一个对象的真实类型,起到RTTI的作用。下面是getNodeType()方法所有可能的返回值:
public static final short ELEMENT_NODE = 1;
public static final short ATTRIBUTE_NODE = 2;
public static final short TEXT_NODE = 3;
public static final short CDATA_SECTION_NODE = 4;
public static final short ENTITY_REFERENCE_NODE = 5;
public static final short ENTITY_NODE = 6;
public static final short PROCESSING_INSTRUCTION_NODE = 7;
public static final short COMMENT_NODE = 8;
public static final short DOCUMENT_NODE = 9;
public static final short DOCUMENT_TYPE_NODE = 10;
public static final short DOCUMENT_FRAGMENT_NODE = 11;
public static final short NOTATION_NODE = 12;
节点的处理
对于树型数据结构,常见的节点处理就是节点的插入、删除和替换。DOM为这些操作提供了非常简单易用的API。
插入节点可以用Node.appendChild(Node),也可以用Node.insertBefore(Node newChild, Node refChild);删除节点可以用Node.removeChild(Node oldChild);替换节点可以用Node.replaceChild(Node newChild, Node oldChild)。DOM会自动调整树型结构,删除、替换的操作还会返回oldChild这个节点,非常方便。
文档(Document)也是一个节点(Node),所以也可以把节点直接插入到文档中。不过要注意:只有该文档创建出的节点才能插入到该文档中,否则会引发WRONG_DOCUMENT_ERR异常。创建节点使用Document.createXxxx方法。可以用cloneNode(boolean deep)方法来克隆一个节点,用boolean型的参数决定是否深度拷贝,但是克隆出的节点也不能插入别的文档中。另外,可以用Document.importNode(Node importedNode, boolean deep)方法来引入别的文档中的节点。
需要处理元素的属性时,可以用Element.setAttributeNode(Attr newAttr)来插入属性,用Element.removeAttribute(String name)来删除不需要的属性。如果属性有同名的,可以用Element. removeAttributeNode(Attr oldAttr)来指定删除某一个属性节点。
文档的序列化
每个Element都覆盖了toString方法,所以只要指定某一个Element作为根,再调用它的toString方法,它就会递归得到其下的整个树型结构,并转换成String型对象。只要把这个String型对象输出到指定的设备上,就可以得到XML文档,非常方便。下面这段代码会生成一个新的HTML文档(HTML可以说是XML的子集),并在标准输出设备上输出。
Document newdoc = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
newdoc = db.newDocument();
} catch(Exception e){};
Element head = newdoc.createElement("Head");
Element title = newdoc.createElement("Title");
title.appendChild(newdoc.createTextNode("Document created by DOM"));
head.appendChild(title);
Element body = newdoc.createElement("Body");
body.appendChild(newdoc.createTextNode("This is a test document"));
Element newroot = newdoc.createElement("Html");
newroot.appendChild(body);
newroot.insertBefore(head, body);
newdoc.appendChild(newroot);
System.out.println(newroot);
总结
DOM在内存中生成树型结构来处理XML数据,在处理速度和方便性上有优势,但是比较耗存储空间。如果XML文档比较大的话,解析过程可能会需要比较长的时间
分享到:
相关推荐
DOM4J是一个强大的Java库,专门用于处理XML文档。它提供了灵活且高效的API,使得XML的解析、创建、修改和查询变得简单。DOM4J的名字来源于“Document Object Model for Java”,它采用面向对象的设计思想,提供了对...
DOM Inspector是Mozilla Firefox的一个扩充套件,官方中文版上称之为DOM观察器,在安装Mozilla Firefox时,可以在自订安装中选择是否安装DOM Inspector,如果在安装Mozilla Firefox时没有选择自订安装以安装DOM ...
DOM4J是一个强大的Java库,专门用于处理XML文档。它提供了灵活、高效的API,使得XML的解析、创建、查询和修改变得更为简单。在本文中,我们将深入探讨DOM4J 1.6.1版本的安装及其在Maven项目中的应用。 首先,DOM4J...
为了处理XML文档,有三种主要的解析方式:DOM、SAX和DOM4J。每种方法都有其特点和适用场景,下面将详细介绍这三种解析方式。 1. DOM(Document Object Model) DOM解析器将整个XML文档加载到内存中,构建一个树形...
在Java中,解析XML文件是常见的任务,通常有DOM(Document Object Model)和DOM4J两种方式。下面我们将详细探讨这两种解析方法。 DOM解析方式是将整个XML文件加载到内存中,形成一棵DOM树,每个节点代表XML文档的一...
标题提及的"dom4j_1.6.1.jar"和"dom4j_2.1.0.jar"是两个不同版本的DOM4J库的Java档案文件,DOM4J是一个非常流行的Java XML API,用于处理XML文档。这两个版本的差异在于功能、性能优化和可能存在的bug修复。描述中...
DOM4J是一个强大的Java库,专门用于处理XML文档。它提供了灵活、高效的API,使得XML的解析、创建、修改和查询变得简单。这次我们有两个版本的DOM4J库:1.6.1和2.0.0-ALPHA。这两个版本在功能、性能和API设计上都有所...
常见的 XML 解析器有 DOM、SAX、JDOM 和 DOM4J 等。每种解析器都有其特点和优缺,选择合适的解析器对应用程序的性能和开发效率有很大影响。 1. DOM 解析器 DOM(Document Object Model)是 W3C 官方标准,用于表示...
DOM 和 BOM 的使用 DOM(Document Object Model)和 BOM(Browser Object Model)是前端开发中两个基础概念。DOM 是一个文档对象模型,它将 HTML 文档抽象为一个树形结构,允许开发者通过 JavaScript 操作文档的...
DOM4J是一个强大的Java库,专门用于处理XML文档。它提供了灵活且高效的API,使得XML的解析、创建、修改和查询变得简单。DOM4J的名字来源于“Document Object Model for Java”,但它并不仅仅是一个DOM实现,它还包含...
DOM4J 2.1.1 是一个针对Java平台的高效、开源的XML处理库,其全称为“Document Object Model for Java”。这个库提供了一系列强大的API,使得开发人员能够轻松地解析、创建、修改和操作XML文档。XML(eXtensible ...
DOM4J是一个强大的Java库,专门用于处理XML文档。它提供了灵活且高效的API,使得XML的解析、创建、查询和修改变得简单。这个压缩包包含了DOM4J的完整版本,适用于那些希望在Java项目中使用DOM4J进行XML操作的开发者...
在IT领域,尤其是在Web开发和数据抓取方面,"谷歌获取网页DOM的插件"是一种非常实用的工具。DOM(Document Object Model)是HTML和XML文档的结构化表示,它将网页内容作为树形结构处理,使得我们可以方便地通过...
赠送jar包:dom4j-2.1.1.jar; 赠送原API文档:dom4j-2.1.1-javadoc.jar; 赠送源代码:dom4j-2.1.1-sources.jar; 赠送Maven依赖信息文件:dom4j-2.1.1.pom; 包含翻译后的API文档:dom4j-2.1.1-javadoc-API文档-...
《深入解析DOM4J——基于Java的XML处理框架》 DOM4J,作为一个强大的Java XML API,是处理XML文档的主流工具之一。它提供了一套简单而高效的方式来操作XML文档,包括读取、写入、修改和遍历XML结构。在Java开发中,...
DOM4J 的使用 DOM4J 是一个开源的 XML 解析包,由 dom4j.org 出品,应用于 Java 平台,采用了 Java 集合框架并完全支持 DOM、SAX 和 JAXP。DOM4J 的主要特点是使用大量的接口,所有主要接口都在 org.dom4j 里面定义...
3. **遍历DOM**:可以轻松地遍历DOM树,获取元素、属性等信息。 4. **修改DOM**:可以添加、删除、修改HTML元素及其属性。 5. **提取数据**:支持提取文本、HTML、属性值等数据。 三、基本用法 1. **加载HTML**...
在Vue框架中,页面动态更新是非常常见的需求,但有时候开发者可能会遇到在页面上进行DOM操作不生效的问题。这种情况通常发生在某些数据更新之后,但直接进行DOM操作时,并没有取得预期效果。Vue使用的是虚拟DOM...
赠送jar包:dom4j-2.1.1.jar; 赠送原API文档:dom4j-2.1.1-javadoc.jar; 赠送源代码:dom4j-2.1.1-sources.jar; 赠送Maven依赖信息文件:dom4j-2.1.1.pom; 包含翻译后的API文档:dom4j-2.1.1-javadoc-API文档-...