導(dǎo)航
三種解析XML方法的比較

XML
Android 提供了三種解析XML的方式:SAX(Simple API XML), DOM(Document Object Model), Pull
本文中所用的XML文檔內(nèi)容如下:
<students>
<student>
<name sex="man">小明</name>
<nickName>明明</nickName>
</student>
<student>
<name sex="woman">小紅</name>
<nickName>紅紅</nickName>
</student>
<student>
<name sex="man">小亮</name>
<nickName>亮亮</nickName>
</student>
</students>
第一種、Pull解析方式
1)、創(chuàng)建對應(yīng)XML的Bean對象
public class Student {
private String name;
private String sex;
private String nickName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}
2)、Pull解析
public class pullxml{
public List<Student> pull2xml(InputStream is) throws Exception {
List<Student> list = null;
Student student = null;
//創(chuàng)建xmlPull解析器
XmlPullParser parser = Xml.newPullParser();
///初始化xmlPull解析器
parser.setInput(is, "utf-8");
//讀取文件的類型
int type = parser.getEventType();
//無限判斷文件類型進(jìn)行讀取
while (type != XmlPullParser.END_DOCUMENT) {
switch (type) {
//開始標(biāo)簽
case XmlPullParser.START_TAG:
if ("students".equals(parser.getName())) {
list = new ArrayList<>();
} else if ("student".equals(parser.getName())) {
student = new Student();
} else if ("name".equals(parser.getName())) {
//獲取sex屬性
String sex = parser.getAttributeValue(null,"sex");
student.setSex(sex);
//獲取name值
String name = parser.nextText();
student.setName(name);
} else if ("nickName".equals(parser.getName())) {
//獲取nickName值
String nickName = parser.nextText();
student.setNickName(nickName);
}
break;
//結(jié)束標(biāo)簽
case XmlPullParser.END_TAG:
if ("student".equals(parser.getName())) {
list.add(student);
}
break;
}
//繼續(xù)往下讀取標(biāo)簽類型
type = parser.next();
}
return list;
}}
調(diào)用的時(shí)候只需傳入xmlData即可
List<student> list=pullxml.pull2xml(getResources().getAssets().open("news.xml"));
tv.setText(list.toString());
第二種、SAX解析方式
SAX(Simple API for XML)解析器是一種基于事件的解析器,事件驅(qū)動的流式解析方式是,從文件的開始順序解析到文檔的結(jié)束,不可暫停或倒退。
- 優(yōu)點(diǎn):解析速度快,占用內(nèi)存少。非常適合在Android移動設(shè)備中使用。
- 缺點(diǎn):不會記錄標(biāo)簽的關(guān)系,而要讓你的應(yīng)用程序自己處理,這樣就增加了你程序的負(fù)擔(dān)。
- 工作原理:對文檔進(jìn)行順序掃描,當(dāng)掃描到文檔(document)開始與結(jié)束、元素(element)開始與結(jié)束、文檔 (document)結(jié)束等地方時(shí)通知事件處理函數(shù),由事件處理函數(shù)做相應(yīng)動作,然后繼續(xù)同樣的掃描,直至文檔結(jié)束。
使用步驟:
1. 新建 ContentHanlder 類繼承 DefaultHandler 類,并重寫父類的五個(gè)方法
- startDocument(): 開始解析XML時(shí)調(diào)用
- startElement(): 開始解析某個(gè)結(jié)點(diǎn)時(shí)調(diào)用
- characters(): 在獲取節(jié)點(diǎn)內(nèi)容時(shí)調(diào)用
- endElement(): 在完成解析某個(gè)結(jié)點(diǎn)時(shí)調(diào)用
- endDocument(): 在完成整個(gè)XML解析的時(shí)候調(diào)用
2.創(chuàng)建函數(shù) parseXMLWithSAX
3.調(diào)用函數(shù) parseXMLWithSAX 解析 XML
代碼如下:
新建 ContentHandler 類繼承 DefaultHandler類,重寫五個(gè)父類方法
public class saxxml {
public static List<student> sax2xml(InputStream is) throws Exception {
SAXParserFactory spf = SAXParserFactory.newInstance();
//初始化Sax解析器
SAXParser sp = spf.newSAXParser();
//新建解析處理器
MyHandler handler = new MyHandler();
//將解析交給處理器
sp.parse(is, handler);
//返回List
return handler.getList();
}
public static class MyHandler extends DefaultHandler {
private List<student> list;
private student student;
//用于存儲讀取的臨時(shí)變量
private String tempString;
/**
* 解析到文檔開始調(diào)用,一般做初始化操作
*
* @throws SAXException
*/
@Override
public void startDocument() throws SAXException {
list = new ArrayList<>();
super.startDocument();
}
/**
* 解析到文檔末尾調(diào)用,一般做回收操作
*
* @throws SAXException
*/
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
/**
* 每讀到一個(gè)元素就調(diào)用該方法
*
* @param uri
* @param localName
* @param qName
* @param attributes
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("student".equals(qName)) {
//讀到student標(biāo)簽
student = new student();
} else if ("name".equals(qName)) {
//獲取name里面的屬性
String sex = attributes.getValue("sex");
System.out.println("sex-----"+sex);
student.setSex(sex);
}
super.startElement(uri, localName, qName, attributes);
}
/**
* 讀到元素的結(jié)尾調(diào)用
*
* @param uri
* @param localName
* @param qName
* @throws SAXException
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("student".equals(qName)) {
list.add(student);
}
if ("name".equals(qName)) {
student.setName(tempString);
} else if ("nickName".equals(qName)) {
student.setNiceName(tempString);
}
super.endElement(uri, localName, qName);
}
/**
* 讀到屬性內(nèi)容調(diào)用
*
* @param ch
* @param start
* @param length
* @throws SAXException
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
tempString = new String(ch, start, length);
super.characters(ch, start, length);
}
/**
* 獲取該List
*
* @return
*/
public List<student> getList() {
return list;
}
}
}
調(diào)用的時(shí)候只需傳入xmlData即可
List<student> list=saxxml.sax2xml(getResources().getAssets().open("news.xml"));
tv.setText(list.toString());
【注:在Android API中,另外提供了Android.util.Xml類,同樣可以解析XML文件,使用方法類似SAX,也都需編寫Handler來處理XML的解析,但是在使用上卻比SAX來得簡單 ,如下所示:
以android.util.XML實(shí)現(xiàn)XML解析:
MyHandler myHandler=new MyHandler0;
android.util.Xm1.parse(ur1.openC0nnection().getlnputStream0,Xm1.Encoding.UTF-8,myHandler);】
第三種、Dom解析方式

Paste_Image.png
1)、創(chuàng)建對應(yīng)XML的Bean對象
和第一種一樣這里就不貼了
2)、Dom解析
public List<Student> dom2xml(InputStream is) throws Exception {
//一系列的初始化
List<Student> list = new ArrayList<>();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
//獲得Document對象
Document document = builder.parse(is);
//獲得student的List
NodeList studentList = document.getElementsByTagName("student");
//遍歷student標(biāo)簽
for (int i = 0; i < studentList.getLength(); i++) {
//獲得student標(biāo)簽
Node node_student = studentList.item(i);
//獲得student標(biāo)簽里面的標(biāo)簽
NodeList childNodes = node_student.getChildNodes();
//新建student對象
Student student = new Student();
//遍歷student標(biāo)簽里面的標(biāo)簽
for (int j = 0; j < childNodes.getLength(); j++) {
//獲得name和nickName標(biāo)簽
Node childNode = childNodes.item(j);
//判斷是name還是nickName
if ("name".equals(childNode.getNodeName())) {
String name = childNode.getTextContent();
student.setName(name);
//獲取name的屬性
NamedNodeMap nnm = childNode.getAttributes();
//獲取sex屬性,由于只有一個(gè)屬性,所以取0
Node n = nnm.item(0);
student.setSex(n.getTextContent());
} else if ("nickName".equals(childNode.getNodeName())) {
String nickName = childNode.getTextContent();
student.setNickName(nickName);
}
}
//加到List中
list.add(student);
}
return list;
}