转载:http://www.cnblogs.com/huhx/p/AndroidXmlParse.html
Pull解析的用法:
START_DOCUMENT 文档开始的标签 文档开始时,解析器没有任何数据
START_TAG 解析到标签开头
TEXT 解析到元素的内容
END_TAG 解析在标签末尾
END_DOCUMENT 文档结束,解析器不会再解析
PULL解析的步骤:
建立XML PuLL工厂实例
XmlPullParseFactory factory=XmlPullParseFactory.newInstance();
不指定命名空间,将使用默认的解析器,如果要改变命名空间,则使用setNamespaceAware()这个方法:
factory.setNamespaceAware(true);
创建一个解析的实例:
XmlPullParse xpp=factory.newPullParse();
解析输入的数据:
xpp.setInput(new FileReader(filename));
接下来就可以根据不同的事件,做不同额解析处理:一般用next()方法去得到下一个事件
next()方法与nextToken()方法
next()方法只能支持上述常用的五个事件
nextToken()方法不但支持next()方法的事件,还额外支持:COMMENT CDSECT DECDECL ENTITY_REF ROCESSING_INSTRUCTION, or IGNORABLE_WHITESPACE
我们在assets中创建一个文件:linux.xml
<span style="font-family:Courier New;font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<LOL>
<person>
<!-- 这里是盖伦的注释 -->
<name sex="man">盖伦</name>
<address>德玛西亚</address>
<say>我将带头冲锋</say>
</person>
<person>
<!-- 这里是亚索的注释 -->
<name sex="man">亚索</name>
<address>艾欧尼亚</address>
<say>死亡如风,常伴吾身</say>
</person>
<person>
<!-- 这里是瑞雯的注释 -->
<name sex="girl">瑞雯</name>
<address>诺克萨斯</address>
<say>战争与谋杀之间,潜藏着我们的心魇</say>
</person>
</LOL>
</span>
在MainActivity.java中定义一个方法,得到linux.xml文件的内容
<span style="font-family:Courier New;">// 得到xml的数据
private String getXMLData(String fileName) {
StringBuffer stringBuffer = new StringBuffer();
InputStream inputStream = null;
BufferedReader bufferedReader = null;
try {
inputStream = getResources().getAssets().open(fileName);
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line + "\n");
}
bufferedReader.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Log.i(TAG, stringBuffer.toString());
return stringBuffer.toString();
}</span><span style="font-family:courier new, 微软雅黑, courier, sans-serif;">
</span>
定义一个方法,用PULL解析得到的数据:
<span style="font-family:Courier New;">// pull解析xml数据
public void pullParse(View view) {
String xmlData = getXMLData(fileName);
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(xmlData));
int eventType = xmlPullParser.getEventType();
String name = "";
String address = "";
String say = "";
String sex = "";
while (eventType != XmlPullParser.END_DOCUMENT) {
String nodeName = xmlPullParser.getName();
switch (eventType) {
case XmlPullParser.START_TAG: {
if ("name".equals(nodeName)) {
// sex与name的位置不能互换
// sex = xmlPullParser.getAttributeValue(0);
sex = xmlPullParser.getAttributeValue(null, "sex");
name = xmlPullParser.nextText();
} else if ("address".equals(nodeName)) {
address = xmlPullParser.nextText();
} else if ("say".equals(nodeName)) {
say = xmlPullParser.nextText();
}
break;
}
// 完成解析某个结点
case XmlPullParser.END_TAG: {
if ("person".equals(nodeName)) {
Log.d(TAG, "name: " + name);
Log.d(TAG, "address: " + address);
Log.d(TAG, "say: " + say);
Log.d(TAG, "sex: " + sex);
}
break;
}
default:
break;
}
eventType = xmlPullParser.next();
}
} catch (Exception e) {
e.printStackTrace();
}
}</span>
若要解析到<!-- -->里面的注释内容,需要做以下的修改:增加case,修改next()方法为nextToken()方法:
<span style="font-family:Courier New;">// 增加一个case,用于接收注释的事件
case XmlPullParser.COMMENT: {
coment = xmlPullParser.getText();
break;
}
default:
break;
}
eventType = xmlPullParser.nextToken(); // 此处为修改部分</span>
打印日志如下:(增加了注释的功能)
<span style="font-family:Courier New;">03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: name: 盖伦
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: address: 德玛西亚
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: say: 我将带头冲锋
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: sex: man
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: comment: 这里是盖伦的注释
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: name: 亚索
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: address: 艾欧尼亚
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: say: 死亡如风,常伴吾身
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: sex: man
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: comment: 这里是亚索的注释
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: name: 瑞雯
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: address: 诺克萨斯
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: say: 战争与谋杀之间,潜藏着我们的心魇
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: sex: girl
03-16 18:09:59.662 24745-24745/com.example.linux.xmlparsetest D/MainActivity: comment: 这里是瑞雯的注释 </span>
Sax解析的用法
一、 SAX解析的简要:
SAX:事件驱动型的XML解析方式。顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问,且是只读的。由于移动设备的内存资源有限,SAX的顺序读取方式更适合移动开发。
二、 SAX解析XML步骤:
- 创建XML解析处理器。
- 创建SAX解析器。
- 将XML解析处理器分配给解析器。
- 对文档进行解析,将每个事件发送给处理器。
三、SAX解析的过程:
- 解析开始之前,需要向XMLReader注册一个ContentHandler,也就是相当于一个事件监听器,
- 在ContentHandler中定义了很多方法,比如startDocument(),它定制了当在解析过程中,遇到文档开始时应该处理的事情。
- 当 XMLReader读到合适的内容,就会抛出相应的事件,并把这个事件的处理权代理给ContentHandler,调用其相应的方法进行响应。
<span style="font-family:Courier New;">package com.example.linux.xmlparsetest;
import android.util.Log;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Created by Linux on 2016/3/16.
*/
public class ContentHandler extends DefaultHandler {
private final static String TAG = "MainActivity";
private String nodeName;
private StringBuilder name;
private StringBuilder address;
private StringBuilder say;private StringBuilder sex;
// 文档开始时执行
@Override
public void startDocument() throws SAXException {
name = new StringBuilder();
address = new StringBuilder();
say = new StringBuilder();
sex = new StringBuilder();
coment = new StringBuilder();
}
// 元素开始时执行
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// 记录当前结点名
nodeName = localName;
if (nodeName.equals("name") && attributes != null) {
sex.append(attributes.getValue("sex"));
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// 根据当前的结点名判断将内容添加到哪一个StringBuilder对象中
if ("name".equals(nodeName)) {
name.append(ch, start, length);
} else if ("address".equals(nodeName)) {
address.append(ch, start, length);
} else if ("say".equals(nodeName)) {
say.append(ch, start, length);
}
}
// 元素结束时执行
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("person".equals(localName)) {
Log.d(TAG, "name is " + name.toString().trim());
Log.d(TAG, "adress is " + address.toString().trim());
Log.d(TAG, "say is " + say.toString().trim());
Log.d(TAG, "sex is " + sex.toString().trim());
// 最后要将StringBuilder清空掉
name.setLength(0);
address.setLength(0);
say.setLength(0);
sex.setLength(0);
}
}
// 文档结束时
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
}</span>
在MainActivity中定义方法,进行SAX解析
<span style="font-family:Courier New;">// sax解析数据
public void saxParse(View view) {
String xmlData = getXMLData(fileName);
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
ContentHandler handler = new ContentHandler();
// 将ContentHandler的实例设置到XMLReader中
xmlReader.setContentHandler(handler);
// 开始执行解析
xmlReader.parse(new InputSource(new StringReader(xmlData)));
} catch (Exception e) {
e.printStackTrace();
}
}</span>
打印日志如下:
<span style="font-family:Courier New;">03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: name is 盖伦
03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: adress is 德玛西亚
03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: say is 我将带头冲锋
03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: sex is man
03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: name is 亚索
03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: adress is 艾欧尼亚
03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: say is 死亡如风,常伴吾身
03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: sex is man
03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: name is 瑞雯
03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: adress is 诺克萨斯
03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: say is 战争与谋杀之间,潜藏着我们的心魇
03-16 18:10:55.732 24745-24745/com.example.linux.xmlparsetest D/MainActivity: sex is girl</span>
Sax与Pull的比较:
区别:
- SAX解析器的工作方式是自动将事件推入注册的事件处理器进行处理,因此你不能控制事件的处理主动结束
- PULL解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析
相似性:
Pull解析器也提供了类似SAX的事件,开始文档START_DOCUMENT和结束文档END_DOCUMENT,开始元素START_TAG和结束元素END_TAG,遇到元素内容TEXT等,但需要调用next() 方法提取它们(主动提取事件)。
使用:
如果在一个XML文档中我们只需要前面一部分数据,但是使用SAX方式或DOM方式会对整个文档进行解析,尽管XML文档中后面的大部分数据我们其实都不需要解析,因此这样实际上就浪费了处理资源。使用PULL方式正合适。