Android学习笔记(八)XML文档的解析
一、廢話
最近幾天四川一直下雨,冷!今天到成都的時候,下午3點多的天和晚上天差不多,黑呼呼的... ...難道傳說的2012來了?哈哈哈... ...
二、正文
在上一篇筆記中提到過說在Android系統(tǒng)中,存儲數(shù)據(jù)的方式除了SQLite外,還有很多其他的方式,比較常用的就是XML方式。在Android中,比較常用的XML解析方式有SAX方式和DOM方式。下面就來看看這兩種方式吧。
1、 SAX解析
SAX——Simple API for XML,在org.xml.sax包中被提供使用。SAX是基于事件驅(qū)動的,有事件就一定有事件源,這個事件源就是SAX解析XML時的一個XMLReader對象。當(dāng)XMLReader對象讀取到XML文件的開始和結(jié)束標(biāo)簽時或者在取到一個節(jié)點內(nèi)容時,都會觸發(fā)在Handler(事件處理器)中注冊的相應(yīng)事件。
在XMLReader中可以通過setContentHandler(ContentHandler handler)方法來調(diào)用我們自己的Handler,而這個Handler就是我們解析XML文件的核心。我們可以通過繼承SDK中的DefaultHandler類來實現(xiàn)一個我們自己的Handler。針對我們今天的主題,主要需要實現(xiàn)以下幾個方法。
- public void startDocument() throws SAXException{}——讀取到文檔時觸發(fā)的事件,通常可以通過這個事件來處理一些IO錯誤之類的事情。
- public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException{}——讀取到XML文檔內(nèi)容中的標(biāo)簽時觸發(fā),如<work></work>中的<work>標(biāo)簽。
- uri? XML文檔中NameSpace的URI,如果不清楚XML文檔中Namespace的可以去網(wǎng)上看看。
- localName? 無前綴的標(biāo)簽名,如<works><work></work></works>標(biāo)簽,返回的可以是work字符串。
- qName? 有前綴具有完整路徑的標(biāo)簽名,如<works><work></work></works>中返回的是/works/work字符串。
- attributes? 標(biāo)簽中的屬性名,如<work id=”111”></work>這里面的id就是屬性,而”111”就是屬性值。
- public void endElement(String uri, String localName, String qName)throws SAXException{}——讀取到XML文檔內(nèi)容中的結(jié)束標(biāo)簽時觸發(fā)。
- public void endDocument() throws SAXException{}——讀取到XML文檔結(jié)尾時觸發(fā)該事件。
- public void characters(char[] ch, int start, int length)throws SAXException{}——讀取到XML文檔某個標(biāo)簽下的內(nèi)容時,就會調(diào)用這個方法返回該內(nèi)容。
- ch? 內(nèi)容的字符值。
- start?? 讀取的開始位置。
- length? 讀取的內(nèi)容長度。
a) 現(xiàn)在來理下要解析XML文檔的整個思路
-
- 新建一個SAXParserFactory對象,通過該對象的newSAXParser()方法來獲得一個SAXParser對象。
- 通過SAXParser對象的getXMLReader()方法來獲得一個XMLReader對象。
- 利用XMLReader對象的setConentHandler()方法來注冊一個我們自己的Handler對象。
- 利用XMLReader對象的parse()方法來開始處理我們的XML文檔。
- 實現(xiàn)自己的Handler類。
b) 普通方式下的解析
1 package LiB.XMLDemo;2
3 import org.xml.sax.Attributes;
4 import org.xml.sax.SAXException;
5 import org.xml.sax.helpers.DefaultHandler;
6
7 public class SAXHandler extends DefaultHandler {
8
9 String tagName;
10 //當(dāng)有值存在時,就調(diào)用該方法解析取值(如果是空值,也會調(diào)用這個方法)
11 @Override
12 public void characters(char[] ch, int start, int length)
13 throws SAXException {
14 String value= new String(ch, start,length);
15 if(tagName.equals("name"))
16 {
17 System.out.println("name="+ value);
18 }
19 if(tagName.equals("age"))
20 {
21 System.out.println("age="+value);
22 }
23 }
24
25 @Override
26 public void endDocument() throws SAXException {
27
28 System.out.println("---end----");
29 }
30
31 @Override
32 public void endElement(String uri, String localName, String qName)
33 throws SAXException {
34 if(localName.equals("work"))
35 {
36 System.out.println("-----end----work");
37 }
38 }
39
40 @Override
41 public void startDocument() throws SAXException {
42
43 System.out.println("---begin----");
44 }
45
46 @Override
47 public void startElement(String uri, String localName, String qName,
48 Attributes attributes) throws SAXException {
49 tagName = localName;
50 if(localName.equals("work"))
51 {
52 for(int i=0;i< attributes.getLength();i++)
53 {
54 System.out.println(attributes.getLocalName(i)+"="+attributes.getValue(i));
55 }
56 }
57 }
58
59 }
上面這個方法中存在一個問題:在讀取出來的數(shù)據(jù)中,沒區(qū)分開始標(biāo)簽和結(jié)束標(biāo)簽,所以出現(xiàn)了空值的狀況。這個問題我一直都很奇怪,因為在不久前我處理的時候是不存在這個問題的,可是現(xiàn)在出現(xiàn)了。
c) 改進后的解析
解決的方法在網(wǎng)上也挺多的,而且大家都比較相似,就是在startElement和endElement方法中設(shè)置相應(yīng)的標(biāo)志位,然后在characters方法中通過標(biāo)志位來決定是否需要讀取它的內(nèi)容。
修改后的方法有興趣的朋友可以把源碼下載下來看看。
2、 DOM解析
DOM方式解析XML文件呢,就需要將整個XML文檔裝入我們的手機內(nèi)存中,如果文檔過大,那么將非常的耗費內(nèi)存,但是這樣的好處是解析速度很快,同時DOM解析方式可以只解析你需要的那個部分,靈活性非常大。
DOM解析的原理呢,其實就是把動過DOM API訪問XML文檔的樹形結(jié)構(gòu),并獲取相應(yīng)的數(shù)據(jù)。在java中通過DOM解析XML文件,一般會涉及到以下幾個類。
- DocumentBuilderFactory——創(chuàng)建DocumentBuilder對象的工廠類。
- DocumentBuilder——通過這個方法可以創(chuàng)建一個能夠獲取Document實例的API。
- Document——加載XML文檔的入口,這是解析文檔的源所在。
- Element——元素,在DOM中,所有的節(jié)點都可以稱作Element。
- NodeList——節(jié)點的集合。
來看看通過DOM方式解析XML文檔的步驟吧:
- 通過javax.xml.parsers包中的DocumentBuilderFactory類的newInstance()方法新建一個DocumentBuilderFactory對象。
- 通過DocumentBuilderFactory對象的newDocumentBuilder ()方法創(chuàng)建一個DoucumentBuilder對象。
- 通過DoucumentBuilder的parse()方法讀取外部流來創(chuàng)建一個Document對象。
- 通過Document對象來獲得文檔中的所有節(jié)點的根節(jié)點。
- 通過根節(jié)點來解析所需要的文件內(nèi)容。
2
3
4 import javax.xml.parsers.DocumentBuilder;
5 import javax.xml.parsers.DocumentBuilderFactory;
6
7 import org.w3c.dom.Document;
8 import org.w3c.dom.Element;
9 import org.w3c.dom.Node;
10 import org.w3c.dom.NodeList;
11 import org.xml.sax.InputSource;
12
13 public class DomHandler {
14 public static void GetStringFromDom(InputSource inputSource) {
15 try {
16 DocumentBuilderFactory factory = DocumentBuilderFactory
17 .newInstance();
18 DocumentBuilder builder = factory.newDocumentBuilder();
19 Document document = builder.parse(inputSource);
20 //獲取根節(jié)點
21 Element rootElement = document.getDocumentElement();
22 //獲取第一級子節(jié)點
23 NodeList nodeList = rootElement.getElementsByTagName("work");
24 for(int i=0 ; i<nodeList.getLength();i++)
25 {
26 //String work = rootElement.getElementsByTagName("name").item(0).getFirstChild().getNodeValue();
27
28 Element workElement = ((Element)nodeList.item(i));
29 //獲取節(jié)點中的屬性值
30 //String attr= workElement.getAttribute("XXX");
31 //通過節(jié)點的標(biāo)簽名字來獲取值
32 String name = workElement.getElementsByTagName("name").item(0).getFirstChild().getNodeValue();
33 String age = workElement.getElementsByTagName("age").item(0).getFirstChild().getNodeValue();
34 System.out.println("name="+name);
35 System.out.println("age="+age);
36 }
37
38 } catch (Exception e) {
39 }
40 }
41 }
其實是用DOM方式來解析XML文件,有一些.NET和java開發(fā)經(jīng)驗的同學(xué)看到上面的代碼都應(yīng)該非常親切,因為這和在.NET和java中相似。
3、 二者區(qū)別
SAX——流式解析,通過事件模型解析XML文件,對內(nèi)存消耗比較小。但是只能順序解析,也就是說如果你需要的數(shù)據(jù)在文件的末尾,那么你將需要把整個XML文件全部解析才能得到你想要的數(shù)據(jù)。
Dom解析——符合W3C標(biāo)準(zhǔn)的一種解析方式。解析速度非常快。在幾乎所有的語言中,都能使用,可以解析你所需要的數(shù)據(jù)(不管這個數(shù)據(jù)在文件中間還是文件末尾)。但是這個需要全部加載進系統(tǒng)內(nèi)存中才能進行解析。
?三、總結(jié)
這這個筆記中介紹了兩種解析XML文檔的方法。從下篇筆記開始,我將介紹如何與藍牙、WIFI、網(wǎng)絡(luò)傳輸相關(guān)的一些知識。
【源碼下載】
轉(zhuǎn)載于:https://www.cnblogs.com/cxcco/archive/2012/01/10/2318420.html
總結(jié)
以上是生活随笔為你收集整理的Android学习笔记(八)XML文档的解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JS信用卡真实利率计算器
- 下一篇: Android代码中实现关机