在学习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,就这样。