DOM基礎&實例
作者:yi5 轉貼自:yi5_yuyu 點擊數:12 文章錄入: yuyu3007
在先前的一章介紹了SAX的基本方法,對于SAX來說他本身就具有串行的特點,所以讀寫起來比較方便但是,接下來要講述的DOM(Document Object Model),雖然也是處理XML的一種方法,但是他的使用方法與SAX卻完全不同,他的處理方法有點類似于數據結構中的樹,在處理上也和樹比較相似。他在處理XML的時候,是把整個XML文件讀入到內存中,然后建立像我們在瀏覽中看到的樹一樣的一棵樹,通過對樹的操作我們可以完成刪除添加等。提到了樹的操作,要先介紹幾個用到的對象,通過這些對象能夠更好的完成DOM對XML的操作。在介紹這些數據類型之前首先給出DOM在內存中的樹的一個基本結構。
Document-----------Document Type
|_______Element-----------Element
|____Attr
|____Text
上面只是一個簡單的圖,在這個圖中,Element是可以嵌套的,另外樹種還要包含實體注釋等內容。在DOM的處理過程中,類似于上面樹中的每一個節點,都是一個Node對象。這個Node對象可以看成是我們學習數據結構時樹的節點,通過他可以獲得它的孩子節點,父節點。由于XML還擁有屬性,同時XML擁有的屬性和子節點都可以使多個,所以DOM還提供了兩個類NodeList,NamedNodeMap這兩個類可以很方便的處理多個節點。通過Node的getChilds()可以得到一個NodeList這個NodeList中包含了Node的所有子節點,通過Node的getAttributes()方法可以獲得該節點的所有屬性,這個方法的返回值是NamedNodeMap通過對這個返回值的遍歷可以獲得所有的屬性值。
通過這些獲得了DOM樹的節點但是如何處理哪?怎樣才能知道他是什么類型,元素還是實體,或者是其他類型哪?這正是接下來要處理的問題。從DOM數中取出的每一個節點都有對應的一個類型,可以通過Node中的getNodeType()方法來獲得,同時在Node接口中有XML中所有元素的類型,只要是用你得到的節點的NodeType與已知的類型進行比較就能知道他是什么類型,不同的類型作不同的處理。一般來說都是用一個switch()…case語句對DOM樹中的所有節點進行處理。
如果要完成對DOM樹的添加刪除修改等操作,那就需要具備一定的數據結構知識,這里就不詳細介紹了,處理方法和樹一樣,這不過是樹,而不是二叉樹。如果是數據的修改比較容易,可是結構的修改就比較麻煩了。完成了對DOM樹修改之后如何才能把它寫回到文件中去哪,要知道樹并不是串行的,但是寫入的文件卻是串行的。所以這就需要用到一種遍歷的方法。但是這種遍歷的方法和樹結構的建立有關,因為建立時不管怎樣都是Document在根部的,所以遍歷的方法用到的也是處理樹傳統方式遞歸。處理流程是這樣的:
1、 處理Document節點。
2、 用相同的方法處理他的孩子節點。
3、 對每種節點都用相同的方法處理他們的孩子節點,形成遞歸。知道遍歷完整棵樹。
下面是一個具體的例子,只不過這個例子中,我無論如何也不能寫入數據或者讀出數據還忘高手能夠指教,先行謝過了。
import org.w3c.dom.*;
import org.w3c.dom.Document;
import org.apache.xerces.impl.xs.dom.DOMParser;
import java.io.*;
import org.xml.sax.*;
public class DomOutput {
private DOMParser parser = new DOMParser();
private Document doc;
public DomOutput() {
}
private void init()
{
try {
parser.parse("first1.xml");
doc = parser.getDocument();
FileWriter fw = new FileWriter("second.xml");
serialize(doc,fw);
fw.close();
}
catch (IOException ex) {
ex.printStackTrace();
}
catch (SAXException ex) {
ex.printStackTrace();
}
}
public void serialize(Document docu,Writer writer)
{
serialize(docu,writer,"");
try {
writer.flush();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
private void serialize(Node node,Writer writer,String indentLevel)
{
try
{
switch (node.getNodeType()) {
case Node.DOCUMENT_NODE:
writer.write("<?xml version = \"1.0\"?>\n");
Document doc1 = (Document) node;
serialize(doc1.getDocumentElement(),writer,"");
break;
case Node.ELEMENT_NODE:
String name = node.getNodeName();
String names = name;
String value = "";
NamedNodeMap nnm = node.getAttributes();
for(int i = 0 ; i < nnm.getLength(); i++)
{
name+=" "+nnm.item(i).getNodeName()+"=\""+nnm.item(i).getNodeValue()+"\"";
}
writer.write("<"+name+">");
NodeList childs = node.getChildNodes();
if(childs != null && childs.getLength()>0 && childs.item(0).getNodeType() == Node.ELEMENT_NODE)
{
for(int i = 0 ; i < childs.getLength(); i++)
serialize(childs.item(i),writer,"");
}
else
{
value = node.getNodeValue();
if(value == null)
value = "";
}
writer.write(value+"</"+names+">\n");
break;
case Node.TEXT_NODE:
writer.write(node.getNodeValue());
System.out.println(node.getNodeValue());
break;
default:
break;
}
}catch(IOException ex){
ex.printStackTrace();
}
}
public static void main(String[] args) {
DomOutput domOutput = new DomOutput();
domOutput.init();
}
}
在上面這個例子中使用的XML文件和SAX中用的相同這里就不再貼出了,對于用DOM來建立心數主要是利用了Element類的appendChild()方法來添加新的節點。下面也給出一個簡單的例子,不過這個例子要用到上面例子中的船行化的方法,所以最好把他們放在相同的目錄下。
package TestDom;
import org.w3c.dom.DOMImplementation;
import org.apache.xerces.dom.DOMImplementationImpl;
import org.w3c.dom.Document;
import org.w3c.dom.*;
import java.io.FileWriter;
import java.io.*;
public class CreateDom {
public CreateDom() {
}
private void Init()
{
DOMImplementation domImpl = new DOMImplementationImpl();
Document doc = domImpl.createDocument(null,"item",null);
Element ele = doc.getDocumentElement();
Element item1 = doc.createElement("name");
item1.setAttribute("id","001");
Text item1text = doc.createTextNode("This is a test");
item1.appendChild(item1text);
ele.appendChild(item1);
Element item2 = doc.createElement("name");
item2.setAttribute("id","002");
item2.setNodeValue("Pencil");
Text item2text = doc.createTextNode("Test2");
item2.appendChild(item2text);
ele.appendChild(item2);
DomOutput out = new DomOutput();
try {
out.serialize(doc, new FileWriter("third.xml"));
}
catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
CreateDom dom = new CreateDom();
dom.Init();
}
}
在創建過程中我遇到了相同的問題就是無法寫入數據,如果哪位朋友能幫我搞定這個問題小弟不勝感激,剛剛學習XML就出來獻丑,實在慚愧,不過這也算是學習過程中的一點心得,寫出來希望能夠對別人有所幫助,同時也為了使自己能夠加深理解。DOM在這里只是介紹了他的比較簡單的使用方法,算是入門吧,后續章節中講給出DOM的一些高級知識。
posted on 2005-10-23 00:00
YangRj 閱讀(635)
評論(1) 編輯 收藏