




已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Java與XML聯合編程之DOM篇來源網絡轉載 作者揚帆 時間2005-08-24 點擊 991 DOM初步DOM是DocumentObjectModel的縮寫,即文檔對象模型。前面說過,XML將數據組織為一顆樹,所以DOM就是對這顆樹的一個對象描敘。通俗的說,就是通過解析XML文檔,為XML文檔在邏輯上建立一個樹模型,樹的節點是一個個對象。我們通過存取這些對象就能夠存取XML文檔的內容。下面我們來看一個簡單的例子,看看在DOM中,我們是如何來操作一個XML文檔的。這是一個XML文檔,也是我們要操作的對象Good-byeserialization,helloJava!下面,我們需要把這個文檔的內容解析到一個個的Java對象中去供程序使用,利用JAXP,我們只需幾行代碼就能做到這一點。首先,我們需要建立一個解析器工廠,以利用這個工廠來獲得一個具體的解析器對象DocumentBuilderFactorydbf=DocumentBuilderFactory.newInstance();我們在這里使用DocumentBuilderFacotry的目的是為了創建與具體解析器無關的程序,當DocumentBuilderFactory類的靜態方法newInstance()被調用時,它根據一個系統變量來決定具體使用哪一個解析器。又因為所有的解析器都服從于JAXP所定義的接口,所以無論具體使用哪一個解析器,代碼都是一樣的。所以當在不同的解析器之間進行切換時,只需要更改系統變量的值,而不用更改任何代碼。這就是工廠所帶來的好處。這個工廠模式的具體實現,可以參看下面的類圖。DocumentBuilderdb=dbf.newDocumentBuilder();當獲得一個工廠對象後,使用它的靜態方法newDocumentBuilder()方法可以獲得一個DocumentBuilder對象,這個對象代表了具體的DOM解析器。但具體是哪一種解析器,微軟的或者IBM的,對于程序而言並不重要。然後,我們就可以利用這個解析器來對XML文檔進行解析了Documentdoc=db.parse(c:/xml/message.xml);DocumentBuilder的parse()方法接受一個XML文檔名覂淙氬問禱匾桓ocument對象,這個Document對象就代表了一個XML文檔的樹模型。以後所有的對XML文檔的操作,都與解析器無關,直接在這個Document對象上進行操作就可以了。而具體對Document操作的方法,就是由DOM所定義的了。Jaxp支持W3C所推薦的DOM2。如果你對DOM很熟悉,那麼下面的內容就很簡單了只需要按照DOM的規範來進行方法調用就可以。當然,如果你對DOM不清楚,也不用著急,後面我們會有詳細的介紹。在這兒,你所要知道並牢記的是DOM是用來描敘XML文檔中的數據的模型,引入DOM的全部原因就是為了用這個模型來操作XML文檔的中的數據。DOM規範中定義有節點(即對象)、屬性和方法,我們通過這些節點的存取來存取XML的數據。從上面得到的Document對象開始,我們就可以開始我們的DOM之旅了。使用Document對象的getElementsByTagName()方法,我們可以得到一個NodeList對象,一個Node對象代表了一個XML文檔中的一個標簽元素,而NodeList對象,觀其名而知其意淼氖且桓ode對象的列表NodeListnl=doc.getElementsByTagName(message);我們通過這樣一條語句所得到的是XML文檔中所有標簽對應的Node對象的一個列表。然後,我們可以使用NodeList對象的item()方法來得到列表中的每一個Node對象Nodemy_node=nl.item(0);當一個Node對象被建立之後,保存在XML文檔中的數據就被提取出來並封裝在這個Node中了。在這個例子中,要提取Message標簽內的內容,我們通常會使用Node對象的getNodeValue()方法Stringmessage=my_node.getFirstChild().getNodeValue();請注意,這里還使用了一個getFirstChild()方法來獲得message下面的第一個子Node對象。雖然在message標簽下面除了文本外並沒有其它子標簽或者屬性,但是我們堅持在這里使用getFirseChild()方法,這主要和W3C對DOM的定義有關。W3C把標簽內的文本部分也定義成一個Node,所以先要得到代表文本的那個Node,我們才能夠使用getNodeValue()來獲取文本的內容。現在,既然我們已經能夠從XML文件中提取出數據了,我們就可以把這些數據用在合適的地方,來構築應用程序。下面的內容,我們將更多的關注DOM,為DOM作一個較為詳細的解析,使我們使用起來更為得心應手。DOM詳解1基本的DOM對象DOM的基本對象有5個Document,Node,NodeList,Element和Attr。下面就這些對象的功能和實現的方法作一個大致的介紹。Document對象代表了整個XML的文檔,所有其它的Node,都以一定的順序包含在Document對象之內,排列成一個樹形的結構,程序員可以通過遍歷這顆樹來得到XML文檔的所有的內容,這也是對XML文檔操作的起點。我們總是先通過解析XML啈葆玫揭桓ocument對象,然後再來執行後續的操作。此外,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.Nodenew,org.w3c.dom.Noderef)在給定的一個子對象前再插入一個子對象。removeChild(org.w3c.dom.Node)刪除給定的子節點對象。replaceChild(org.w3c.dom.Nodenew,org.w3c.dom.Nodeold)用一個新的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語言來閎?W摹蚨OM其實可以在任何面向對象的語言中實現,只要它實現了DOM所定義的接口和功能就可以了。同時,有些方法在DOM中並沒有定義,是用IDL的屬性來表達的,當被映射到具體的語言時,這些屬性被映射為相應的方法。2DOM實例有了上面的介紹,相信你對DOM理解的更多了吧。下面的例子將讓你對DOM更加熟悉起來。先說說這個例子到底要做的是什麼吧,我們希望在一個名為link.xml文件中保存了一些URL地址,通過一個簡單的程序,我們可以通過DOM把這些URL讀出並顯示出來,也可以反過來向這個XML文件中寫入加入的URL地址。很簡單,卻很實用,也足夠來例示DOM的絕大部分用法了。XML文件本身不復雜,就不給出它的DTD了。link.xml:JSPInsiderJSPInsider212001AJSPinformationsite.ThemakersofJavaSunMicrosystems312001SunMicrosystemswebsite.ThestandardJSPcontainerApacheGroup412001Somegreatsoftware.第一個程序我們稱為xmldisplay.java,具體的程序清單可以在附件中找到。主要的功能就是讀取這個XML文件中各個節點的內容,然後在格式化輸出在System.out上,我們來看看這個程序importjavax.xml.parsers.*;importorg.w3c.dom.*;這是引入必要的類,因為在這里使用的是Sun所提供的XML解析器,因而需要引入java.xml.parsers包,其中包含了有DOM解析器和SAX解析器的具體實現。org.w3c.dom包中定義了w3c所制定的DOM接口。DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();DocumentBuilderbuilder=factory.newDocumentBuilder();Documentdoc=builder.parse(links.xml);doc.normalize();除了上面講到的,還有一個小技巧,對Document對象調用normalize(),可以去掉XML文檔中作為格式化內容的空白而映射在DOM樹中的不必要的TextNode對象。否則你得到的DOM樹可能並不如你所想象的那樣。特別是在輸出的時候,這個normalize()更為有用。NodeListlinks=doc.getElementsByTagName(link);剛才說過,XML文檔中的空白符也會被作為對象映射在DOM樹中。因而,直接調用Node方法的getChildNodes方法有時候會有些問題,有時不能夠返回所期望的NodeList對象。解決的辦法是使用Element的getElementByTagName(String),返回的NodeLise就是所期待的對象了。然後,可以用item()方法提取想要的元素。for(inti=0;ilinks.getLength();i+)Elementlink=(Element)links.item(i);System.out.print(Content:);System.out.println(link.getElementsByTagName(text).item(0).getFirstChild().getNodeValue();System.out.print(URL:);System.out.println(link.getElementsByTagName(url).item(0).getFirstChild().getNodeValue();System.out.print(Author:);System.out.println(link.getElementsByTagName(author).item(0).getFirstChild().getNodeValue();System.out.print(Date:);Elementlinkdate=(Element)link.getElementsByTagName(date).item(0);Stringday=linkdate.getElementsByTagName(day).item(0).getFirstChild().getNodeValue();Stringmonth=linkdate.getElementsByTagName(month).item(0).getFirstChild().getNodeValue();Stringyear=linkdate.getElementsByTagName(year).item(0).getFirstChild().getNodeValue();System.out.println(day+-+month+-+year);System.out.print(Description:);System.out.println(link.getElementsByTagName(description).item(0).getFirstChild().getNodeValue();System.out.println();上面的代碼片斷就完成了對XML文檔內容的格式化輸出。只要注意到一些細節的問題,比如getFirstChile()方法和getElementsByTagName()方法的使用,這些還是比較容易的。下面的內容,就是在修改了DOM樹後重新寫入到XML文檔中去的問題了。這個程序名為xmlwrite.java。在JAXP1.0版本中,並沒有直接的類和方法能夠處理XML文檔的寫入問題,需要借助其它包中的一些輔助類。而在JAXP1.1版本中,引入了對XSLT的支持,所謂XSLT,就是對XML文檔進行變換(Translation)後,得到一個新的文檔結構。利用這個新加入的功能,我們就能夠很方便的把新生成或者修改後的DOM樹從新寫回到XML文件中去了,下面我們來看看代碼的實現,這段代碼翔x饕蓯竅inks.xml文件中加入一個新的link節點importjavax.xml.parsers.*;importjavax.xml.transform.*;importjavax.xml.transform.dom.DOMSource;importjavax.xml.transform.stream.StreamResult;importorg.w3c.dom.*;新引入的java.xml.transform包中的幾個類,就是用來處理XSLT變換的。我們希望在上面的XML文件中加入一個新的link節點,因而首先還是要讀入links.xml文件,構建一個DOM樹,然後再對這個DOM樹進行修改(添加節點),最後把修改後的DOM寫回到links.xml文件中DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();DocumentBuilderbuilder=factory.newDocumentBuilder();Documentdoc=builder.parse(links.xml);doc.normalize();/-取得變量-Stringtext=HanzhongsHomepage;Stringurl=;Stringauthor=HzliuLiu;Stringdiscription=AsitefromHanzhongLiu,giveulotsofsuprise!;為了看清重點,簡化程序,我們把要加入的內容硬編碼到記憶String對象中,而實際操作中,往往利用一個界面來提取用戶輸入,或者通過JDBC從數據庫中提取想要的內容。Texttextseg;Elementlink=doc.createElement(link);首先應該明了的是,無論什麼類型的Node,Text型的也好,Attr型的也好,Element型的也好,它們的創建都是通過Document對象中的createXXX()方法來創建的(XXX代表具體要創建的類型),因此,我們要向XML文檔中添加一個link項目,首先要創建一個link對象Elementlinktext=doc.createElement(text);textseg=doc.createTextNode(text);linktext.appendChild(textseg);link.appendChild(linktext);Elementlinkurl=doc.createElement(url);textseg=doc.createTextNode(url);linkurl.appendChild(textseg);link.appendChild(linkurl);Elementlinkauthor=doc.createElement(author);textseg=doc.createTextNode(author);linkauthor.appendChild(textseg);link.appendChild(linkauthor);java.util.CalendarrightNow=java.util.Calendar.getInstance();Stringday=Integer.toString(rightNow.get(java.util.Calendar.DAY_OF_MONTH);Stringmonth=Integer.toString(rightNow.get(java.util.Calendar.MONTH);Stringyear=Integer.toString(rightNow.get(java.util.Calendar.YEAR);Elementlinkdate=doc.createElement(date);Elementlinkdateday=doc.createElement(day);textseg=doc.createTextNode(day);linkdateday.appendChild(textseg);Elementlinkdatemonth=doc.createElement(month);textseg=doc.createTextNode(month);linkdatemonth.appendChild(textseg);Elementlinkdateyear=doc.createElement(year);textseg=doc.createTextNode(year);linkdateyear.appendChild(textseg);linkdate.appendChild(linkdateday);linkdate.appendChild(linkdatemonth);linkdate.appendChild(linkdateyear);link.appendChild(linkdate);Ele
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- YY/T 0865.1-2024超声水听器第1部分:医用超声场的测量和特征描绘
- JJG(烟草)29-2011烟草加工在线水分仪检定规程
- JJG(烟草)18-2012烟草专用透气度流量盘检定规程
- 2005年上海市中考数学试题【含答案、解析】
- 安徽省天一大联考2025届高三上学期期末检测-物理试卷+答案
- 考研复习-风景园林基础考研试题带答案详解(模拟题)
- 风景园林基础考研资料试题及答案详解【易错题】
- 《风景园林招投标与概预算》试题A附答案详解(精练)
- 2025年江西省高速公路投资集团有限责任公司招聘笔试备考题库附答案详解(夺分金卷)
- 2024年滨州新能源集团有限责任公司及权属公司公开招聘工作人员递补笔试备考题库附答案详解(夺分金卷)
- 2025年全国高考作文题+参考答案
- 2025年新高考全国Ⅰ卷英语模拟试卷(含答案)
- 【MOOC】模拟电子电路实验-东南大学 中国大学慕课MOOC答案
- 超星尔雅学习通《当代大学生国家安全教育》章节测试答案
- ISO28000:2022供应链安全管理体系
- 丽声英语百科分级读物第四级Animal Tricks课件
- 煤矿开采学基本概念
- 个人公证委托书
- 第五章溶胶凝胶法
- 中华人民共和国敏感物项呵技术出口许可申请表
- 最全复利系数表(共41页)
评论
0/150
提交评论