转载请注明出处:http://blog.csdn.net/skyunicorn/article/details/51003177,谢谢
一、概述
在Android中,常见的XML解析器分为三种:SAX解析器、DOM解析器、PULL解析器。
先向大家解释下三种解析器的工作原理及优缺点。
(本文关于简绍三种解析器借鉴于http://blog.csdn.net/liuhe688/article/details/6415593,并对在实战中出现的问题做了一些详解,本文重点讲PULL解析,其他解析请移步上面链接)
1.DOM解析器:(全部读取完成后解析)
DOM(Document Object Model)定义了表示和修改文档所需的对象、这些对象的行为和属性以及这些对象之间的关系。可以把DOM认为是页面上数据和结构的一个树形表示,允许开发人员使用DOM API遍历XML树、检索所需数据。分析该结构通常需要加载整个文档和构造树形结构,然后才可以检索和更新节点信息。
由于DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源。
2.SAX解析器:(逐行解析)
SAX(Simple API for XML)的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。
SAX解析器的优点是解析速度快,占用内存少。非常适合在Android移动设备中使用。
3.PULL解析器:(逐行解析,个人推荐)
PULL解析器的运行方式和SAX类似,都是基于事件的模式。不同的是,在PULL解析过程中,我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码。PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器。
二、使用
现在在工作中接口传数据一般是用json,对于博主这种小白来说,XML用的实在是比较少,但公司要求用XML,就不得不义无反顾的去回顾该知识了。
1.关于XML结构详解
请看http://blog.csdn.net/skyunicorn/article/details/51002970
2.PULL解析
举个例子
<DataTable xmlns="http://tempuri.org/">
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<NewDataSet xmlns="">
<Table diffgr:id="Table1" msdata:rowOrder="0">
<Customer>张三</Customer>
<Tel>110</Tel>
<Address>世贸大厦</Address>
<CompShort>某某集团</CompShort>
</Table>
<Table diffgr:id="Table2" msdata:rowOrder="1">
<Customer>李四</Customer>
<Tel>120</Tel>
<Address>中心医院</Address>
<CompShort>某某集团</CompShort>
</Table>
</NewDataSet>
</diffgr:diffgram>
</DataTable>
首先判断出根节点<NewDataSet></NewDataSet>,中间的<Table></Table>是子节点,然后再中间的就是我们需要解析的属性了。
三、解析
1.我们定义一个Customer对象
/**
* Created by SkyUnicorn on 2016/3/21 14:30.
* <p/>
* 用户信息实例:包括获取地址,客户名,公司名。
*/
public class Customer {
private String CustName; //客户姓名
private String CustTel; //客户手机
private String CompShort; //公司简称
private String Address; //地址
public Customer() {
}
public Customer(String custName, String custTel, String compShort, String address) {
CustName = custName;
CustTel = custTel;
CompShort = compShort;
Address = address;
}
@Override
public String toString() {
return "Customer{" +
"CustName='" + CustName + '\'' +
", CustTel='" + CustTel + '\'' +
", CompShort='" + CompShort + '\'' +
", Address='" + Address + '\'' +
'}';
}
public String getCustName() {
return CustName;
}
public void setCustName(String custName) {
CustName = custName;
}
public String getCustTel() {
return CustTel;
}
public void setCustTel(String custTel) {
CustTel = custTel;
}
public String getCompShort() {
return CompShort;
}
public void setCompShort(String compShort) {
CompShort = compShort;
}
public String getAddress() {
return Address;
}
public void setAddress(String address) {
Address = address;
}
}
2.一个CustParser接口
import com.batar.yjw.callcenter.Bean.Customer;
import java.io.InputStream;
import java.util.List;
/**
* Created by SkyUnicorn on 2016/3/17 16:03.
* <p/>
* Cust接口
*/
public interface CustParser {
/**
* 解析输入流 得到Cust对象集合
*
* @param is
* @return
* @throws Exception
*/
public List<Customer> parse(InputStream is) throws Exception;
}
3.写解析器
import android.util.Xml;
import com.batar.yjw.callcenter.Bean.Customer;
import com.batar.yjw.callcenter.Interface.CustParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
/**
* Pull解析Cust的XML数据
* <p/>
* Created by SkyUnicorn on 2016/3/17 18:05.
*/
public class PullCustParser implements CustParser {
@Override
public List<Customer> parse(InputStream is) throws Exception {
List<Customer> customers = null;
Customer customer = new Customer();//new一个Customer对象
XmlPullParser parser = Xml.newPullParser();//由android.util.Xml创建一个XmlPullParser实例
parser.setInput(is, "UTF-8");//设置输入流,并指明编码方式
int eventType = parser.getEventType(); //获取事件类型
while (eventType != XmlPullParser.END_DOCUMENT) {
//如果还不是结束文档事件,迭代每一个元素
switch (eventType) {
case XmlPullParser.START_DOCUMENT: //开始文档事件,这里是NewDataSet
customers = new ArrayList<Customer>();
break;
case XmlPullParser.START_TAG: //开始元素事件,即每个属性的开始标识
// parser.isEmptyElementTag()
if (parser.getName().equals("Table")) { //pullParser.getName()得到当前指针所指向的节点的名称
customer = new Customer();
} else if (parser.getName().equals("Customer")) {
eventType = parser.next();
customer.setCustName(parser.getText());
} else if (parser.getName().equals("CompShort")) {
eventType = parser.next();
customer.setCompShort(parser.getText());
} else if (parser.getName().equals("Tel")) {
eventType = parser.next();
customer.setCustTel1(parser.getText());
} else if (parser.getName().equals("Address")) {
eventType = parser.next();
customer.setAddress(parser.getText());
}
break;
case XmlPullParser.END_TAG: //结束元素标识,即每个元素的结束标识
if (parser.getName().equals("Table")) {
customers.add(customer);
customer = null;
}
break;
}
eventType = parser.next();
}
return customers;
}
}
至此我们已经写完了解析器
4.XML解析
在此由于我只是写了一个XML的例子,没有具体的XML的url,所以只能给出大体的代码;
解析过程:(AndroidStudio用户建议将网络请求写入子线程,studio比eclipse严格,不允许将耗时写入主线程)
class GetCustThread extends Thread {
@Override
public void run() {
super.run();
try {
String path = MyConstants.URL_GetCust + "strTele=" + Tel; //拼接URL,这里请参照你们自己的Url拼接格式
HttpURLConnection con = (HttpURLConnection) new URL(path).openConnection(); //这里用的是HttpURLConnect,studio把HttpClient认为是过时的方法,我表示不理解
con.setRequestMethod("GET"); //设置连接为GET
con.setConnectTimeout(5000); //连接超时的时间
int i = con.getResponseCode();
if (i == 200) { //当连接成功时解析XML
InputStream is = con.getInputStream();
parser = new PullCustParser();
customers = parser.parse(is);
for (Customer customer : customers) {
Tel= customer.getTel();
CustName = customer.getCustName();
Address = customer.getAddress();
Company = customer.getCompShort();
}
}
}
} catch (Exception e) {
}
}
}
主要的解析过程就是上面了,其他的按大家需求自己改吧。