android XML文件解析之 SAX解析方法

在学习android几天之后,看到Mars老师的视频,而且在网上也查过很多资料,对xml文件的解析稍稍有了一些了解,记录一下,以后自己可以回来卡看。。

首先是解析函数,这个函数传进一个url地址,自己封装一下,以后用的方便些

private void XMLPrase(String path) {
     HttpDownloader hd = new HttpDownloader();
  String resultStr = hd.download(path);
  //输出整个下载到的标签
  System.out.println(resultStr);
  try{
   //创建一个SAXParserFactory
   SAXParserFactory factory = SAXParserFactory.newInstance();
   XMLReader reader = factory.newSAXParser().getXMLReader();
   //为XMLReader设置内容处理器
   reader.setContentHandler(new MyContentHandler());
   //开始解析文件
   reader.parse(new InputSource(new StringReader(resultStr))); 
  }
  catch(Exception e){
   e.printStackTrace();
  }
 }

HttDownloader类封装了download函数,这个函数传入url参数,用于下载网上的xml文件,函数将下载的文件通过stringbuffer在转化为字串,把整个文件放入到一个string字串中,得到了字串文件后,再要解析就OK了。download函数代码还是贴一下吧

public String download(String urlStr) {
  StringBuffer sb = new StringBuffer();
  String line = null;
  BufferedReader buffer = null;
  try {
   // 创建一个URL对象
   url = new URL(urlStr);
   // 创建一个Http连接
   HttpURLConnection urlConn = (HttpURLConnection) url
     .openConnection();
   // 使用IO流读取数据
   buffer = new BufferedReader(new InputStreamReader(urlConn
     .getInputStream()));
   while ((line = buffer.readLine()) != null) {
    sb.append(line);
   }
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   try {
    buffer.close();
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
  return sb.toString();
 }


stringbuffer用起来还是挺方便的,转为string非常轻松。那接下来就开始解析了,解析中要用到contenthandler,通过覆盖其中一些函数来解析标签,解析文档,当然咯,大家都知道contenthandler这个接口里面函数很多,直接用这个接口没必要嘛,所以就换种方法,继承他的子类DefaultHandler,然后自己覆盖几个需要用到的函数,这样就简单而且比较清晰了

package dai.xml;

import java.util.ArrayList;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MyContentHandler extends DefaultHandler{
 private String tagName=null;
 //构建一个放路线上站点的数据类
 private RouteData routeData=new RouteData();
 //暂时存放线路上的站点的一些信息
 private ArrayList<String>stopTag=new ArrayList<String>();
 private ArrayList<String>stopTitle=new ArrayList<String>();
 private ArrayList<String>stopLat=new ArrayList<String>();
 private ArrayList<String>stopLon=new ArrayList<String>();

 @Override
 public void characters(char[] ch, int start, int length)
   throws SAXException {
  // TODO Auto-generated method stub
  super.characters(ch, start, length);
 }

 @Override
 public void endDocument() throws SAXException {
  // TODO Auto-generated method stub
  System.out.println("end------------>");
  System.out.println(routeData.toString());
  super.endDocument();
 }

 @Override
 public void endElement(String uri, String localName, String qName)
   throws SAXException {
  // 标签解析完毕
  if (localName.equals("route")) {
   routeData.setStopTag(stopTag);//最后一次添加到对象中去
   routeData.setStopTitle(stopTitle);
   routeData.setStopLat(stopLat);
   routeData.setStopLon(stopLon);
  }
  //System.out.println("endlelement-------------->");  
  super.endElement(uri, localName, qName);
 }

 @Override
 public void startDocument() throws SAXException {
  // TODO Auto-generated method stub
  System.out.println("start------------->");
  super.startDocument();
 }
 //开始解析标签
 @Override
 public void startElement(String uri, String localName, String qName,
   Attributes attributes) throws SAXException {
  // TODO Auto-generated method stub
  tagName=localName;
  //System.out.println("startelement------>" +localName);
  //解析这条路线的基本信息,路线标签,名字,最大的经纬度
  if(tagName.equals("route"))
     {
   //只会发生一次
   routeData.setRouteTag(attributes.getValue(0));
      routeData.setRouteTitle(attributes.getValue(1));
      routeData.setRoutelatMin(attributes.getValue(4));
      routeData.setRoutelatMax(attributes.getValue(5));
      routeData.setRoutelonMin(attributes.getValue(6));
      routeData.setRoutelonMax(attributes.getValue(7));
     }
  if (localName.equals("stop")) {
   //System.out.println("进入stop");
   //会有很多次,最后一次再添加的话会更有效率的吧
   stopTag.add(attributes.getValue(0));
   stopTitle.add(attributes.getValue(1));
   stopLat.add(attributes.getValue(2));
   stopLon.add(attributes.getValue(3));   
  }
  //System.out.println("startelement------>");
  super.startElement(uri, localName, qName, attributes);
 }

}

每个函数的作用就不说了,看看字面意思就知道了,解析的大概过程都一样,覆盖的几个函数都是这样,但是往往错误就发生在具体的某个xml文件的标签配对问题上。上次就是在characters函数中把一个标签单词拼错了,搞了一下午都没发现。。郁闷死了,所以啊,还是提醒自己一定要仔细仔细再仔细吧。具体xml文件具体分析吧

这次解析的xml文件是一条公交路线的站点信息,http://webservices.nextbus.com/service/publicXMLFeed?command=routeConfig&a=sf-muni&r=N这里也贴一下把,xml文件就这样,所以characters里面就用不着不写了。。能搞定就行吧。

在数据的存放上,学习了Mars老师的存放数据的方法,不错不错,大家也值得借鉴,话不多说,先贴上~~

package dai.xml;

import java.util.ArrayList;
/*
 *
 * 此类包含了解析路线xml文件后路线上的站点信息,名称 方位 经纬度等
 *
 */
public class RouteData {
 private String RouteTag=null;
 private String RouteTitle=null;
 private String RoutelatMin=null;
 private String RoutelatMax=null;
 private String RoutelonMin=null;
 private String RoutelonMax=null;
 private ArrayList<String>stopTag;
 public RouteData() {
  super();
 }
 private ArrayList<String>stopTitle;
 private ArrayList<String>stopLat;
 private ArrayList<String>stopLon;
 
 public String getRouteTag() {
  return RouteTag;
 }
 public void setRouteTag(String routeTag) {
  RouteTag = routeTag;
 }
 public String getRouteTitle() {
  return RouteTitle;
 }
 @Override
 public String toString() {
  return "RouteData [RouteTag=" + RouteTag + ", RouteTitle=" + RouteTitle
    + ", RoutelatMin=" + RoutelatMin + ", RoutelatMax="
    + RoutelatMax + ", RoutelonMin=" + RoutelonMin
    + ", RoutelonMax=" + RoutelonMax + ", stopTag=" + stopTag
    + ", stopTitle=" + stopTitle + ", stopLat=" + stopLat
    + ", stopLon=" + stopLon + ", stopID=" + stopID + "]";
 }
 public void setRouteTitle(String routeTitle) {
  RouteTitle = routeTitle;
 }
 public String getRoutelatMin() {
  return RoutelatMin;
 }
 public void setRoutelatMin(String routelatMin) {
  RoutelatMin = routelatMin;
 }
 public String getRoutelatMax() {
  return RoutelatMax;
 }
 public void setRoutelatMax(String routelatMax) {
  RoutelatMax = routelatMax;
 }
 public String getRoutelonMin() {
  return RoutelonMin;
 }
 public void setRoutelonMin(String routelonMin) {
  RoutelonMin = routelonMin;
 }
 public String getRoutelonMax() {
  return RoutelonMax;
 }
 public void setRoutelonMax(String routelonMax) {
  RoutelonMax = routelonMax;
 }
 public ArrayList<String> getStopTag() {
  return stopTag;
 }
 public void setStopTag(ArrayList<String> stopTag) {
  this.stopTag = stopTag;
 }
 public ArrayList<String> getStopTitle() {
  return stopTitle;
 }
 public void setStopTitle(ArrayList<String> stopTitle) {
  this.stopTitle = stopTitle;
 }
 public ArrayList<String> getStopLat() {
  return stopLat;
 }
 public void setStopLat(ArrayList<String> stopLat) {
  this.stopLat = stopLat;
 }
 public ArrayList<String> getStopLon() {
  return stopLon;
 }
 public void setStopLon(ArrayList<String> stopLon) {
  this.stopLon = stopLon;
 }
 public ArrayList<String> getStopID() {
  return stopID;
 }
 public void setStopID(ArrayList<String> stopID) {
  this.stopID = stopID;
 }
 private ArrayList<String>stopID;

}

 方法就是新建一个RouteData类,包含了几个数据成员,按照xml文件中的标签来定数据成员的,用来存放解析得到的数据的嘛。类中的几个arraylist存放了tag,title,latitude,lontitude的数据,大小都是一样的,用起来很方便。然后就是搞了一些set,get方法来设定或者得到数据,用eclipse生成下很快的。测试的时候就用个tostring方法,方便快捷。

新建RouteData类的好处就是数据存取就方便了嘛,如果其他地方还要用到数据的话,直接构造一个RouteData对象,在endelement()或者自己觉得能行的地方传递下就行,能轻松把数据传递到当前activity类中,挺好的选择。

最后要说下的就是androidmanifest里面的权限吧,解析的话貌似没什么特别要求,就是要下载的话加上<uses-permission android:name="android.permission.INTERNET"/>咯。OK,就这样。

你可能感兴趣的:(android,xml,exception,String,download,attributes)