日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Android--解析XML之SAX

發(fā)布時(shí)間:2025/5/22 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android--解析XML之SAX 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

  既然要說(shuō)XML解析,那么先來(lái)聊聊什么是XML。XML,可擴(kuò)展標(biāo)記語(yǔ)言 (Extensible Markup Language) ,用于標(biāo)記電子文件使其具有結(jié)構(gòu)性的標(biāo)記語(yǔ)言,可以用來(lái)標(biāo)記數(shù)據(jù)、定義數(shù)據(jù)類(lèi)型,是一種允許用戶(hù)對(duì)自己的標(biāo)記語(yǔ)言進(jìn)行定義的源語(yǔ)言,這是百度百科的解釋。而XML是一種在Internet中傳輸數(shù)據(jù)的常見(jiàn)格式,它與HTML一樣,都是SGML(標(biāo)準(zhǔn)通用標(biāo)記語(yǔ)言),無(wú)論你是需要通過(guò)Internet訪(fǎng)問(wèn)數(shù)據(jù),或者發(fā)送數(shù)據(jù)給Web服務(wù),都可能需要用到XML的知識(shí)。恰恰Android應(yīng)用程序需要和網(wǎng)絡(luò)交互,否則只是一款單機(jī)的無(wú)互動(dòng)的應(yīng)用程序,所以很可能在Android應(yīng)用程序開(kāi)發(fā)的過(guò)程中使用到XML。

  由于XML的擴(kuò)展性強(qiáng),致使它需要有穩(wěn)定的基礎(chǔ)規(guī)則來(lái)支持?jǐn)U展,該語(yǔ)法規(guī)則需要注意的是:

  • 開(kāi)始和結(jié)束標(biāo)簽匹配。
  • 嵌套標(biāo)簽不能相互嵌套。
  • 區(qū)分大小寫(xiě)。
  • Android中的XML

      Android平臺(tái)最大的優(yōu)勢(shì)在于,上層應(yīng)用基本可以利用Java編程語(yǔ)言開(kāi)發(fā),Java平臺(tái)支持通過(guò)許多不同的方式來(lái)使用XML,并且大多數(shù)與XML相關(guān)的API已經(jīng)在Android系統(tǒng)上得到了完全的支持。但是因?yàn)锳ndroid這個(gè)移動(dòng)設(shè)備的局限性,一般僅考慮使用三種方式解析XML:

  • DOM,Document Object Model,文檔對(duì)象模型方式,解析完的XML將生成一個(gè)樹(shù)狀結(jié)構(gòu)的對(duì)象。
  • SAX,simple API for ?Xml,以事件的形式通知程序,對(duì)XML進(jìn)行解析。
  • XML PULL,類(lèi)似于SAX方式,程序以拉取的方式對(duì)XML進(jìn)行解析。
  • SAX

      SAX是一種以事件驅(qū)動(dòng)的XML API,由它定義的事件流可以指定從解析器傳到專(zhuān)門(mén)的處理程序的代碼的XML結(jié)構(gòu),簡(jiǎn)單來(lái)講,它是解析速度快,占用內(nèi)存少的接解析器,這種解析器比較適合Android等移動(dòng)設(shè)備。

      使用SAX的優(yōu)點(diǎn):

    因?yàn)镾AX的優(yōu)勢(shì)是流的方式處理,當(dāng)遇到一個(gè)標(biāo)簽的時(shí)候,并不會(huì)記錄下之前所碰到的標(biāo)簽。也就是說(shuō),在每個(gè)節(jié)點(diǎn)讀取會(huì)觸發(fā)的startElement()方法中,所能知道的信息,僅僅是當(dāng)前的簽名的名字和屬性,至于標(biāo)簽嵌套的結(jié)構(gòu),上層標(biāo)簽的名字,是否有子元素與其他結(jié)構(gòu)相關(guān)的信息,都是不知道的。 使用SAX解析XML的簡(jiǎn)單步驟:
  • 新建一個(gè)類(lèi)MyHandler,繼承自DefaultHandler,并重寫(xiě)DefaultHandler中的特有方法,解析XML的工作在此類(lèi)中完成。
  • 實(shí)例化一個(gè)SAX解析器的工廠(chǎng)對(duì)象,SAXParserFactory對(duì)象,使用SAXParserFactory.newInstance()方法獲取。
  • 利用SAXParserFactory.newSAXParser()獲得SAX解析器對(duì)象SAXParser。
  • 實(shí)例化MyHandler類(lèi),傳入需要解析的節(jié)點(diǎn)名稱(chēng)。
  • 使用SAXParser.parse()方法設(shè)置待解析的XML流和XML解析對(duì)象。
  • 最后從MyHandler對(duì)象中獲得解析結(jié)果。
  • 現(xiàn)在詳細(xì)講解一下上面提到的類(lèi)的作用。 DefaultHandler類(lèi)是SAX2事件處理程序的默認(rèn)基類(lèi)。它繼承了EntityResolver、DTDHandler、ContentHandler和ErrorHandler這四個(gè)接口。包含這四個(gè)接口的所有方法,所以我們?cè)诰帉?xiě)事件處理程序時(shí),可以不用直接實(shí)現(xiàn)這四個(gè)接口,而繼承該類(lèi),然后重寫(xiě)我們需要的方法。 而在DefaultHandler中的繼承類(lèi)中,具體需要重寫(xiě)的方法有以下幾個(gè):
    • public void startDocument():接受到一個(gè)XML文檔時(shí)候的通知。
    • public void startElement(String uri, String localName, String qName,Attributes attributes):接受到一個(gè)開(kāi)始元素的通知,并且可以在此獲得元素的屬性。
    • public void characters(char[] ch, int start, int length):接收元素中字符數(shù)據(jù)的通知。
    • public void endElement(String uri, String localName, String qName):接收結(jié)束元素的通知。
    • public void endDocument():接受一個(gè)文檔的結(jié)束通知。

      上面一些重寫(xiě)的方法通過(guò)一個(gè)XML文件來(lái)講解一下什么時(shí)候被執(zhí)行。

    <?xml version="1.0" encoding="utf-8"?>?????????????? startDocument
    <persons>????????????????????????????????????????????????????????? startElement
    ?<person id="23">?????????????????????????????????????????????? startElement
    ??<name nameid="1">??????????????????????????????????????????startElement
    ???Jack???????????????????????????????????????????????????????????????? characters
    ??</name>?????????????????????????????????????????????????????????? endElement
    ??<age>?????????????????????????????????????????????????????????????? startElement
    ???21???????????????????????????????????????????????????????????????????characters
    ??</age>?????????????????????????????????????????????????????????????endElement
    ?</person>                     endElement       
    </persons>?                    endElement

      SAXParserFactory類(lèi),定義了一個(gè)工廠(chǎng)API,使應(yīng)用程序能夠配置和獲得基于SAX的解析器以解析XML文檔。它只有一個(gè)prctected的構(gòu)造方法(單例模式),所以需要使用靜態(tài)的newInstance()方法來(lái)回的SAXParserFactory()對(duì)象。使用SAXParserFactory可以通過(guò)調(diào)用.newSAXParser()方法獲得一個(gè)SAXParser,通過(guò)SAXParser對(duì)象可以執(zhí)行parser()方法,通過(guò)傳遞的參數(shù)設(shè)定XML流和解析器類(lèi)。

    示例程序

      現(xiàn)在通過(guò)一個(gè)示例程序來(lái)講解一下SAX是怎么解析XML文件的,這個(gè)示例程序是運(yùn)行在Android平臺(tái)上的,為了模擬真實(shí)情況,在IIS服務(wù)器上放置了一個(gè)靜態(tài)的XML文件,通過(guò)Android程序去讀取XML文件中的內(nèi)容,在這個(gè)示例程序中,讀取person節(jié)點(diǎn)的值。因?yàn)槭茿ndroid程序,所以別忘了賦予其訪(fǎng)問(wèn)網(wǎng)絡(luò)的權(quán)限。

      XML文件內(nèi)容:

    1 <?xml version="1.0" encoding="utf-8"?> 2 <persons> 3 <person id="23"> 4 <name nameid="1">Jack</name> 5 <age>21</age> 6 </person> 7 <person id="20"> 8 <name nameid="2">Dick</name> 9 <age>23</age> 10 </person> 11 </persons>

    ?

      步驟一,DefaultHandler類(lèi)的繼承子類(lèi)MyHandler:

    1 package cn.bgxt.handler; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 7 import org.xml.sax.Attributes; 8 import org.xml.sax.SAXException; 9 import org.xml.sax.helpers.DefaultHandler; 10 11 public class MyHandler extends DefaultHandler { 12 13 private List<HashMap<String, String>> list = null; //解析后的XML內(nèi)容 14 private HashMap<String, String> map = null; //存放當(dāng)前需要記錄的節(jié)點(diǎn)的XML內(nèi)容 15 private String currentTag = null;//當(dāng)前讀取的XML節(jié)點(diǎn) 16 private String currentValue = null;//當(dāng)前節(jié)點(diǎn)的XML文本值 17 private String nodeName = null;//需要解析的節(jié)點(diǎn)名稱(chēng) 18 19 public MyHandler(String nodeName) { 20 // 設(shè)置需要解析的節(jié)點(diǎn)名稱(chēng) 21 this.nodeName = nodeName; 22 } 23 24 @Override 25 public void startDocument() throws SAXException { 26 // 接收文檔開(kāi)始的通知。 27 // 實(shí)例化ArrayList用于存放解析XML后的數(shù)據(jù) 28 list = new ArrayList<HashMap<String, String>>(); 29 } 30 31 @Override 32 public void startElement(String uri, String localName, String qName, 33 Attributes attributes) throws SAXException { 34 // 接收元素開(kāi)始的通知。 35 if (qName.equals(nodeName)) { 36 //如果當(dāng)前運(yùn)行的節(jié)點(diǎn)名稱(chēng)與設(shè)定需要讀取的節(jié)點(diǎn)名稱(chēng)相同,則實(shí)例化HashMap 37 map = new HashMap<String, String>(); 38 } 39 //Attributes為當(dāng)前節(jié)點(diǎn)的屬性值,如果存在屬性值,則屬性值也讀取。 40 if (attributes != null && map != null) { 41 for (int i = 0; i < attributes.getLength(); i++) { 42 //讀取到的屬性值,插入到Map中。 43 map.put(attributes.getQName(i), attributes.getValue(i)); 44 } 45 } 46 //記錄當(dāng)前節(jié)點(diǎn)的名稱(chēng)。 47 currentTag = qName; 48 } 49 50 @Override 51 public void characters(char[] ch, int start, int length) 52 throws SAXException { 53 // 接收元素中字符數(shù)據(jù)的通知。 54 //當(dāng)前節(jié)點(diǎn)有值的情況下才繼續(xù)執(zhí)行 55 if (currentTag != null && map != null) { 56 //獲取當(dāng)前節(jié)點(diǎn)的文本值,ch這個(gè)直接數(shù)組就是存放的文本值。 57 currentValue = new String(ch, start, length); 58 if (currentValue != null && !currentValue.equals("") 59 && !currentValue.equals("\n")) { 60 //讀取的文本需要判斷不能為null、不能等于”“、不能等于”\n“ 61 map.put(currentTag, currentValue); 62 } 63 } 64 //讀取完成后,需要清空當(dāng)前節(jié)點(diǎn)的標(biāo)簽值和所包含的文本值。 65 currentTag = null; 66 currentValue = null; 67 } 68 69 @Override 70 public void endElement(String uri, String localName, String qName) 71 throws SAXException { 72 // 接收元素結(jié)束的通知。 73 if (qName.equals(nodeName)) { 74 //如果讀取的結(jié)合節(jié)點(diǎn)是我們需要關(guān)注的節(jié)點(diǎn),則把map加入到list中保存 75 list.add(map); 76 //使用之后清空map,開(kāi)始新一輪的讀取person。 77 map = null; 78 } 79 } 80 81 public List<HashMap<String, String>> getList() { 82 return list; 83 } 84 85 }

      因?yàn)閄ML文件是放在服務(wù)器上的,需要寫(xiě)一個(gè)HttpUitils類(lèi)讀取服務(wù)器上XML文件,使用的是URLHttpConnection的方式讀取,如果不了解URLHttpConnection的朋友,可以看之前的博客:http://www.cnblogs.com/plokmju/p/java-HTTP.html。下面直接附上代碼:

    1 package cn.bgxt.http; 2 3 import java.io.InputStream; 4 import java.net.HttpURLConnection; 5 import java.net.URL; 6 7 public class HttpUtils { 8 9 public HttpUtils() { 10 } 11 public static InputStream getXML(String path) { 12 try { 13 URL url=new URL(path); 14 if(url!=null) 15 { 16 HttpURLConnection connection=(HttpURLConnection)url.openConnection(); 17 connection.setDoInput(true); 18 connection.setConnectTimeout(3000); 19 connection.setRequestMethod("GET"); 20 int requesetCode=connection.getResponseCode(); 21 if(requesetCode==200) 22 { 23 //如果執(zhí)行成功,返回HTTP響應(yīng)流 24 return connection.getInputStream(); 25 } 26 } 27 } catch (Exception e) { 28 // TODO: handle exception 29 } 30 return null; 31 } 32 }

      還需要一個(gè)調(diào)用SAXParser對(duì)象的類(lèi),這里新建一個(gè)SaxService類(lèi),實(shí)例化SAXParserFactory用于設(shè)定XML流和解析器。代碼如下:

    1 package cn.bgxt.service; 2 3 import java.io.InputStream; 4 import java.util.HashMap; 5 import java.util.List; 6 7 import javax.xml.parsers.SAXParser; 8 import javax.xml.parsers.SAXParserFactory; 9 10 import cn.bgxt.handler.MyHandler; 11 12 public class SaxService { 13 14 public SaxService() { 15 // TODO Auto-generated constructor stub 16 } 17 18 public static List<HashMap<String, String>> readXML(InputStream inputStream,String nodeName) 19 { 20 try { 21 //實(shí)例化SAX工廠(chǎng)類(lèi) 22 SAXParserFactory factory=SAXParserFactory.newInstance(); 23 //實(shí)例化SAX解析器。 24 SAXParser sParser=factory.newSAXParser(); 25 //實(shí)例化DefaultHandler,設(shè)置需要解析的節(jié)點(diǎn) 26 MyHandler myHandler=new MyHandler(nodeName); 27 // 開(kāi)始解析 28 sParser.parse(inputStream, myHandler); 29 // 解析完成之后,關(guān)閉流 30 inputStream.close(); 31 //返回解析結(jié)果。 32 return myHandler.getList(); 33 } catch (Exception e) { 34 // TODO: handle exception 35 } 36 return null; 37 } 38 39 }

     最后就是Android的一個(gè)Activity類(lèi)了,布局界面很簡(jiǎn)單,只有一個(gè)按鈕控件,這里不展示布局代碼了。點(diǎn)擊按鈕后,觸發(fā)點(diǎn)擊事件,因?yàn)槭茿ndroid4.0+,所以不能在主線(xiàn)程中訪(fǎng)問(wèn)網(wǎng)絡(luò),需要另起一個(gè)線(xiàn)程,這里使用Thread類(lèi)。代碼如下: 

    1 package cn.bgxt.androidxmlforsax; 2 3 import java.io.InputStream; 4 import java.util.HashMap; 5 import java.util.List; 6 import cn.bgxt.http.HttpUtils; 7 import cn.bgxt.service.SaxService; 8 import android.os.Bundle; 9 import android.app.Activity; 10 import android.view.Menu; 11 import android.view.View; 12 import android.widget.Button; 13 14 public class MainActivity extends Activity { 15 private Button btn; 16 @Override 17 protected void onCreate(Bundle savedInstanceState) { 18 super.onCreate(savedInstanceState); 19 setContentView(R.layout.activity_main); 20 21 btn=(Button)findViewById(R.id.btn); 22 btn.setOnClickListener(new View.OnClickListener() { 23 24 @Override 25 public void onClick(View v) { 26 //Android4.0+需要另起線(xiàn)程訪(fǎng)問(wèn)網(wǎng)絡(luò) 27 Thread thread=new Thread(new Runnable() { 28 29 @Override 30 public void run() { 31 // 設(shè)置XML文檔的位置 32 String path="http://192.168.1.107:1231/persons.xml"; 33 //讀取服務(wù)器上的XML,獲取XML流 34 InputStream inputStream=HttpUtils.getXML(path); 35 try { 36 //解析流,設(shè)定需要解析的節(jié)點(diǎn) 37 List<HashMap<String, String>> list=SaxService.readXML(inputStream, "person"); 38 for(HashMap<String,String> map:list) 39 { 40 //打印到LogCat中 41 System.out.println(map.toString()); 42 } 43 } catch (Exception e) { 44 // TODO: handle exception 45 } 46 } 47 }); 48 thread.start(); 49 } 50 }); 51 } 52 53 @Override 54 public boolean onCreateOptionsMenu(Menu menu) { 55 // Inflate the menu; this adds items to the action bar if it is present. 56 getMenuInflater().inflate(R.menu.main, menu); 57 return true; 58 } 59 60 }

    ?  當(dāng)點(diǎn)擊后,XML解析后的內(nèi)容會(huì)把打印到日志中,可以使用LogCat查看。


    本文轉(zhuǎn)自承香墨影博客園博客,原文鏈接:http://www.cnblogs.com/plokmju/p/android_XMLForSAX.html,如需轉(zhuǎn)載請(qǐng)自行聯(lián)系原作者


    總結(jié)

    以上是生活随笔為你收集整理的Android--解析XML之SAX的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。