关于xml文件的解析感觉忘得差不多了,还是记录一下学习笔记方便以后查看。
参考地址:(1)、http://blog.csdn.net/zzp16/article/details/7795410(2)、点击打开链接
在android中常见的解析方法有三种,DOM、SAX和PULL解析。其中DOM解析是先将xml文件读入内存再通过接口获取数据,该方法适用比较小的xml文件,对于大文件效率会跟不上,SAX和PULL解析都是通过事件驱动方式来进行解析,android中的事件机制基于回调函数。
本文主要讲解SAX和PULL解析。
xml文件一般存放在assets目录、res/xml或res/raw文件夹下,
(1)、assets目录用于存放需要打包到应用程序的静态文件,以便部署到设备上去,支持任意深度的子目录,不能通过R类来访问,访问形式如:
InputStream is=this.getResources().getAssets().open(fileName);
(2)、res/xml中的文件和其他资源文件一样,会被编译成二进制格式放到最终的安装包里,可以通过R类来访问其中的文件,如:
XmlResourceParser parser=this.getResources().getXml(R.xml.XXX);
其中,XmlResourceParser是XmlPullParser的子类。
(3)、res/raw中的文件会原封不动的复制到设备上,不会被编译成二进制格式,也可以通过R类来访问,如:
InputStream is=this.getResources().openRawResource(R.raw.XXX);
知道了如何获取xml文件,接下来就是解析了,自定义一个data.xml文件,如下:
<?xml version="1.0" encoding="utf-8"?>
<Document>
<type tname="居民点">
<child name="城镇" code="aa" />
<child name="农村" code="ab" />
</type>
<type tname="工厂点">
<child name="工厂" code="cc" />
</type>
</Document>
1、PULL解析
一般将xml文件放在res/xml文件中:
public List<TypeInfo> parse() throws Exception{
XmlResourceParser xmlParser=getResources().getXml(R.xml.data);
int eventType=xmlParser.getEventType();
TypeInfo typeInfo=null;
List<TypeInfo> typeInfoList=null;
List<ChildInfo> childList=null;
ChildInfo childInfo=null;
while(eventType!=XmlPullParser.END_DOCUMENT){
switch(eventType){
case XmlPullParser.START_DOCUMENT:
typeInfoList=new ArrayList<TypeInfo>();
break;
case XmlPullParser.START_TAG:
if(xmlParser.getName().equals("type")){
typeInfo=new TypeInfo();
typeInfo.setTname(xmlParser.getAttributeValue(0));
childList=new ArrayList<ChildInfo>();
}else if(xmlParser.getName().equals("child")){//若child的格式为<child>哈哈</child>,则通过xmlParser.nextText()获取child的值
childInfo=new ChildInfo();
childInfo.setName(xmlParser.getAttributeValue(null,"name"));
childInfo.setCode(xmlParser.getAttributeValue(null,"code"));
}
break;
case XmlPullParser.END_TAG:
if(xmlParser.getName().equals("child")){
childList.add(childInfo);
}else if(xmlParser.getName().equals("type")){
typeInfo.setChildList(childList);
typeInfoList.add(typeInfo);
}
break;
}
eventType=xmlParser.next();
}
return typeInfoList;
}
若xml文件放在assets目录中,则将上述第二行代码更换为下面的代码即可
XmlPullParser xmlParser=XmlPullParser .newPullParser();
InputStream is=getResources().getAssets().open("data.xml");
xmlParser.setInput(is,"utf-8");
2、SAX解析
SAX解析会遍历完所有的节点,对于SAX解析,android有两种方式,第一种是使用org.xml.sax.helpers.DefaultHandler类进行解析,另一种是使用android自带的android.util.Xml类进行解析。
(1)、使用android自带的类进行解析(这种方法更加简单,高效)
private List<TypeInfo> typeInfoList=new ArrayList<TypeInfo>();
private TypeInfo typeInfo;
private List<ChildInfo> childList;
private ChildInfo childInfo;
public void doParse(){
InputStream is=getResources().openRawResource(R.raw.data);
RootElement root=new RootElement("Document");//根节点
Element typeChild=root.getChild("type");
typeChild.setElementListener(new ElementListener() {
@Override
public void start(Attributes attributes) {//读到元素开始时
typeInfo=new TypeInfo();
typeInfo.setTname(attributes.getValue("tname"));//根据属性名获取相应的值
childList=new ArrayList<ChildInfo>();
}
@Override
public void end() {//读到元素结束时
typeInfo.setChildList(childList);
typeInfoList.add(typeInfo);
}
});
Element child=typeChild.getChild("child");
child.setElementListener(new ElementListener() {
@Override
public void start(Attributes attributes) {
childInfo=new ChildInfo();
childInfo.setName(attributes.getValue("name"));
childInfo.setCode(attributes.getValue("code"));
}
@Override
public void end() {
childList.add(childInfo);
}
});
//若child是文本,即<child>哈哈</child>,则解析如下:
//child.setTextElementListener(new TextElementListener() {
//
// @Override
// public void end(String body) {
// //body就是取出的字符串,即"哈哈",可在这里获取相应的值
// }
//
// @Override
// public void start(Attributes attributes) {
//
// }
//});
try {
Xml.parse(is, Encoding.UTF_8, root.getContentHandler());
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
(2)、使用org.xml.sax.helpers.DefaultHandler类进行解析
首先定义一个SAXHandler类继承DefaultHandler,并将解析的数据放入typeInfoList中,
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SAXHandler extends DefaultHandler {
private List<TypeInfo> typeInfoList;
private TypeInfo typeInfo;
private String value;
private List<ChildInfo> childList;
private ChildInfo childInfo;
public SAXHandler(List<TypeInfo> typeInfoList){
this.typeInfoList=typeInfoList;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
super.characters(ch, start, length);
value=new String(ch, start, length);
}
@Override
public void startDocument() throws SAXException {
super.startDocument();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if(localName.equalsIgnoreCase("child")){
childInfo=new ChildInfo();
childInfo.setCode(attributes.getValue("code"));
childInfo.setName(attributes.getValue("name"));
}else if(localName.equalsIgnoreCase("type")){
typeInfo=new TypeInfo();
typeInfo.setTname(attributes.getValue("tname"));
childList=new ArrayList<ChildInfo>();
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(uri, localName, qName);
if(localName.equalsIgnoreCase("child")){
childList.add(childInfo);
}else if(localName.equalsIgnoreCase("type")){
typeInfo.setChildList(childList);
typeInfoList.add(typeInfo);
}
}
}
在Activity中开始解析,
//调用解析的类
SAXParserFactory saxFactory=SAXParserFactory.newInstance();
try {
SAXParser saxParser=saxFactory.newSAXParser();
XMLReader xmlReader=saxParser.getXMLReader();
//设置解析的处理类为我们自定义的SAXHandler类
xmlReader.setContentHandler(new SAXHandler(typeInfoList));
//设置解析源
InputStream is=getResources().openRawResource(R.raw.data);
InputSource source=new InputSource(is);
xmlReader.parse(source);
} catch (IOException e) {
e.printStackTrace();
}catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
解析完成后,数据就存储在了typeInfoList中,可以显示查看
StringBuilder str=new StringBuilder();
for(int i=0;i<typeInfoList.size();i++){
TypeInfo typeInfo=typeInfoList.get(i);
str.append("tname=");
str.append(typeInfo.getTname()+"\n");
List<ChildInfo> childList=typeInfo.getChildList();
if(childList!=null){
str.append("child:"+"\n");
for(int j=0;j<childList.size();j++){
str.append("name="+childList.get(j).getName()+",");
str.append("code="+childList.get(j).getCode()+"\n");
}
}
}
TextView text=(TextView) findViewById(R.id.tv_show);
text.setText(str.toString());
运行结果如下,解析成功:
tname=居民点
child:
name=城镇,code=aa
name=农村,code=ab
tname=工厂点
child:
name=工厂,code=cc