在开始使用 DOM 之前,了解它实际表示什么是值得的。DOM Document 是以层次结构组织起来的节点,或信息片段,的集合。这种层次结构允许开发 者浏览树来查找特定信息。通常,分析结构需要在完成任何工作之前装入整个 文档并且装入层次结构。
由于 DOM 是基于信息的层次结构,因此它被称为是基于树的。
对于极其大的文档,装入整个文档并对该文档进行解析会很慢且占用大量资源, 所以要用其它方式来处理数据。一些基于事件的模型,如 Simple API for XML(SAX),是工作在数据流之上,在数据流经过时对其进行处理。基于事件 的 API 消除了在内存中构建数据树的需要,但它不允许开发者实际更改原始 文档中的数据。
另一方面,DOM 还提供了一个 API,该 API 允许开发者为创建应用程序而在树的任何地方添加、编辑、移动或除去节点。
XML 中最常见的节点类型:
- Node: DOM 基本的数据类型。
- Element: 您将最主要处理的对象是 Element。
- Attr: 代表一个元素的属性。
- Text: 一个 Element 或 Attr 的实际内容。
- Document: 代表整个 XML 文档。一个 Document 对象通常也被称为一棵 DOM 树。
较不常见的节点类型:CData、注释、处理指令和文档片段:
- CData:“字符数据”的缩写
- 注释:注释包含有关数据的信息,通常应用程序会忽略它们。
- 处理指令:PI 是专门针对应用程序的信息。
- 文档片段:为了形成良好的格式,文档只能有一个根元素。有时,必须临时创建几组元素,这些元素不是满足需求所必要的。
文档片段类似于这样:
<item instock="Y" itemid="SA15"> <name>Silver Show Saddle, 16 inch</name> <price>825.00</price> <qty>1</qty> </item> <item instock="N" itemid="C49"> <name>Premium Cinch</name> <price>49.00</price> <qty>1</qty> </item> |
为了使用 XML 文件中的信息,必须解析该文件以创建 Document 对象。
Document 对象是一个接口,所以不能直接实例化;相反,应用程序一般使用 factory。确切的过程随实现的不同而不同,但想法是相同的。在示例 JAXP 环境中,解析文件是一个三步过程:
- 创建 DocumentBuilderFactory。该对象将创建 DocumentBuilder。
- 创建 DocumentBuilder。 DocumentBuilder 将实际进行解析以创建 Document 对象。
- 解析该文件以创建 Document 对象。
如果需要,在不必更改代码的情况下,JAXP 允许插进不同的解析器。让我们继续,开始构建应用程序。
从创建基本的应用程序,名为 OrderProcessor 的类开始。
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.File; import org.w3c.dom.Document; public class OrderProcessor { public static void main (String args[]) { 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."); } } } |
首先,Java 导入必要的类,然后创建 OrderProcessor 应用程序。在本教程中的这个示例将只处理一个文件,所以为简短起见,该应用程序包含对它的直接引用。
应用程序在 try-catch 块外部定义了 Document 对象,以便在后面使用该对象。try-catch 使您能执行可能会抛出异常的一些操作,这样不会危及整个应用程序。如果异常抛出,则应用程序简单地执行相应的 catch 代码。
在 try-catch 块内部,应用程序创建 DocumentBuilderFactory,然后使用它来创建 DocumentBuilder。最后,DocumentBuilder 解析该文件以创建 Document。
- Document.getDocumentElement()
返回文档的根(root)元素。 - Node.getFirstChild() and Node.getLastChild()
返回给定 Node 的第一个子女。 - Node.getNextSibling() and Node.getPreviousSibling()
这些方法返回下一个或前一个给定 Node 的同胞。 - Node.getAttribute(attrName)
对给定的 Node,返回给定名称的属性。例如,如果您要获得名为 id 属性 的对象,可调用 getAttribute("id")。
- 更改节点数据
Node.setNodeValue(elemValue);
- 添加节点
String totalString = new Double(total).toString(); Node totalNode = doc.createTextNode(totalString); //Document 对象创建新的文本节点,该节点带有作为值的 totalString Element totalElement = doc.createElement("total"); //创建新元素 total totalElement.appendChild(totalNode); // 将节点添加到新的 total 元素。 thisOrder.insertBefore(totalElement, thisOrder.getFirstChild()); //将新元素添加到 Document,指定新的 Node,然后指定新 Node 在 Node 之前
- 除去节点
Node deadNode = thisOrderItem.getParentNode().removeChild(thisOrderItem);
- 替换节点
Element backElement = doc.createElement("backordered"); //创建新元素 backordered Node deadNode = thisOrderItem.getParentNode().replaceChild(backElement,thisOrderItem);
- 创建和设置属性
Element backElement = doc.createElement("backordered"); //创建新元素 backordered backElement.setAttributeNode(doc.createAttribute("itemid")); //创建新属性 itemid String itemIdString = thisOrderItem.getAttributeNode("itemid").getNodeValue(); //取得thisOrderItem的属性itemid的值 backElement.setAttribute("itemid", itemIdString); //设置backElement的属性item的值,可以省略createAttribute Node deadNode = thisOrderItem.getParentNode().replaceChild(backElement,thisOrderItem);
- 除去属性
Element thisOrder = (Element)orders.item(orderNum); Element customer = (Element)thisOrder.getElementsByTagName("cusomertid").item(0); customer.removeAttribute("limit"); //去除属性limit