大佬教程收集整理的这篇文章主要介绍了详解android使用SAX解析XML文件,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
解析XML的方式有很多种,大家比较熟悉的可能就是DOM解析。
DOM(文件对象模型)解析:解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以根据DOM接口来操作这个树结构了。
优点:整个文档读入内存,方便操作:支持修改、删除和重现排列等多种功能。
缺点:将整个文档读入内存中,保留了过多的不需要的节点,浪费内存和空间。
使用场合:一旦读入文档,还需要多次对文档进行操作,并且在硬件资源充足的情况下(内存,cpu)。
为了解决DOM解析存在的问题,就出现了SAX解析。其特点为:
优点:不用实现调入整个文档,占用资源少。尤其在嵌入式环境中,如android,极力推荐使用SAX解析。
缺点:不像DOM解析一样将文档长期驻留在内存中,数据不是持久的。如果事件过后没有保存数据,数据就会丢失。
使用场合:机器有性能限制。
SAX解析XML文档采用事件驱动模式。什么是事件驱动模式?它将XML文档转换成一系列的事件,由单独的事件处理器来决定如何处理。
基于事件驱动的处理模式主要是基于事件源和事件处理器(或者叫监听器)来工作的。一个可以产生事件的对象叫做事件源,而一个可以针对事件做出响应的对象就被叫做事件处理器。
在SAX接口中,事件源是org.xml.sax包中的XMLReader,他通过parse()方法开始解析XML文档,并根据文档内容产生事件。而事件处理器则是org.xml.sax包中的ContentHandler、DTDHandler、ErrorHandler,以及EntityResolver这四个接口。他们分别处理事件源在解析过程中产生不同类的事件(其中DTDHandler为解析文档DTD时所用)。详细介绍如下表:
在上述四个接口中,最重要的就是ContentHandler这个接口,下面是对这个接口方法的说明:
//设置一个可以定位文档内容事件发生位置的定位器对象 public void setDocumentLocator(Locator locator) //用于处理文档解析开始事件 public void startDocument()throws SAXException //处理元素开始事件,从参数中可以获得元素所在名称空间的uri,元素名称,属性类表等信息 public void startElement(String namespacesURI,String localName,String qName,Attributes atts) throws SAXException //处理元素结束事件,从参数中可以获得元素所在名称空间的uri,元素名称等信息 public void endElement(String namespacesURI,String qName) throws SAXException //处理元素的字符内容,从参数中可以获得内容 public void characters(char[] ch,int start,int length) throws SAXException
这里再介绍下XMLReader中的方法。
//注册处理XML文档解析事件ContentHandler public void setContentHandler(ContentHandler handler) //开始解析一个XML文档 public void parse(InputSorce input) throws SAXException
SAX实现实体解析的步骤:
在Android中使用SAx是有迹可循的,完全可以按照下面的方法就可以轻松找到xml里的tag,然后得到想要的内容。具体实现步骤如下:
(一)第一步:新建一个工厂类SAXParserFactory,代码如下:
SAXParserFactory factory = SAXParserFactory.newInstance();
(二)第二步:让工厂类产生一个SAX的解析类SAXParser,代码如下:
SAXParser parser = factory.newSAXParser();
(三)第三步:从SAXPsrser中得到一个XMLReader实例,代码如下:
XMLReader reader = parser.getXMLReader();
(四)第四步:把自己写的handler注册到XMLReader中,一般最重要的就是ContentHandler,代码如下:
(五)第五步:将一个xml文档或者资源变成一个java可以处理的InputStream流后,解析正式开始,代码如下:
parser.parse(is);
上面几个步骤中,最重要、最关键的就是第四步,handler的实现。
我们先是自己见一个RSS的xml文档,实现本地解析,新建的RSS文档如下:
<?xml version="1.0" encoding="UTF-8"?> <chAnnel> <title>RSS 解析练习</title> <description>hehehaha</description> <link>http://www.cnblogs.com/Felix-hua/</link> <language>zh-cn</language> <item> <title><![CDATA[头条]]></title> <link>http://mc.cz001.com.cn/images/menu/23_active.png</link> <category>0</category> <description>描述详细信息的</description> <pubDate>2012-01-09</pubDate> </item> <item> <title><![CDATA[新闻]]></title> <link>http://mc.cz001.com.cn/images/menu/23_active.png</link> <category>0</category> <description>描述详细信息的</description> <pubDate>2012-01-09</pubDate> </item> <item> <title><![CDATA[首页]]></title> <link>http://mc.cz001.com.cn/images/menu/23_active.png</link> <category>0</category> <description>描述详细信息的</description> <pubDate>2012-01-09</pubDate> </item> <item> <title><![CDATA[财经]]></title> <link>http://mc.cz001.com.cn/images/menu/23_active.png</link> <category>0</category> <description>描述详细信息的</description> <pubDate>2012-01-09</pubDate> </item>
建好后,我们命名为RSSxml.xml,然后放到项目的根目录下:
然后我们可以建立两个@L_489_53@:
这样在解析xml时,我们就可以把解析出来的信息放到@L_489_53@里,然后直接操作@L_489_53@就可以了。下面给出代码:
package com.sax.org.entity; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; public class RSSFeed { private String title; privatE int itemcount; private List<RSSItem> itemlist; public RSSFeed(){ itemlist = new Vector<RSSItem>(0); } /** * 负责将一个RSSItem加入到RSSFeed类中 * @param item * @return */ public int addItem(RSSItem item){ itemlist.add(item); itemcount++; return itemcount; } public RSSItem getItem(int LOCATIOn){ return itemlist.get(LOCATIOn); } public List<RSSItem> getAllItems(){ return itemlist; } /** * 负责从RSSFeed类中生成列表所需要的数据 * @return */ public List getAllItemForListView(){ List<Map<String,Object>> data = new ArrayList<Map<String,Object>>(); int size = itemlist.size(); for(int i=0 ; i<size ; i++){ HashMap<String,Object> item = new HashMap<String,Object>(); item.put(RSSItem.title,itemlist.get(i).gettitle()); item.put(RSSItem.PUBDATE,itemlist.get(i).getPubdate()); data.add(item); } return data; } public String gettitle() { return title; } public void settitle(String titlE) { this.title = title; } public int getItemcount() { return itemcount; } public void setItemcount(int itemcount) { this.itemcount = itemcount; } public List<RSSItem> getItemlist() { return itemlist; } public void setItemlist(List<RSSItem> itemlist) { this.itemlist = itemlist; } }
package com.sax.org.entity; public class RSSItem { public static String titlE = "title"; public static String PUBDATE = "pubdate"; public String title; public String description; public String link; public String category; public String pubdate; public RSSItem() { } public String gettitle() { return title; } public void settitle(String titlE) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getLink() { return link; } public void setLink(String link) { this.link = link; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } public String getPubdate() { return pubdate; } public void setPubdate(String pubdatE) { this.pubdate = pubdate; } }
下面就是最最重要的地方了,建立自己的ContentHandler.看下面的代码:
RSSHandler.java
package com.sax.org.handler; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.Helpers.DefaultHandler; import com.sax.org.entity.RSSFeed; import com.sax.org.entity.RSSItem; public class RSSHandler extends DefaultHandler{ RSSFeed RSSFeed; RSSItem RSSItem; final int RSS_titlE = 1; final int RSS_LINK = 2; final int RSS_DESCRIPTION = 3; final int RSS_CATEGORY = 4; final int RSS_PUBDATE = 5; int currentstate = 0; public RSSHandler(){} public RSSFeed getFeed(){ return RSSFeed; } @Override public void startDocument() throws SAXException { // TODO Auto-generated method stub RSSFeed = new RSSFeed(); RSSItem = new RSSItem(); } @Override public void endDocument() throws SAXException { // TODO Auto-generated method stub } @Override public void startElement(String uri,Attributes attributes) throws SAXException { // TODO Auto-generated method stub if(localName.equals("chAnnel")){ currentstate = 0; return; } if(localName.equals("item")){ RSSItem = new RSSItem(); return; } if(localName.equals("title")){ currentstate = RSS_titlE; return; } if(localName.equals("description")){ currentstate = RSS_DESCRIPTION; return; } if(localName.equals("link")){ currentstate = RSS_LINK; return; } if(localName.equals("category")){ currentstate = RSS_CATEGORY; return; } if(localName.equals("pubDate")){ currentstate = RSS_PUBDATE; return; } currentstate = 0; } @Override public void endElement(String uri,String qName) throws SAXException { // TODO Auto-generated method stub if(localName.equals("item")){ RSSFeed.addItem(RSSItem); return; } } @Override public void characters(char[] ch,int length) throws SAXException { // TODO Auto-generated method stub String theString = new String(ch,start,length); switch(currentstatE){ case RSS_titlE: RSSItem.settitle(theString); currentstate = 0; break; case RSS_DESCRIPTION: RSSItem.setDescription(theString); currentstate = 0; break; case RSS_LINK: RSSItem.setLink(theString); currentstate = 0; break; case RSS_PUBDATE: RSSItem.setPubdate(theString); currentstate = 0; break; case RSS_CATEGORY: RSSItem.setCategory(theString); currentstate = 0; break; default: return; } } }
就上面的代码分析,实现一个ContentHandler一般要一下几个步骤:
1、声明一个类,继承DefaultHandler。DefaultHandler是一个基类,这个类里面简单实现了一个ContentHandler。我们只需要重写里面的方法即可。
2、重写 startDocument() 和 endDocument(),一般解析将正式解析之前的一些初始化工资放到startDocument()里面,收尾的工作放到endDocument()里面。
3、重写startElement(),XML解析器遇到XML里面的tag时就会调用这个函数。经常在这个函数内是通过localName俩进行判断而操作一些数据。
4、重写characters()方法,这是一个回调方法。解析器执行完startElement()后,解析完节点的内容后就会执行这个方法,并且参数ch[]就是节点的内容。这个例子里我们根据currentstate的不同,来判断当前那个tag的内容,并放到合适的@L_489_53@中。
5、重写endElement()方法,这个方法与startElement()相对应,解析完一个tag节点后,执行这个方法。再找个例子中,如果解析一个item结束,就将RSSIiem添加到RSSFeed中。
最后我们实现一个activity来展现解析的结果:
package com.sax.org; import java.io.IOException; import java.net.URL; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Inputsource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import android.app.Activity; import android.os.bundle; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.TextView; import com.sax.org.entity.RSSFeed; import com.sax.org.entity.RSSItem; import com.sax.org.handler.RSSHandler; public class SAXReaderActivity extends Activity { /** Called when the activity is first created. */ public String RSSUrl = "http://mc.cz001.com.cn/a/indexconfig/index.RSS"; public RSSFeed Feed; @Override public void onCreate(Bundle savedInstanceStatE) { super.onCreate(savedInstanceStatE); setContentView(R.layout.main); Feed = getFeed(RSSUrl); showList(); } public RSSFeed getFeed(String RSSUrl) { try { // 这里我们实现了本地解析,所以注掉了这个取网络数据的。 // URL url = new URL(RSSUrl); SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); XMLReader reader = parser.getXMLReader(); RSSHandler handler = new RSSHandler(); reader.setContentHandler(handler); Inputsource is = new Inputsource(this.getClassLoader().getresourceAsStream("RSSxml.xml"));//取得本地xml文件 reader.parse(is); return handler.getFeed(); } 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 null; } public void showList() { ListView RSSlistview = (ListView) findViewById(R.id.RSSList); TextView RSStitle = (TextView) findViewById(R.id.RSStitlE); if (Feed == null) { RSStitle.setText("访问失败..."); return; } SimpleAdapter adapter = new SimpleAdapter(this,Feed.getAllItemForListView(),android.R.layout.simple_list_item_2,new String[] { RSSItem.title,RSSItem.PUBDATE },new int[] { android.R.id.text1,android.R.id.text2 }); RSSlistview.setAdapter(adapter); } }
展示下运行结果:
以上是大佬教程为你收集整理的详解android使用SAX解析XML文件全部内容,希望文章能够帮你解决详解android使用SAX解析XML文件所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。