版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、DOM解析器是通過將XML文檔解析成樹狀模型并將其放入內(nèi)存來完成解析工作的,而后對文檔的操作都是在這個樹狀模型上完成的。這個在內(nèi)存中的文檔樹將是文檔實際大小的幾倍。這樣做的好處是結(jié)構(gòu)清除、操作方便,而帶來的麻煩就是極其耗費(fèi)系統(tǒng)資源。而SAX正好克服了DOM的缺點,分析能夠立即開始,而不是等待所有的數(shù)據(jù)被處理。而且,由于應(yīng)用程序只是在讀取數(shù)據(jù)時檢查數(shù)據(jù),因此不需要將數(shù)據(jù)存儲在內(nèi)存中,這對于大型文檔來說是個巨大的優(yōu)點。事實上,應(yīng)用程序甚至不必解析整個文檔;它可以在某個條件得到滿足時停止解析。選擇 DOM 還是選擇 SAX,這取決于下面幾個因素:應(yīng)用程序的目的:如果打算對數(shù)據(jù)作出更改并將它輸出為 X
2、ML,那么在大多數(shù)情況下,DOM 是適當(dāng)?shù)倪x擇。并不是說使用 SAX 就不能更改數(shù)據(jù),但是該過程要復(fù)雜得多,因為您必須對數(shù)據(jù)的一份拷貝而不是對數(shù)據(jù)本身作出更改。數(shù)據(jù)容量: 對于大型文件,SAX 是更好的選擇。數(shù)據(jù)將如何使用:如果只有數(shù)據(jù)中的少量部分會被使用,那么使用 SAX 來將該部分?jǐn)?shù)據(jù)提取到應(yīng)用程序中可能更好。 另一方面,如果您知道自己以后會回頭引用已處理過的大量信息,那么 SAX 也許不是恰當(dāng)?shù)倪x擇。對速度的需要: SAX 實現(xiàn)通常要比 DOM 實現(xiàn)更快?;谏厦娴姆治觯诨贏ndroid系統(tǒng)的內(nèi)存和CPU資源比較有限的手持設(shè)備上,只要我們不需要修改XML數(shù)據(jù)或者隨機(jī)的訪問XML數(shù)據(jù),
3、SAX盡管可能需要更多的編碼工作,但是為了更小的內(nèi)存和CPU消耗,還是值得的。另外,Android SDK中已經(jīng)包含了JAXP對應(yīng)的javax.xml.parsers包,和SAX對應(yīng)org.xml.sax(當(dāng)然DOM對應(yīng)的org.w3c.dom包也包含在內(nèi)),加上Android還提供了android.sax這樣的包來方便SAX Handle的開發(fā),基于JAXP和SAX這樣的標(biāo)準(zhǔn)方法來開發(fā)不僅復(fù)雜度不高,即使出現(xiàn)問題在討論組中尋求解決方案也是比較容易的。android 中的xml解析應(yīng)該是和java中一條道路 主要分為sax 解析和的Dom 解析。 如下的介紹的相關(guān)的包和類均為android 環(huán)
4、境下:sax解析對應(yīng)為:orgxmlsax 包 :xml解析兩個主要用于SAXParser的上下文建立示例如下:SAXParserFactory factory = SAXParserFactory.newInstance();SAXParser parser = factory.newSAXParser();ParseXML parX = new ParseXML();parser.parse(F:emps.xml, parX);這里的ParseXML 一般是繼承于org.xml.sax.helpers.DefaultHandler類的解析實現(xiàn)。因為Sax 對xml的解析是基于事件類型的,也
5、就是Sax Parser逐步的讀取xml文件,然后碰到一個節(jié)點,一個屬性,碰到一個節(jié)點的結(jié)束等事件都會回調(diào)哦org.xml.sax.helpers.DefaultHandler 之類的實現(xiàn),然后在Hander 的實現(xiàn)中具體解析各個節(jié)點名稱,屬性名稱。通過以上的特點可以看出sax有速度快(不需要全部的讀入內(nèi)存并構(gòu)建樹),消耗的內(nèi)存較少,線性的從上往下解析,所以它比較的適合于xml文件大,速度要求高,解析結(jié)構(gòu)自上而下 如把html展示出來,xml轉(zhuǎn)為html等。Dom解析對應(yīng)為:orgw3cdom包:xml的各個元素對應(yīng)類結(jié)構(gòu)也和sax 一樣,最終的解析目標(biāo)指向org.w3c.dom.Docume
6、nt.示例如下:File docFile = new File(orders.xml);Document doc = null;DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();doc = db.parse(docFile); / get the document.因為Dom 是基于樹結(jié)構(gòu),所以要全部結(jié)構(gòu)內(nèi)容讀入內(nèi)容,構(gòu)造樹,所以比較花費(fèi)時間,但是dom 的操作可以反復(fù)的來回操作,靈活性比較高,做出的程序結(jié)構(gòu)也比較容易認(rèn)可
7、,對于那些性能要求不是很高的,內(nèi)容比較少的,xml上下結(jié)構(gòu)比較復(fù)雜的用dom應(yīng)該是比較好的選擇了。因為在開發(fā)中,我們會常用到xml文件的讀寫操作,因為手機(jī)操作有很多版本問題和很多小數(shù)據(jù)在數(shù)據(jù)庫不是良好的解決方案。所以會用到很多xml操作。 android開發(fā)一般對xml操作常用三種技術(shù):sax、dom、pull 分別詳細(xì)的進(jìn)行介紹: 首先創(chuàng)建開發(fā)測試壞境(一下三種方法都會使用這個環(huán)境): 在類路徑下面創(chuàng)建xml文件: person.xml 王昌龍 23 小妾 17 (我的名字and因為沒有媳婦,就假設(shè)叫小妾) 針對person創(chuàng)建javabean,(因為我們下面要以對象的形式獲取此xml文件內(nèi)
8、容) package cn.partner4java.xml.bean;public class Person private int id; private String name; private short age; public int getId() return id; public void setId(int id) this.id = id; public String getName() return name; public void setName(String name) = name; public short getAge() return age; public
9、 void setAge(short age) this.age = age; Override public int hashCode() final int prime = 31; int result = 1; result = prime * result + id; return result; Override public boolean equals(Object obj) if (this = obj) return true; if (obj = null) return false; if (getClass() != obj.getClass() return fals
10、e; Person other = (Person) obj; if (id != other.id) return false; return true; sax: SAX是一個解析速度快并且占用內(nèi)存少的xml解析器,非常適合用于Android等移動設(shè)備。 SAX解析XML文件采用的是事件驅(qū)動,也就是說,它并不需要解析完整個文檔,在按內(nèi)容順序解析文檔的過程中,SAX會判斷當(dāng)前讀到的字符是否合法XML語法中的某部分,如果符合就會觸發(fā)事件。所謂事件,其實就是一些回調(diào)(callback)方法,這些方法(事件)定義在ContentHandler接口。下面是一些ContentHandler接口常用的方
11、法:startDocument()當(dāng)遇到文檔的開頭的時候,調(diào)用這個方法,可以在其中做一些預(yù)處理的工作。endDocument()和上面的方法相對應(yīng),當(dāng)文檔結(jié)束的時候,調(diào)用這個方法,可以在其中做一些善后的工作。 startElement(String namespaceURI, String localName, String qName, Attributes atts) 當(dāng)讀到一個開始標(biāo)簽的時候,會觸發(fā)這個方法。namespaceURI就是命名空間,localName是不帶命名空間前綴的標(biāo)簽名,qName是帶命名空間前綴的標(biāo)簽名。通過atts可以得到所有的屬性名和相應(yīng)的值。要注意的是SAX中
12、一個重要的特點就是它的流式處理,當(dāng)遇到一個標(biāo)簽的時候,它并不會紀(jì)錄下以前所碰到的標(biāo)簽,也就是說,在startElement()方法中,所有你所知道的信息,就是標(biāo)簽的名字和屬性,至于標(biāo)簽的嵌套結(jié)構(gòu),上層標(biāo)簽的名字,是否有子元屬等等其它與結(jié)構(gòu)相關(guān)的信息,都是不得而知的,都需要你的程序來完成。這使得SAX在編程處理上沒有DOM來得那么方便。endElement(String uri, String localName, String name)這個方法和上面的方法相對應(yīng),在遇到結(jié)束標(biāo)簽的時候,調(diào)用這個方法。characters(char ch, int start, int length) 這個方法
13、用來處理在XML文件中讀到的內(nèi)容,第一個參數(shù)為文件的字符串內(nèi)容,后面兩個參數(shù)是讀到的字符串在這個數(shù)組中的起始位置和長度,使用new String(ch,start,length)就可以獲取內(nèi)容。不知道你看懂上面的解釋了么?那好,我們動手做一下: 創(chuàng)建XMLContentHandler,如上面說的應(yīng)該實現(xiàn) ContentHandler接口,但是我們這里去集成一個它的實現(xiàn)類就OL, package cn.partner4java.sax.service;import java.util.ArrayList;import java.util.List;import org.xml.sax.Attri
14、butes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;import cn.partner4java.sax.bean.Person;public class XMLContentHandler extends DefaultHandler private List persons; private Person person; private String preTag; public List getPersons() return persons; /這個方法用來處理在XML文件中讀到
15、的內(nèi)容,第一個參數(shù)為文件的字符串內(nèi)容,后面兩個參數(shù)是讀到的字符串在這個數(shù)組中的起始位置和長度, /使用new String(ch,start,length)就可以獲取內(nèi)容。 Override public void characters(char ch, int start, int length) throws SAXException String data = new String(ch, start, length); if(name.equals(preTag) person.setName(data); else if(age.equals(preTag) person.setAg
16、e(new Short(data); /這個方法和上面的方法相對應(yīng),在遇到結(jié)束標(biāo)簽的時候,調(diào)用這個方法。 Override public void endElement(String uri, String localName, String qName) throws SAXException if(person.endsWith(localName) & person != null) persons.add(person); person = null; preTag = null; /和上面的方法相對應(yīng),當(dāng)文檔結(jié)束的時候,調(diào)用這個方法,可以在其中做一些善后的工作。 Override p
17、ublic void startDocument() throws SAXException persons = new ArrayList(); /當(dāng)讀到一個開始標(biāo)簽的時候,會觸發(fā)這個方法。namespaceURI就是命名空間,localName是不帶命名空間前綴的標(biāo)簽名, /qName是帶命名空間前綴的標(biāo)簽名。通過atts可以得到所有的屬性名和相應(yīng)的值。要注意的是SAX中一個重要的特點就是它的流式處理, /當(dāng)遇到一個標(biāo)簽的時候,它并不會紀(jì)錄下以前所碰到的標(biāo)簽,也就是說,在startElement()方法中,所有你所知道的信息,就是標(biāo)簽的名字和屬性, /至于標(biāo)簽的嵌套結(jié)構(gòu),上層標(biāo)簽的名字,是
18、否有子元屬等等其它與結(jié)構(gòu)相關(guān)的信息,都是不得而知的, /都需要你的程序來完成。這使得SAX在編程處理上沒有DOM來得那么方便。 Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException /初始化:新建javabean if(person.equals(localName) person = new Person(); person.setId(new Integer(attributes.getValue(0);
19、 preTag = localName; SAX 支持已內(nèi)置到JDK1.5中,你無需添加任何的jar文件 書寫service代碼: package cn.partner4java.sax.service;import java.io.InputStream;import java.util.List;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import cn.partner4java.sax.bean.Person;public class SAXService public st
20、atic List readXML(InputStream inStream) try SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); /創(chuàng)建解析器 /設(shè)置解析器的相關(guān)特性,/sax/features/namespaces = true 表示開啟命名空間特性 /saxParser.setProperty(/sax/features/namespaces,true); XMLContentHandler handler = new XMLContent
21、Handler(); saxParser.parse(inStream, handler); inStream.close(); return handler.getPersons(); catch (Exception e) e.printStackTrace(); return null; 進(jìn)行單元測試: package cn.partner4java.sax.junit;import java.io.InputStream;import java.util.List;import android.test.AndroidTestCase;import android.util.Log;i
22、mport cn.partner4java.sax.bean.Person;import cn.partner4java.sax.service.SAXService;public class SAXServiceTest extends AndroidTestCase private static String TAG = SAXServiceTest; public void testReadXML() InputStream inStream = this.getClass().getClassLoader().getResourceAsStream(person.xml); List
23、persons = SAXService.readXML(inStream); for(Person person:persons) System.out.println(person.getName(); Log.i(TAG, person.getName(); sax的集體操作大體就如上,沒有什么太難理解的地方,我們重載的那些方法,你不要想著我們是如何去調(diào)用的,不是,他是使用的流程裝載,也就說會安照我們開始解釋的那個幾個方法的作用,安步驟自動往下走,并且方法是重復(fù)調(diào)用的,因為我們xml里面不止一個數(shù)據(jù)。android的單元測試我這里說一下: 因為單元測試也就是黑盒測試吧,有很好的作用,能夠
24、幫助我們?nèi)フ{(diào)試代碼,避免出現(xiàn)很難解決的復(fù)雜錯誤,因為我們基本都是會每隔方法測試后,再繼續(xù)往下寫。 我們在寫j2ee的junit是怎么樣的我就不說了, android里面首先,要配置我們的AndroidManifest.xml 上面targetPackage指定的包要和應(yīng)用的package相同。也就說必須相同,但是我們的單元測試可以放到此包的子包里,外面是不行的。 編寫單元測試代碼(選擇要測試的方法,右鍵點擊“Run As”-“Android Junit Test” ) 你可能看到了我寫了兩種打印的方法: System.out.println(person.getName();Log.i(TAG
25、, person.getName(); System.out.println在老版本的日志里面是不打印的(我現(xiàn)在用的最新版本可以了),所以只能用 Log。但是這兩種打印方式還是都不可以打印中文,會出現(xiàn)亂碼DOM: 除了可以使用 SAX解析XML文件,大家也可以使用熟悉的DOM來解析XML文件。 DOM解析XML文件時,會將XML文件的所有內(nèi)容讀取到內(nèi)存中,然后允許您使用DOM API遍歷XML樹、檢索所需的數(shù)據(jù)。使用DOM操作XML的代碼看起來比較直觀,并且,在某些方面比基于SAX的實現(xiàn)更加簡單。但是,因為DOM需要將XML文件的所有內(nèi)容讀取到內(nèi)存中,所以內(nèi)存的消耗比較大,特別對于運(yùn)行Andr
26、oid的移動設(shè)備來說,因為設(shè)備的資源比較寶貴,所以建議還是采用SAX來解析XML文件,當(dāng)然,如果XML文件的內(nèi)容比較小采用DOM是可行的。 DOM解析就很常見了,我也就不多說了,但是這個方法是不建議使用的,因為他會加載整個xml文件,會消耗更多的系統(tǒng)資源。 import java.io.InputStream;import java.util.ArrayList;import java.util.List;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import
27、 org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;/* * 使用Dom解析xml文件 * */public class DomXMLReader public static List readXML(InputStream inStream) List persons = new ArrayList(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
28、 try DocumentBuilder builder = factory.newDocumentBuilder(); Document dom = builder.parse(inStream); Element root = dom.getDocumentElement(); NodeList items = root.getElementsByTagName(person);/查找所有person節(jié)點 for (int i = 0; i items.getLength(); i+) Person person = new Person(); /得到第一個person節(jié)點 Element
29、 personNode = (Element) items.item(i); /獲取person節(jié)點的id屬性值 person.setId(new Integer(personNode.getAttribute(id); /獲取person節(jié)點下的所有子節(jié)點(標(biāo)簽之間的空白節(jié)點和name/age元素) NodeList childsNodes = personNode.getChildNodes(); for (int j = 0; j childsNodes.getLength(); j+) Node node = (Node) childsNodes.item(j); /判斷是否為元素類型
30、 if(node.getNodeType() = Node.ELEMENT_NODE) Element childNode = (Element) node; /判斷是否name元素 if (name.equals(childNode.getNodeName() /獲取name元素下Text節(jié)點,然后從Text節(jié)點獲取數(shù)據(jù) person.setName(childNode.getFirstChild().getNodeValue(); else if (“age”.equals(childNode.getNodeName() person.setAge(new Short(childNode.
31、getFirstChild().getNodeValue(); persons.add(person); inStream.close(); catch (Exception e) e.printStackTrace(); return persons;pull: 除了可以使用 SAX和DOM解析XML文件,大家也可以使用Android內(nèi)置的Pull解析器解析XML文件。 Pull解析器的運(yùn)行方式與 SAX 解析器相似。它提供了類似的事件,如:開始元素和結(jié)束元素事件,使用parser.next()可以進(jìn)入下一個元素并觸發(fā)相應(yīng)事件。事件將作為數(shù)值代碼被發(fā)送,因此可以使用一個switch對感興趣的
32、事件進(jìn)行處理。當(dāng)元素開始解析時,調(diào)用parser.nextText()方法可以獲取下一個Text類型元素的值。既然android建議我們使用pull,我就詳細(xì)的說一下這個方法吧。 創(chuàng)建android工程,配置可以單元測試的環(huán)境,然后考入我們上面的javabean和xml文件 創(chuàng)建service:package cn.partner4java.pull.service;import java.io.InputStream;import java.util.List;import cn.partner4java.pull.bean.Person;public class PullService p
33、ublic static List readXML(InputStream inStream) return null; 接下啦我們就書寫readXML方法: /獲取xmlpull,我們可以使用android給我們提供的一個簡單獲取類(便于快速獲得pull解析器) XmlPullParser parser = Xml.newPullParser(); /進(jìn)行編碼設(shè)置,把我們需要解析的內(nèi)容給他 parser.setInput(inStream, UTF-8); /獲取事件,就可以觸發(fā)第一解析到的字符對應(yīng)的事件 /他也是采用的流式觸發(fā) int enentType = parser.getEvent
34、Type(); /這個方法是把流事件往后退/ parser.next(); List persons = null; Person person = null; /XmlPullParser.END_DOCUMENT:Logical end of the xml document. Returned from getEventType, next() and nextToken() /when the end of the input document has been reached. /就是判斷這個事件不為文檔末尾事件,我們就循環(huán)下去 while(enentType != XmlPullP
35、arser.END_DOCUMENT) /對事件進(jìn)行判斷 switch (enentType) /是否為開始事件,可以進(jìn)行數(shù)據(jù)初始化處理 case XmlPullParser.START_DOCUMENT: persons = new ArrayList(); break; /是否為開始元素事件,如 /再往下,處理到person id.也會觸發(fā)這個事件 /也就是每解析一個字符就會觸發(fā)這個事件 case XmlPullParser.START_TAG: String tag = parser.getName(); /如果當(dāng)前為person標(biāo)簽,我們需要獲取id值 if(person.equals
36、(tag) person = new Person(); person.setId(new Integer(parser.getAttributeValue(0); else if(person != null) if(name.equals(tag) /parser.nextText(),當(dāng)前為name下一個節(jié)點,為文本 person.setName(parser.nextText(); else if(age.equals(tag) person.setAge(new Short(parser.nextText(); break; /如果解析到person結(jié)束元素事件時,我們就把當(dāng)前的pe
37、rson加到結(jié)合中 if (parser.getName().equalsIgnoreCase(person) & person != null) persons.add(person); person = null; enentType = parser.next(); return persons;然后我們對讀方法進(jìn)行單元測試 package cn.partner4java.pull.junit;import java.io.InputStream;import java.util.List;import cn.partner4java.pull.bean.Person;import cn
38、.partner4java.pull.service.PullService;import android.test.AndroidTestCase;public class PullServiceTest extends AndroidTestCase public void readXML() throws Exception InputStream inStream = this.getClass().getClassLoader().getResourceAsStream(person.xml); List persons = PullService.readXML(inStream); for(Person person:persons) System.out.println(person.getId() + : + person.getName(); 使用Pull解析器生成XML文件: 有些時候,我們需要生成一個XML文件,生成XML文件的方法有很多,如:可以只使用一個StringBuilder組拼XML內(nèi)容,然后把內(nèi)容寫入到文件中;或者使用DOM API生成XML文件,或者也可以使用pull解析器生成XML文件,這里推薦大家使用Pul
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 手術(shù)室護(hù)士工作小結(jié)范文(5篇)
- 我愛讀書演講稿15篇
- 護(hù)理督查工作匯報
- 感恩節(jié)前的精彩講話稿(9篇)
- 情感電臺廣播稿集錦15篇
- 市場營銷畢業(yè)的實習(xí)總結(jié)
- 師德師風(fēng)宣講活動簡報(18篇)
- 初級會計實務(wù)-2021年5月16日上午初級會計職稱考試《初級會計實務(wù)》真題
- 初級會計經(jīng)濟(jì)法基礎(chǔ)-初級會計《經(jīng)濟(jì)法基礎(chǔ)》??荚嚲?17
- 增強(qiáng)現(xiàn)實環(huán)境下前列腺穿刺手術(shù)導(dǎo)航技術(shù)研究
- 搞笑小品劇本《大城小事》臺詞完整版
- 《健康體檢知識》課件
- 《大模型原理與技術(shù)》全套教學(xué)課件
- 2023年護(hù)理人員分層培訓(xùn)、考核計劃表
- 《銷售培訓(xùn)實例》課件
- 生產(chǎn)計劃主管述職報告
- GB/T 44769-2024能源互聯(lián)網(wǎng)數(shù)據(jù)平臺技術(shù)規(guī)范
- 2025年四川省新高考八省適應(yīng)性聯(lián)考模擬演練(二)地理試卷(含答案詳解)
- 【經(jīng)典文獻(xiàn)】《矛盾論》全文
- 部編版語文五年級下冊 第一單元 專項訓(xùn)練課外閱讀(含答案)
- Vue3系統(tǒng)入門與項目實戰(zhàn)
評論
0/150
提交評論