andorid读取xml文件内容方法有三种 sax dom pull,其中 pull是android自带的
1.先认识一下xml文件中的些术语
Xml代码
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="23">
<name>李明</name>
<age>23</age>
</person>
<person id="22">
<name>李量</name>
<age>25</age>
</person>
</persons>
xml中的标签和内容都可以叫做节点,其中的persons person name age 这些都叫做元素(element).而像李明 25 这些值叫做文本节点.那么有个问题 中<persons>到<person>之间的是什么,什么都没有? 答案是他也是节点,是文本节点,你会说他里面什么都没有啊,错了,它有回车和空格.这个在sax解析xml中你debug一下就会发现.回车和空格(或者是tab)是会被读取出来的.id是属性.
2.sax
sax是采用事件驱动,就是说他不需要完全读完xml文件,他是读到一个节点就解析一个节点是否符合xml语法,如果符合就调用相对应的方法其实就是回调方法,并且没有记忆功能.下面提到的这些方法都是在ContentHander()接口中的方法.
startDocumnet() :当开始解析xml文件的声明的时候就会触发这个事件, 可以做一些初始化的工作
startElement() 当开始解析元素的开始标签的时候,就会触发这个事件
characters() 当读到文本元素的时候要触发这个事件.
endElement() 当读到结束标签的时候 就会触发这个事件
sax就是这样按照顺序来解析的.
3.sax读取xml文件举例
3-1创建一个项目 ReadXml
3-2将xml文件拷贝到根目录下.
Xml代码
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="23">
<name>李明</name>
<age>23</age>
</person>
<person id="22">
<name>李量</name>
<age>25</age>
</person>
</persons>
可以看出这个xml文件中有一个可以抽象出来的对象 就是person 属性有id name age
那么我们就建立一个bean
3-3:创建bean
Java代码
package com.leequer.service.demo;
/**
* <person id="23">
<name>李明</name>
<age>23</age>
</person>
<person id="22">
<name>李量</name>
<age>25</age>
</person>
* @author leequer
*
* xml文件对应的bean
*/
public class Person {
private Integer id;
private String name;
private int age;
public Person ()
{}
public Person (String name ,int age)
{
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.id+",name "+this.name+" age "+this.age+"\n";
}
}
3-4:遵循mvc的架构,我们建立一个service用来读取xml
Java代码
package com.leequer.service;
import java.io.InputStream;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.XMLReader;
import com.leequer.service.demo.Person;
public class SaxReadxml {
public static List<Person> readXml(InputStream inStream)throws Exception {
SAXParserFactory spf = SAXParserFactory.newInstance(); // 初始化sax解析器
SAXParser sp = spf.newSAXParser(); // 创建sax解析器
//XMLReader xr = sp.getXMLReader();// 创建xml解析器
XMLContentHandler handler = new XMLContentHandler();
sp.parse(inStream, handler);
return handler.getPersons();
}
}
sp.parse(inStream, handler);
这句可以看出xml文件是以流的形式传进来的,参数handler就是回调函数的实例,当sax解析器解析xml文件的时候当遇到符合xml的内容就会去handle类中调用对应的上面提到的方法.那我们建立这个XMLContentHandler 就要求这个类要实现ContentHandler()这个接口,但是这个接口中有很多需要实现的方法.sax提供了一个DefaultHandler接口 只要实现这个接口中你感兴趣的方法就可以了.
3-5:创建XMLContentHandler 并完成读取时的事件的实现 注意看注释
Java代码
package com.leequer.service;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.leequer.service.demo.Person;
public class XMLContentHandler extends DefaultHandler {
private List<Person> persons;
private Person person;
private String tempString;
private static final String NAMESTRING = "name";
private static final String AGESTRING = "age";
private static final String PERSONSTRING = "person";
private static final String IDSTRING = "id";
public List<Person> getPersons() {
return persons;
}
/**
* sax 解析文件不带记忆,只读取 对xml文件中的 <person id="23"> <name>李明</name> <age>23</age>
* </person> <person id="22"> <name>李量</name> <age>25</age> </person> 这部分感兴趣
* 那么这部分包含了person这个节点元素的开始和结尾,那么就要有startElement和endElement
* 这两个方法;还有text的节点元素,(就是像节点之间的回车和空格还有标签中的像李明这样的文字都是文本节点 元素
* (text节点元素)那么要解析文本节点元素就要用到characters 这个方法来获取信息。)
*/
/**
* 要开始读取xml文件的时候调用的方法
* 初始化persons
*/
@Override
public void startDocument() throws SAXException {
//这里做list的初始化工作
persons = new ArrayList<Person>();
}
/**
* sax 读取到文本节点的时候调用了这个方法
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (person != null) {
String valueString = new String(ch, start, length);
if (NAMESTRING.equals(tempString)) {
// 如果当前解析到的节点是name 就要将name中的文本节点元素的值得到
person.setName(valueString);
} else if (AGESTRING.equals(tempString)) {
person.setAge(new Integer(valueString).intValue());
}
}
}
/**
* sax 读取到元素节点的时候用到这个方法;
*/
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// 先判断读到的元素是否是person
if (PERSONSTRING.equals(localName)) {
// 如果读到的是person这个元素 就要保存起来,保存在我们创建的那个person的类中 所以我们要new一个person类
person = new Person();
// attributes是属性。
person.setId(new Integer(attributes.getValue(IDSTRING)));
}
tempString = localName;
}
/**
* 这个方法是每次遇到结束的标签都会执行的 并不是只遇到最后的结尾才调用
*
* 读取完毕遇到person'的结尾 就将封装好的一个personbean保存到list中 并且清空person对象
*
*/
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
if(PERSONSTRING.equals(localName)&&person!=null)
{
persons.add(person);
person = null;
}
tempString = null;
}
}
3-6:写个测试类来实验 将xml文件装载入 然后读取
package com.leequer.readxml;
/**
* 测试类
*/
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import com.leequer.service.SaxReadxml;
import com.leequer.service.demo.Person;
import android.test.AndroidTestCase;
import android.util.Log;
public class SaxReadxmlTest extends AndroidTestCase {
private String PERSONSTRING = "ObjectPerson";
public void testReadXml() throws Exception
{//类装载器
InputStream inputStream = SaxReadxmlTest.class.getClassLoader().getResourceAsStream("NewFile.xml");
List <Person> personsList = SaxReadxml.readXml(inputStream);
for (Iterator iterator = personsList.iterator(); iterator.hasNext();) {
Person person = (Person) iterator.next();
Log.i(PERSONSTRING, person.toString());
}
}
}