本文整理自用,部分内容参考http://blog.youkuaiyun.com/anladeyatou/article/details/7446938;
XML解析总结
解析方式:3种解析方式,分别是DOM解析,SAX解析,PULL解析。
————————–DOM解析———————
》DOM简介
dom全称Document Object Model ,为xml文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个主流内存的树结构,然后代码就可以使用dom接口来操作这个树结构
》DOM的特点
>优点
1.整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能
2.通过树形结构存取xml文档
3.可以在树的某个节点上向前或向后移动
>缺点
1.将整个文档调入内存(包括无用的节点),浪费时间和空间
>适用场合
一旦解析了文档还需多次访问这些数据;硬件资源充足(内存,cpu)
》DOM解析步骤
1.创建解析器工厂
2.获得解析器工厂
3.接受一个xml文档作为输入参数名,并得到一个xml的文档对象(Document)
4.操作文档对象
》解析实例:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<Person> list = new ArrayList<Person>();
//判断SDcard是否是挂载状态
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
//得到文件对象
File file = Environment.getExternalStorageDirectory();
//创建文档工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
//得到编辑器
DocumentBuilder builder = factory.newDocumentBuilder();
//通过编辑器 得到文件文档对象
Document document = builder.parse(new File(file.getPath()+"/data.xml"));
//得到文档的根元素
Element element = document.getDocumentElement();
//得到一个子节点集合
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
//创建一个person对象 用于存储解析出来的数据
Person p = new Person();
Node node = childNodes.item(i);
if (node.getNodeType()==node.ELEMENT_NODE) {
Element element2 = (Element) node;
String id = element2.getAttribute("id");
p.id=Integer.parseInt(id.trim());
NodeList childNodes2 = element2.getChildNodes();
for (int j = 0; j < childNodes2.getLength(); j++) {
Node node2 = childNodes2.item(j);
if (node2.getNodeType()==node2.ELEMENT_NODE) {
Element element3 = (Element) node2;
String value = element3.getFirstChild().getNodeValue();
if (element3.getNodeName().equals("name")) {
p.name=value;
}else if (element3.getNodeName().equals("age")) {
p.age=value;
}
}
}
list.add(p);
}
}
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ListView lv = (ListView) findViewById(R.id.lv);
lv.setAdapter(new ArrayAdapter<Person>(this, android.R.layout.simple_expandable_list_item_1, android.R.id.text1, list));
}
}
————————–SAX解析———————————-
》Sax定义
SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于android等移动设备
SAX全称是Simple API for Xml,既是指一种接口,也是一个软件包
作为接口,sax是事件驱动型xml解析的一个标准接口
》Sax特点
1. 解析效率高,占用内存少
2.可以随时停止解析
3.不能载入整个文档到内存
4.不能写入xml
5.SAX解析xml文件采用的是事件驱动
—sax并不需要解析完 整个文档,在按内容顺序解析文档的过程中,sax会判断当前读到的字符是否合法xml语法中的某部分,如果符合就会触发事件
》Sax工作原理
Sax的工作原理简单的说,就是对文档进行顺序扫描,扫描到文档(document)开始与结束,扫描到元素(element)开始、结束等地方时调用事件处理
处理函数做相应动作,然后继续扫描,直到文档结束。
》Sax解析文档过程
1.继承DefaultHandler ,并实现方法
2.创建SAX解析器工厂
3.获得解析器
4.获得输入流
5.使用输入流,和实现接口作参数,调用解析器的解析方法进行解析
》defaultHandler 接口是实现contentHandler接口
ContentHandler接口中的常用方法
>startDocument()
当遇到文档开头的时候,调用这个方法,可以在其中做一些与准备工作
>endDocument()
当文档结束的时候,调用这个方法,可以在其中做一些善后工作
>startElement(String namespaceURL, String localName, String qName, Attributes atts)
当读到一个开始标签的时候,会触发这个方法。namespaceURL就是命名空间,localName是不带命名空间前缀的标签名,
qName是待命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。
>endElement(String uri, String localName, String name)
当遇到结束标签的时候,调用这个方法
>characters(char[] ch, int start, int length)
这个方法用来处理在xml文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,
使用new String(ch, start, length)就可以获取内容
》SAX解析实例
**一、第一步需要一个DefaultHandler的实例,并实现内部方法用于解析**
public class PersonHandler extends DefaultHandler {
private Person p;//实体类
private String ele_name;
private List<Person> list;//实体类集合
//【1】开始解析文档
@Override
public void startDocument() throws SAXException {
//实例化集合
list = new ArrayList<Person>();
super.startDocument();
}
//【2】解析元素头标签 例如:<element>
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
ele_name = localName;
if ("person".equals(ele_name)) {
System.out.println("添加ID");
p = new Person();
p.setId(Integer.parseInt(attributes.getValue(0)));
}
super.startElement(uri, localName, qName, attributes);
}
//【3】解析元素中的文本 例如:<element>文本</element>
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//得到文本
String text = new String(ch,start,length);
if (p!=null) {
if ("name".equals(ele_name)) {
System.out.println("添加名字");
p.setName(text);
}else if ("age".equals(ele_name)) {
System.out.println("添加年龄");
p.setAge(Integer.parseInt(text));
}
}
super.characters(ch, start, length);
}
public List<Person> getList(){
return list;
}
//【4】解析元素结束标签 例如:</element>
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
ele_name=localName;
if ("person".equals(ele_name)) {
System.out.println("添加对象");
//整个元素解析完毕,对象初始化完毕,添加进入集合
list.add(p);
//初始化实体类对象,准备进入下次解析数据
p=null;
}
ele_name="";
super.endElement(uri, localName, qName);
}
}
第二步:开始sax解析
public class MainActivity extends Activity {
List<Person> list;
private PersonHandler ph;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File file = Environment.getExternalStorageDirectory();
//创建工厂对象(工厂模式)
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
//通过工厂实例化一个sax解析对象
SAXParser saxParser = factory.newSAXParser();
//获得事件源
XMLReader reader = saxParser.getXMLReader();
//构建事件处理器的实例
ph=new PersonHandler();
reader.setContentHandler(ph);
//解析,数据已存在事件处理器的实例中的list集合里
reader.parse(new InputSource(new FileInputStream(file.getPath()+"/data.xml")) );
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
——————————pull解析—————————–
》pull解析器简介
1.pull解析器是android内置的解析器,解析原理与sax类似
2.pull它提供了类似的事件。
如:开始元素和结束元素事件,使用parse.next()可以进入下一个元素并触发相应的事件,事件将作为数值代码被发送
因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法获取下一个Text类型节点的值
》pull与sax的不同之处
1.pull读取xml文件后触发相应的事件调用方法返回的是数字。
2.pull可以在程序中控制,想解析到哪里就可以停止到哪里
3.Android中更推荐使用pull解析
》pull解析步骤
1.创建解析器对象
XmlPullParser paser = Xml.newPullParser();
2.进行解析
paser.setInput(input,"utf-8");
3.产生第一个解析事件
int eventType = paser.getEventType();
4.可以使用循环判断是否继续解析
while(eventType!=XmlPullParser.END_DOCUMENT){}
》解析实例
public class MainActivity extends Activity {
String strUrl="http://www.sciencenet.cn/xml/iphoneInterface.aspx?type=news&nums=20&pass=";
List<New> list = null;//实体类集合
private InputStream is=null;//输入流
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//开启异步任务或者子线程获得网络数据,得到输入流--is;
//******
}
//解析方法
public List<New> pullParseXml(InputStream is){
New n=null;//实体类对象
try {
//创建工厂对象
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser pullParser =factory.newPullParser();
pullParser.setInput(is, "utf-8");//传入输入流并设置字符集
int eventType = pullParser.getEventType();//得到元素类型
while (eventType!=XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
list=new ArrayList<New>();
break;
case XmlPullParser.START_TAG:
String name = pullParser.getName();
if ("title".equals(name)) {
n = new New();
n.setTitle(pullParser.nextText());
}
if ("link".equals(name)) {
n.setLink(pullParser.nextText());
}
if ("imgs".equals(name)) {
n.setImgs(pullParser.nextText());
}
if ("description".equals(name)) {
n.setDescription(pullParser.nextText());
}
if ("copyright".equals(name)) {
n.setCopyright(pullParser.nextText());
}
if ("pubDate".equals(name)) {
n.setPubDate(pullParser.nextText());
}
if ("comments".equals(name)) {
n.setComments(pullParser.nextText());
}
break;
case XmlPullParser.END_TAG:
//解析完添加到集合中
list.add(n);
n=null;
break;
}
eventType = pullParser.next();
}
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}