DOM 是 Document Object Model 的缩写,即文档对象模型。前面说过, XML 将数据组织为一颗树,所以 DOM 就是对这颗树的一个对象描叙。通俗的说,就是通过解析 XML 文档,为 XML 文档在逻辑上建立一个树模型,树的节点是一个个对象。我们通过存取这些对象就能够存取 XML 文档的内容。
下面我们来看一个简单的例子,看看在 DOM 中,我们是如何来操作一个 XML 文档的。
这是一个 XML 文档,也是我们要操作的对象:
下面,我们需要把这个文档的内容解析到一个个的 Java 对象中去供程序使用,利用 JAXP ,我们只需几行代码就能做到这一点。首先,我们需要建立一个解析器工厂,以利用这个工厂来获得一个具体的解析器对象:
我们在这里使用 DocumentBuilderFacotry 的目的是为了创建与具体解析器无关的程序,当 DocumentBuilderFactory 类的静态方法 newInstance() 被调用时,它根据一个系统变量来决定具体
使用哪一个解析器。又因为所有的解析器都服从于 JAXP 所定义的接口,所以无论具体使用哪一个解析器,代码都是一样的。所以当在不同的解析器之间进行切换时,只需要更改系统变量的值,而不用更改任何代码。这就是工厂所带来的好处。这个工厂模式的具体实现,可以参看下面的类图。当获得一个工厂对象后, 使用它的静态方法 newDocumentBuilder() 方法可以获得一个 DocumentBuilder 对象,这个对象代表了具体的 DOM 解析器。
DOM 详解
DOM 的基本对象有 5 个: Document , Node , NodeList , Element 和 Attr 。下面就这些对象的功
能和实现的方法作一个大致的介绍。
Document 对象代表了整个 XML 的文档,所有其它的 Node ,都以一定的顺序包含在 Document
String message = my_node.getFirstChild().getNodeValue();
1 .基本的 DOM 对象
对象之内,排列成一个树形的结构,程序员可以通过遍历这颗树来得到 XML 文档的所有的内容,这也是对 XML 文档操作的起点。我们总是先通过解析 XML 源文件而得到一个 Document 对象,然后再来执行后续的操作。此外, Document 还包含了创建其它节点的方法,比如 createAttribut() 用来创建一个 Attr 对象。它所包含的主要的方法有:
createAttribute(String) :用给定的属性名创建一个 Attr 对象,并可在其后使用 setAttributeNode 方法来放置在某一个 Element 对象上面。
createElement(String) :用给定的标签名创建一个 Element 对象,代表 XML 文档中的一个标签,然后就可以在这个 Element 对象上添加属性或进行其它的操作。
createTextNode(String) :用给定的字符串创建一个 Text 对象, Text 对象代表了标签或者属性中所包含的纯文本字符串。如果在一个标签内没有其它的标签,那么标签内的文本所代表的 Text 对象是这个 Element 对象的唯一子对象。
getElementsByTagName(String) :返回一个 NodeList 对象,它包含了所有给定标签名字的标签。 getDocumentElement() :返回一个代表这个 DOM 树的根节点的 Element 对象,也就是代表 XML 文档根元素的那个对象。
Node 对象是 DOM 结构中最为基本的对象,代表了文档树中的一个抽象的节点。在实际使用的时候,很少会真正的用到 Node 这个对象,而是用到诸如 Element 、 Attr 、 Text 等 Node 对象的子对象来操作文档。 Node 对象为这些对象提供了一个抽象的、公共的根。虽然在 Node 对象中定义了对其子节点进行存取的方法,但是有一些 Node 子对象,比如 Text 对象,它并不存在子节点,这一点是要注意的。 Node 对象所包含的主要的方法有: appendChild(org.w3c.dom.Node) :为这个节点添加一个子节点,并放在所有子节点的最后,如果这个子节点已经存在,则先把它删掉再添加进去。 getFirstChild() :如果节点存在子节点,则返回第一个子节点,对等的,还有 getLastChild() 方法返回最后一个子节点。
getNextSibling() : 返回在 DOM 树中这个节点的下一个兄弟节点, 对等的, 还有
getPreviousSibling() 方法返回其前一个兄弟节点。
getNodeName() :根据节点的类型返回节点的名称。
getNodeType() :返回节点的类型。
getNodeValue() :返回节点的值。
hasChildNodes() :判断是不是存在有子节点。
hasAttributes() :判断这个节点是否存在有属性。
getOwnerDocument() :返回节点所处的 Document 对象。
insertBefore(org.w3c.dom.Node new , org.w3c.dom.Node ref) :在给定的一个子对象前再插入一个子对象。
removeChild(org.w3c.dom.Node) :删除给定的子节点对象。
replaceChild(org.w3c.dom.Node new , org.w3c.dom.Node old) :用一个新的 Node 对象代替给定的子节点对象。
NodeList 对象,顾名思义,就是代表了一个包含了一个或者多个 Node 的列表。可以简单的把它看成一个 Node 的数组,我们可以通过方法来获得列表中的元素:
GetLength() :返回列表的长度。
Item(int) :返回指定位置的 Node 对象。
Element 对象代表的是 XML 文档中的标签元素,继承于 Node ,亦是 Node 的最主要的子对象。在标签中可以包含有属性,因而 Element 对象中有存取其属性的方法,而任何 Node 中定义的方法,也可以用在 Element 对象上面。
getElementsByTagName(String) :返回一个 NodeList 对象,它包含了在这个标签中其下的子孙
节点中具有给定标签名字的标签。
getTagName() :返回一个代表这个标签名字的字符串。
getAttribute(String) :返回标签中给定属性名称的属性的值。在这儿需要主要的是,应为 XML
文档中允许有实体属性出现,而这个方法对这些实体属性并不适用。这时候需要用到
getAttributeNodes() 方法来得到一个 Attr 对象来进行进一步的操作。
getAttributeNode(String) :返回一个代表给定属性名称的 Attr 对象。
Attr 对象代表了某个标签中的属性。 Attr 继承于 Node ,但是因为 Attr 实际上是包含在 Element 中的,它并不能被看作是 Element 的子对象,因而在 DOM 中 Attr 并不是 DOM 树的一部分,所以 Node
中的 getparentNode() , getpreviousSibling() 和 getnextSibling() 返回的都将是 null 。也就是说,
Attr 其实是被看作包含它的 Element 对象的一部分,它并不作为 DOM 树中单独的一个节点出现。这一点在使用的时候要同其它的 Node 子对象相区别。
需要说明的是,上面所说的 DOM 对象在 DOM 中都是用接口定义的,在定义的时候使用的是与具体语言无关的 IDL 语言来定义的。因而, DOM 其实可以在任何面向对象的语言中实现,只要它实现了 DOM 所定义的接口和功能就可以了。同时,有些方法在 DOM 中并没有定义,是用 IDL
的属性来表达的,当被映射到具体的语言时,这些属性被映射为相应的方法。
有了上面的介绍,相信你对DOM理解的更多了吧。下面的例子将让你对DOM更加熟悉起来。
package com.dzf.test; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Vector; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /***/ /** * @author dengzhifeng * */ public class Writexml ... { private Documentdocument; private Stringfilename; private boolean validating; public Writexml(Stringname) throws ParserConfigurationException ... { filename = name; DocumentBuilderFactoryfactory = DocumentBuilderFactory.newInstance(); DocumentBuilderbuilder = factory.newDocumentBuilder(); document = builder.newDocument(); } public VectortoRead(Stringfilename) ... { Vectortitle = new Vector(); Vectorcontent = new Vector(); StringmyStr = new String(); try ... { DocumentBuilderFactoryfactory = DocumentBuilderFactory .newInstance(); factory.setValidating(validating); DocumentBuilderbuilder = factory.newDocumentBuilder(); document = builder.parse( new File(filename)); document.getDocumentElement().normalize(); Nodenode = document.getFirstChild(); NodeListlist = node.getChildNodes(); for ( int i = 0 ;i < list.getLength();i ++ ) ... { Nodenodeitm = list.item(i); if (nodeitm.getNodeName().equals( " Title " )) ... { myStr = nodeitm.getFirstChild().getNodeValue(); title.addElement(myStr); // getFirstChild() } if (nodeitm.getNodeName().equals( " Content " )) ... { myStr = nodeitm.getFirstChild().getNodeValue(); content.addElement(myStr); } } } catch (Exceptionexp) ... { exp.printStackTrace(); return null ; } Vectorall = new Vector(); all.add(title); all.add(content); return all; } public void toWrite(Stringmytitle,Stringmycontent) ... { Elementroot = document.createElement( " D " ); document.appendChild(root); Elementsegment = document.createElement( " RH " ); root.appendChild(segment); ElementH_segment = document.createElement( " CH " ); H_segment.setAttribute( " Name " , " FCon_number " ); H_segment.setAttribute( " Type " , " string " ); H_segment.setAttribute( " Value " , " 编码 " ); H_segment.setAttribute( " Visible " , " false " ); H_segment.setAttribute( " Readonly " , " true " ); segment.appendChild(H_segment); ElementH_segment1 = document.createElement( " CH " ); H_segment1.setAttribute( " Name " , " FName " ); H_segment1.setAttribute( " Type " , " string " ); H_segment1.setAttribute( " Value " , " 条件名称 " ); H_segment1.setAttribute( " Visible " , " true " ); H_segment1.setAttribute( " Readonly " , " true " ); segment.appendChild(H_segment1); ElementH_segment2 = document.createElement( " CH " ); H_segment2.setAttribute( " Name " , " FCon_exp " ); H_segment2.setAttribute( " Type " , " string " ); H_segment2.setAttribute( " Value " , " 条件 " ); H_segment2.setAttribute( " Visible " , " true " ); H_segment2.setAttribute( " Readonly " , " true " ); segment.appendChild(H_segment2); ElementH_segment3 = document.createElement( " CH " ); H_segment3.setAttribute( " Name " , " FCon_sum " ); H_segment3.setAttribute( " Type " , " string " ); H_segment3.setAttribute( " Value " , " 结论 " ); H_segment3.setAttribute( " Visible " , " true " ); H_segment3.setAttribute( " Readonly " , " flase " ); segment.appendChild(H_segment3); Elementtitle = document.createElement( " Title " ); title.appendChild(document.createTextNode(mytitle)); root.appendChild(title); Elementtitle1 = document.createElement( " Title " ); title1.appendChild(document.createTextNode( " title1 " )); root.appendChild(title1); Elementcontent = document.createElement( " Content " ); content.appendChild(document.createTextNode(mycontent)); content.appendChild(document.createTextNode( " content1 " )); root.appendChild(content); Writexml.save(root); } public static void save(Nodedoc) ... { StringWritermysw = new StringWriter(); // // System.out.println("doc===="+doc); if (doc != null ) ... { try ... { TransformerFactorytransFact = TransformerFactory.newInstance(); Transformertrans = transFact.newTransformer(); doc.normalize(); trans.transform( new DOMSource(doc), new StreamResult(mysw)); System.out.println(mysw.toString()); } catch (TransformerConfigurationExceptiontce) ... { tce.printStackTrace(System.err); } catch (TransformerExceptionte) ... { te.printStackTrace(System.err); } } // return""; }