简介
Pull解析XML XmlPullParser解析器的运行方式与SAX解析器相似。它提供了类似的事件(开始元素和结束元素),但需要使用parser.next()方法来提取它们。事件将作为数值代码被发送,因此可以根据不同的事件代码值来进行不同的处理。通过parser.getEventType()方法来取得事件的代码值。 当处于某个元素时可以调用XmlPullParser的getAttributte()方法来获取【属性】的值,也可调用它的nextText()获取本【节点】的值。
具体思路: 1、构建PullXmlParser解析器
XmlPullParser parser = Xml.newPullParser();
或
XmlPullParserFactory fac = XmlPullParserFactory.newInstance();//获取解析器工厂
XmlPullParser parser = fac.newPullParser();//通过解析器工厂获取解析器
2、将xml文档注册到解析器中
parser.setInput(is, "utf-8");
3、触发事件,获得事件类型码
int type = parser.getEventType();
4、针对事件进行具体分析 "name".equals(parser.getName());//判断开始标签元素是否是name parser.getAttributeValue(0);//得到标签的【属性值 】 parser.nextText();//获取下一个Text【节点的值 】
5、触发并进入下一个事件
type = parser.next();
Pull解析和Sax解析不一样的地方有:
- pull读取xml文件后触发相应的事件调用方法返回的是数字
- pull可以在程序中控制想解析到哪里就可以停止解析。
Activity
public class MainActivity extends ListActivity {
private TextView tv_info;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv_info = new TextView(this);// 将内容显示在TextView中
tv_info.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
getListView().addFooterView(tv_info);
String[] array = { "生成xml文件(序列化)", "生成XML的内容", "解析XML文件", };
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new ArrayList<String>(Arrays.asList(array))));
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
switch (position) {
case 0:
try {
ArrayList<SmsInfo> infos = new ArrayList<SmsInfo>();
Random random = new Random();
for (int i = 0; i < 10; i++) {
infos.add(new SmsInfo(random.nextInt(100), "短信" + random.nextBoolean(), "电话:" + i));
}
SmsInfoXmlUtils.xmlSerializer(infos, Environment.getExternalStorageDirectory() + "/sms.xml");
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
break;
case 1:
try {
BufferedReader bufr = new BufferedReader(new FileReader(new File(Environment.getExternalStorageDirectory() + "/sms.xml")));
StringBuffer content = new StringBuffer();
String line = null;
//另外开辟一个缓冲区,存储读取的一行数据,返回包含该行内容的字符串,不包含换行符,如果已到达流末尾,则返回【 null】
while ((line = bufr.readLine()) != null) {
content.append(line);
}
bufr.close();
tv_info.setText(content.toString());
} catch (IOException e1) {
e1.printStackTrace();
}
break;
case 2:
try {
ArrayList<SmsInfo> infos = SmsInfoXmlUtils.xmlParser(new FileInputStream(new File(Environment.getExternalStorageDirectory() + "/sms.xml")));
StringBuffer sb = new StringBuffer();
for (SmsInfo info : infos) {
sb.append(info + "\n");
}
tv_info.setText(sb.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
}
工具类
public class SmsInfoXmlUtils {
/**将传入的数据以XML形式保存到制定的路径上*/
public static void xmlSerializer(ArrayList<SmsInfo> infos, String path) throws IllegalArgumentException, IllegalStateException, IOException {
XmlSerializer xmlSerializer = Xml.newSerializer();
FileOutputStream fos = new FileOutputStream(new File(path));
xmlSerializer.setOutput(fos, "utf-8");
xmlSerializer.startDocument("utf-8", true);// 写入头,指定头部encoding、standalone属性的值
xmlSerializer.startTag(null, "smss");// 写开始标签,定义namespace和标签名
for (SmsInfo info : infos) {
xmlSerializer.startTag(null, "sms");
xmlSerializer.attribute(null, "id", info.id + "");// 写入【属性】名称及属性值
xmlSerializer.startTag(null, "address");
// 写入【节点】名称
xmlSerializer.text(info.address);
// 写入
节点的
值
xmlSerializer.endTag(null, "address");
xmlSerializer.startTag(null, "body");
xmlSerializer.text(info.body);
xmlSerializer.endTag(null, "body");
xmlSerializer.endTag(null, "sms");
}
xmlSerializer.endTag(null, "smss");
xmlSerializer.endDocument();
fos.close();
}
/**参数为一个输入流,返回值为解析此输入流后生成的集合*/
public static ArrayList<SmsInfo> xmlParser(InputStream is) throws Exception {
ArrayList<SmsInfo> infos = null;
SmsInfo info = null;
XmlPullParserFactory fac = XmlPullParserFactory.newInstance();//获取解析器工厂
XmlPullParser parser = fac.newPullParser();//通过解析器工厂获取解析器
parser.setInput(is, "utf-8");//初始化,指定要解析的文件(输入流)及文件的编码方式
int type = parser.getEventType();//获取当前事件的事件类型,类型值在XmlPullParser中均已定义
while (type != XmlPullParser.END_DOCUMENT) {//一直解析文档,直到解析到文档的结束事件
switch (type) {//根据事件的类型执行指定的事件
case XmlPullParser.START_TAG://标签开始
if ("smss".equals(parser.getName())) {//解析到全局开始标签
infos = new ArrayList<SmsInfo>();
} else if ("sms".equals(parser.getName())) {//解析到sms标签
info = new SmsInfo();//创建一个自定义对象,保存信息
info.id = Integer.valueOf(parser.getAttributeValue(0));//得到标签的属性值,注意id是属性值,而下面的body是节点的值
} else if ("body".equals(parser.getName())) {//解析到body节点
info.body = parser.nextText();//nextText()为让解析器指向name节点,并得到name节点的值
} else if ("address".equals(parser.getName())) {
info.address = parser.nextText();
}
break;
case XmlPullParser.END_TAG://标签结束
if ("sms".equals(parser.getName())) {//解析到sms闭合标签
infos.add(info);//将这个城市的天气信息存到集合中
info = null;//清空,节约内存
}
break;
}
type = parser.next();//这一步很重要,该方法返回一个事件码,也是触发下一个事件的方法
}
return infos;//整个文档解析完毕,返回集合
}
}
附件列表