最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

android編程之XML文件解析方法詳解(附源碼)

 更新時(shí)間:2015年11月13日 12:08:13   投稿:shichen2014  
這篇文章主要介紹了android編程之XML文件解析方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android解析XML文件的sax、pull及Dom三種方法,具有一定參考借鑒價(jià)值,需要的朋友可以參考下

本文實(shí)例講述了android編程之XML文件解析方法。分享給大家供大家參考,具體如下:

在android開發(fā)中,經(jīng)常用到去解析xml文件,常見的解析xml的方式有一下三種:SAX、Pull、Dom解析方式。最近做了一個(gè)android版的CSDN閱讀器,用到了其中的兩種(sax,pull),今天對(duì)android解析xml的這三種方式進(jìn)行一次總結(jié)。

今天解析的xml示例(channels.xml)如下:

<?xml version="1.0" encoding="utf-8"?>
<channel>
<item id="0" url="http://www.baidu.com">百度</item>
<item id="1" url="http://www.qq.com">騰訊</item>
<item id="2" url="http://www.sina.com.cn">新浪</item>
<item id="3" url="http://www.taobao.com">淘寶</item>
</channel>

一、使用sax方式解析

基礎(chǔ)知識(shí):

這種方式解析是一種基于事件驅(qū)動(dòng)的api,有兩個(gè)部分,解析器和事件處理器,解析器就是XMLReader接口,負(fù)責(zé)讀取XML文檔,和向事件處理器發(fā)送事件(也是事件源),事件處理器ContentHandler接口,負(fù)責(zé)對(duì)發(fā)送的事件響應(yīng)和進(jìn)行XML文檔處理。

下面是ContentHandler接口的常用方法

public abstract void characters (char[] ch, int start, int length)

這個(gè)方法來接收字符塊通知,解析器通過這個(gè)方法來報(bào)告字符數(shù)據(jù)塊,解析器為了提高解析效率把讀到的所有字符串放到一個(gè)字符數(shù)組(ch)中,作為參數(shù)傳遞給character的方法中,如果想獲取本次事件中讀取到的字符數(shù)據(jù),需要使用start和length屬性。

public abstract void startDocument () 接收文檔開始的通知

public abstract void endDocument () 接收文檔結(jié)束的通知

public abstract void startElement (String uri, String localName, String qName, Attributes atts) 接收文檔開始的標(biāo)簽

public abstract void endElement (String uri, String localName, String qName) 接收文檔結(jié)束的標(biāo)簽

在一般使用中為了簡(jiǎn)化開發(fā),在org.xml.sax.helpers提供了一個(gè)DefaultHandler類,它實(shí)現(xiàn)了ContentHandler的方法,我們只想繼承DefaultHandler方法即可。

另外SAX解析器提供了一個(gè)工廠類:SAXParserFactory,SAX的解析類為SAXParser 可以調(diào)用它的parser方法進(jìn)行解析。

看了些基礎(chǔ)以后開始上代碼吧(核心代碼,下載代碼在附件)

public class SAXPraserHelper extends DefaultHandler {
 final int ITEM = 0x0005;
 List<channel> list;
 channel chann;
 int currentState = 0;
 public List<channel> getList() {
  return list;
 }
 /*
 * 接口字符塊通知
 */
 @Override
 public void characters(char[] ch, int start, int length)
  throws SAXException {
  // TODO Auto-generated method stub
 // super.characters(ch, start, length);
  String theString = String.valueOf(ch, start, length);
  if (currentState != 0) {
  chann.setName(theString);
  currentState = 0;
  }
  return;
 }
 /*
 * 接收文檔結(jié)束通知
 */
 @Override
 public void endDocument() throws SAXException {
  // TODO Auto-generated method stub
  super.endDocument();
 }
 /*
 * 接收標(biāo)簽結(jié)束通知
 */
 @Override
 public void endElement(String uri, String localName, String qName)
  throws SAXException {
  // TODO Auto-generated method stub
  if (localName.equals("item"))
  list.add(chann);
 }
 /*
 * 文檔開始通知
 */
 @Override
 public void startDocument() throws SAXException {
  // TODO Auto-generated method stub
  list = new ArrayList<channel>();
 }
 /*
 * 標(biāo)簽開始通知
 */
 @Override
 public void startElement(String uri, String localName, String qName,
  Attributes attributes) throws SAXException {
  // TODO Auto-generated method stub
  chann = new channel();
  if (localName.equals("item")) {
  for (int i = 0; i < attributes.getLength(); i++) {
   if (attributes.getLocalName(i).equals("id")) {
   chann.setId(attributes.getValue(i));
   } else if (attributes.getLocalName(i).equals("url")) {
   chann.setUrl(attributes.getValue(i));
   }
  }
  currentState = ITEM;
  return;
  }
  currentState = 0;
  return;
 }
}

private List<channel> getChannelList() throws ParserConfigurationException, SAXException, IOException
 {
  //實(shí)例化一個(gè)SAXParserFactory對(duì)象
  SAXParserFactory factory=SAXParserFactory.newInstance();
  SAXParser parser;
  //實(shí)例化SAXParser對(duì)象,創(chuàng)建XMLReader對(duì)象,解析器
  parser=factory.newSAXParser();
  XMLReader xmlReader=parser.getXMLReader();
  //實(shí)例化handler,事件處理器
  SAXPraserHelper helperHandler=new SAXPraserHelper();
  //解析器注冊(cè)事件
  xmlReader.setContentHandler(helperHandler);
  //讀取文件流
  InputStream stream=getResources().openRawResource(R.raw.channels);
  InputSource is=new InputSource(stream);
  //解析文件
  xmlReader.parse(is);
  return helperHandler.getList();
}

從第二部分代碼,可以看出使用SAX解析XML的步驟:

1、實(shí)例化一個(gè)工廠SAXParserFactory

2、實(shí)例化SAXPraser對(duì)象,創(chuàng)建XMLReader 解析器

3、實(shí)例化handler,處理器

4、解析器注冊(cè)一個(gè)事件

4、讀取文件流

5、解析文件

二、使用pull方式解析

基礎(chǔ)知識(shí):

在android系統(tǒng)中,很多資源文件中,很多都是xml格式,在android系統(tǒng)中解析這些xml的方式,是使用pul解析器進(jìn)行解析的,它和sax解析一樣(個(gè)人感覺要比sax簡(jiǎn)單點(diǎn)),也是采用事件驅(qū)動(dòng)進(jìn)行解析的,當(dāng)pull解析器,開始解析之后,我們可以調(diào)用它的next()方法,來獲取下一個(gè)解析事件(就是開始文檔,結(jié)束文檔,開始標(biāo)簽,結(jié)束標(biāo)簽),當(dāng)處于某個(gè)元素時(shí)可以調(diào)用XmlPullParser的getAttributte()方法來獲取屬性的值,也可調(diào)用它的nextText()獲取本節(jié)點(diǎn)的值。

其實(shí)以上描述,就是對(duì)整個(gè)解析步驟的一個(gè)描述,看看代碼吧

private List<Map<String, String>> getData() {
  List<Map<String, String>> list = new ArrayList<Map<String, String>>();
  XmlResourceParser xrp = getResources().getXml(R.xml.channels);
  try {
  // 直到文檔的結(jié)尾處
  while (xrp.getEventType() != XmlResourceParser.END_DOCUMENT) {
   // 如果遇到了開始標(biāo)簽
   if (xrp.getEventType() == XmlResourceParser.START_TAG) {
   String tagName = xrp.getName();// 獲取標(biāo)簽的名字
   if (tagName.equals("item")) {
    Map<String, String> map = new HashMap<String, String>();
    String id = xrp.getAttributeValue(null, "id");// 通過屬性名來獲取屬性值
    map.put("id", id);
    String url = xrp.getAttributeValue(1);// 通過屬性索引來獲取屬性值
    map.put("url", url);
    map.put("name", xrp.nextText());
    list.add(map);
   }
   }
   xrp.next();// 獲取解析下一個(gè)事件
  }
  } catch (XmlPullParserException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
  } catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
  }
  return list;
}

三、使用Dom方式解析

基礎(chǔ)知識(shí):

最后來看看Dom解析方式,這種方式解析自己之前也沒有用過(在j2ee開發(fā)中比較常見,沒有做過這方面的東西),在Dom解析的過程中,是先把dom全部文件讀入到內(nèi)存中,然后使用dom的api遍歷所有數(shù)據(jù),檢索想要的數(shù)據(jù),這種方式顯然是一種比較消耗內(nèi)存的方式,對(duì)于像手機(jī)這樣的移動(dòng)設(shè)備來講,內(nèi)存是非常有限的,所以對(duì)于比較大的XML文件,不推薦使用這種方式,但是Dom也有它的優(yōu)點(diǎn),它比較直觀,在一些方面比SAX方式比較簡(jiǎn)單。在xml文檔比較小的情況下也可以考慮使用dom方式。

Dom方式解析的核心代碼如下:

public static List<channel> getChannelList(InputStream stream)
{
  List<channel> list=new ArrayList<channel>();
  //得到 DocumentBuilderFactory 對(duì)象, 由該對(duì)象可以得到 DocumentBuilder 對(duì)象
  DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
  try {
  //得到DocumentBuilder對(duì)象
  DocumentBuilder builder=factory.newDocumentBuilder();
  //得到代表整個(gè)xml的Document對(duì)象
  Document document=builder.parse(stream);
  //得到 "根節(jié)點(diǎn)" 
  Element root=document.getDocumentElement();
  //獲取根節(jié)點(diǎn)的所有items的節(jié)點(diǎn)
  NodeList items=root.getElementsByTagName("item"); 
  //遍歷所有節(jié)點(diǎn)
  for(int i=0;i<items.getLength();i++)
  {
   channel chann=new channel();
   Element item=(Element)items.item(i);
   chann.setId(item.getAttribute("id"));
   chann.setUrl(item.getAttribute("url"));
   chann.setName(item.getFirstChild().getNodeValue());
   list.add(chann);
  }
  } catch (ParserConfigurationException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
  } catch (SAXException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
  } catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
  }
  return list;
}

總結(jié)一下Dom解析的步驟(和sax類似)

1、調(diào)用 DocumentBuilderFactory.newInstance() 方法得到 DOM 解析器工廠類實(shí)例。

2、調(diào)用解析器工廠實(shí)例類的 newDocumentBuilder() 方法得到 DOM 解析器對(duì)象

3、調(diào)用 DOM 解析器對(duì)象的 parse() 方法解析 XML 文檔得到代表整個(gè)文檔的 Document 對(duì)象。

四、總結(jié)

除以上三種外還有很多解析xml的方法,比如DOM4J、JDOM等等。但其基本的解析方式包含兩種,一種是事件驅(qū)動(dòng)的(代表SAX),另一種方式是基于文檔結(jié)構(gòu)(代表DOM)。其他的只不過語法不一樣而已。

附(本文示例運(yùn)行截屏):

完整實(shí)例代碼代碼點(diǎn)擊此處本站下載

希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • Android Drawerlayout實(shí)現(xiàn)側(cè)滑菜單效果

    Android Drawerlayout實(shí)現(xiàn)側(cè)滑菜單效果

    這篇文章主要為大家詳細(xì)介紹了Android Drawerlayout實(shí)現(xiàn)側(cè)滑菜單效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Android更多條目收縮展開控件ExpandView的示例代碼

    Android更多條目收縮展開控件ExpandView的示例代碼

    本篇文章主要介紹了Android更多條目收縮展開控件ExpandView的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • Android編程實(shí)現(xiàn)提取網(wǎng)址鏈接的方法

    Android編程實(shí)現(xiàn)提取網(wǎng)址鏈接的方法

    這篇文章主要介紹了Android編程實(shí)現(xiàn)提取網(wǎng)址鏈接的方法,涉及Android針對(duì)字符串的正則匹配操作相關(guān)技巧,需要的朋友可以參考下
    2016-10-10
  • Android實(shí)現(xiàn)橫屏切換科學(xué)計(jì)算器

    Android實(shí)現(xiàn)橫屏切換科學(xué)計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)橫屏切換科學(xué)計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Android處理圖像數(shù)據(jù)轉(zhuǎn)換的各種方法

    Android處理圖像數(shù)據(jù)轉(zhuǎn)換的各種方法

    這篇文章主要介紹了Android處理圖像數(shù)據(jù)轉(zhuǎn)換的各種方法,本文講解了RGB值轉(zhuǎn)Bitmap、Color值轉(zhuǎn)Bitmap、字節(jié)數(shù)組轉(zhuǎn)Bitmap、讀取文件轉(zhuǎn)Bitmap、讀取資源轉(zhuǎn)Bitmap、輸入流轉(zhuǎn)Bitmap等內(nèi)容,需要的朋友可以參考下
    2015-01-01
  • Android處理時(shí)間各種方法匯總

    Android處理時(shí)間各種方法匯總

    這篇文章主要匯總了Android處理時(shí)間的各種方法,如何獲取當(dāng)前時(shí)間,日期之間的比較,如何計(jì)算兩段日期的重合日期等,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Android錄屏功能的實(shí)現(xiàn)

    Android錄屏功能的實(shí)現(xiàn)

    這篇文章主要介紹了Android錄屏功能的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,一起跟隨小編過來看看吧
    2018-05-05
  • 安卓(Android)中如何實(shí)現(xiàn)滑動(dòng)導(dǎo)航

    安卓(Android)中如何實(shí)現(xiàn)滑動(dòng)導(dǎo)航

    導(dǎo)航是移動(dòng)應(yīng)用最重要的方面之一,對(duì)用戶體驗(yàn)是良好還是糟糕起著至關(guān)重要的作用。好的導(dǎo)航可以讓一款應(yīng)用更加易用并且讓用戶快速上手。相反,糟糕的應(yīng)用導(dǎo)航很容易讓人討厭,并遭到用戶的拋棄。
    2014-08-08
  • 一文吃透Hilt自定義與跨壁壘

    一文吃透Hilt自定義與跨壁壘

    這篇文章主要介紹了Hilt自定義與跨壁壘的實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Android NDK開發(fā)(C語言字符串)

    Android NDK開發(fā)(C語言字符串)

    這篇文章主要介紹了Android NDK開發(fā) C語言字符串 ,主要以字符數(shù)組、字符指針及一些字符串常用的方法的方法未來全文展開內(nèi)容,需要的朋友可以參考一下
    2021-12-12

最新評(píng)論

唐海县| 沧源| 垣曲县| 乌海市| 尚义县| 河池市| 军事| 平原县| 望谟县| 巩留县| 扶余县| 安阳县| 门源| 伊金霍洛旗| 株洲市| 蒙自县| 凤翔县| 若羌县| 南木林县| 凉城县| 清河县| 常熟市| 通城县| 湘潭县| 临泉县| 昌乐县| 东乌珠穆沁旗| 淮阳县| 大余县| 桐城市| 淳安县| 集安市| 斗六市| 县级市| 德钦县| 清远市| 台山市| 法库县| 沁阳市| 尼玛县| 务川|