Android之旅十四 android中的xml文件解析
时间:2014-05-15 13:10:15
收藏:0
阅读:368
在我们做有关android项目的时候,肯定会涉及到对xml文件的解析操作,下面给大家介绍一下xml文件的解析,包含DOM、SAX、Pull以及以前我们用到的DOM4J和JDOM:
要解析的XML文件:person.xml
<?xml version="1.0" encoding="UTF-8"?> <persons> <person id="001"> <name>zhangsan</name> <age>25</age> </person> <person id="002"> <name>lisi</name> <age>23</age> </person> </persons>
创建person实体类:
package cn.itcast.domain;
public class Person {
private Integer id;
private String name;
private Short age;
public Person(){}
public Person(Integer id, String name, Short age) {
this.id = id;
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 Short getAge() {
return age;
}
public void setAge(Short age) {
this.age = age;
}
@Override
public String toString() {
return "Person [age=" + age + ", id=" + id + ", name=" + name + "]";
}
}
public static List<Person> getPersons(InputStream inStream) throws Throwable{
List<Person> persons = new ArrayList<Person>();
//创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//创建文档树模型,所有的Node都以一定的顺序包含在Document对象之内,
//排列成一个树状结构,以后对XML文档的所有操作都与解析器无关
Document documnet = builder.parse(inStream);
//获取根元素
Element root = documnet.getDocumentElement();
//获得根元素下的person节点列表
NodeList personNodes = root.getElementsByTagName("person");
for(int i=0 ; i < personNodes.getLength(); i++){
Person person = new Person();
//获得节点中的元素
Element personElement = (Element)personNodes.item(i);
//获得person中id属性
person.setId(new Integer(personElement.getAttribute("id")));
//获得person节点下的子节点
NodeList personChilds = personElement.getChildNodes();
for(int y=0 ; y < personChilds.getLength(); y++){
if(personChilds.item(y).getNodeType()==Node.ELEMENT_NODE){//判断当前节点是否是元素类型节点
Element childElement = (Element)personChilds.item(y);
if("name".equals(childElement.getNodeName())){
//获得相应元素的值
person.setName(childElement.getFirstChild().getNodeValue());
}else if("age".equals(childElement.getNodeName())){
person.setAge(new Short(childElement.getFirstChild().getNodeValue()));
}
}
}
persons.add(person);
}
return persons;
}2、SAX解析XML:顺序读取XML文件,不需要一次全部装载整个文件,由于移动设备的内存资源有限,SAX的顺序读取方式更适合移动开发
public List<Person> getPersons(InputStream inStream) throws Throwable{
//创建SAXParserFactory
SAXParserFactory factory = SAXParserFactory.newInstance();
//创建SAX解析器
SAXParser parser = factory.newSAXParser();
//创建XML解析处理器
PersonParser personParser = new PersonParser();
//将XML解析处理器分配给解析器,对文档进行解析,将每个事件发送给处理器
parser.parse(inStream, personParser);
inStream.close();
return personParser.getPersons();
}
//定义解析处理器
private final class PersonParser extends DefaultHandler{
private List<Person> persons = null;//将解析的数据放在List集合中
private String tag = null;//定义一个全局变量的标签名称
private Person person = null;
public List<Person> getPersons() {
return persons;
}
//解析Document
@Override
public void startDocument() throws SAXException {
//解析<persons>部分
persons = new ArrayList<Person>();
}
@Override
public void endDocument() throws SAXException {
System.out.println("end parse xml");
}
/**
* 解析Element
* namespaceURI 命名空间
* localName 不带前缀部分<person id="001">--->person
* qName 带前缀部分<abc:person id="001">---->abc:worker
* attributes 属性集合 <abc:person id="001">---->id="001"....
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
//解析<person id="001">部分
if("person".equals(localName)){
person = new Person();
person.setId(new Integer(attributes.getValue(0)));
}
tag = localName;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//解析其中的文本<name>zhangsan</name>-->zhangsan
if(tag!=null){
String data = new String(ch, start, length);//获取文本节点的数据
if("name".equals(tag)){
person.setName(data);
}else if("age".equals(tag)){
person.setAge(new Short(data));
}
}
}
//解析结束元素
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if("person".equals(localName)){
persons.add(person);
person = null;
}
tag = null;
}
}3、pull解析XML:pull解析和SAX解析很相似,都是轻量级的解析,在android内核中已经嵌入了pull,所以我们不需要再添加第三方jar包来支持pull
/**
* 使用pull解析XML文档
* @param inStream
* @return
* @throws Throwable
*/
public static List<Person> getPersons(InputStream inStream) throws Throwable{
List<Person> persons = null;
Person person = null;
XmlPullParser parser = Xml.newPullParser();
parser.setInput(inStream, "UTF-8");
int eventType = parser.getEventType();//产生第一个事件
while(eventType!=XmlPullParser.END_DOCUMENT){//只要不是文档结束事件
switch (eventType) {
case XmlPullParser.START_DOCUMENT://判断当前事件是否是文档开始事件
persons = new ArrayList<Person>();//初始化Person集合
break;
case XmlPullParser.START_TAG://判断当前事件是否是标签元素开始事件
String name = parser.getName();//获取解析器当前指向的元素的名称
if("person".equals(name)){
person = new Person();
//得到相应的标签的属性值
person.setId(new Integer(parser.getAttributeValue(0)));
}
if(person!=null){
if("name".equals(name)){
//获取解析器当前指向元素的下一个文本节点的值
person.setName(parser.nextText());
}
if("age".equals(name)){
person.setAge(new Short(parser.nextText()));
}
}
break;
case XmlPullParser.END_TAG://判断当前事件是否是标签元素结束事件
if("person".equals(parser.getName())){
persons.add(person);
person = null;
}
break;
}
//进入下一元素并触发相应事件
eventType = parser.next();
}
return persons;
}采用pull解析器创建一个xml文档:
/**
* 使用pull解析器创建一个xml文档
* @param persons
* @param writer
* @throws Throwable
*/
public static void save(List<Person> persons, Writer writer) throws Throwable{
XmlSerializer serializer = Xml.newSerializer();
serializer.setOutput(writer);
serializer.startDocument("UTF-8", true);
serializer.startTag(null, "persons");
for(Person person : persons){
serializer.startTag(null, "person");
serializer.attribute(null, "id", person.getId().toString());
serializer.startTag(null, "name");
serializer.text(person.getName());
serializer.endTag(null, "name");
serializer.startTag(null, "age");
serializer.text(person.getAge().toString());
serializer.endTag(null, "age");
serializer.endTag(null, "person");
}
serializer.endTag(null, "persons");
serializer.endDocument();
writer.flush();
writer.close();
}
在android项目中通过Junit对各方法进行测试:
注意在使用junit的时候,需要在AndroidMainifest.xml中加入:
<uses-library android:name="android.test.runner" /> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.xin.activity" android:label="Tests for My App" />编写我们的java测试类:
public class PersonServiceTest extends AndroidTestCase {
private static final String TAG = "PersonServiceTest";
public void testSAXGetPersons() throws Throwable{
SAXPersonService service = new SAXPersonService();
InputStream inStream = getClass().getClassLoader().getResourceAsStream("person.xml");
List<Person> persons = service.getPersons(inStream);
for(Person person : persons){
Log.i(TAG, person.toString());
}
}
public void testDomGetPersons() throws Throwable{
InputStream inStream = getClass().getClassLoader().getResourceAsStream("person.xml");
List<Person> persons = DOMPersonService.getPersons(inStream);
for(Person person : persons){
Log.i(TAG, person.toString());
}
}
public void testPullGetPersons() throws Throwable{
InputStream inStream = getClass().getClassLoader().getResourceAsStream("person.xml");
List<Person> persons = PULLPersonService.getPersons(inStream);
for(Person person : persons){
Log.i(TAG, person.toString());
}
}
}
运行输出即可得到我们想要的结果!
几种方法比较: SAX:一行一行读取,效率高,读取到相应需要的数据后不再往下操作,操作复杂,适合移动设备
DOM:操作简单,一开始加载一个DOM树,当XML文件相对比计较大的时候影响效率,速度慢
* Pull解析和Sax解析不一样的地方有
* (1)pull读取xml文件后触发相应的事件调用方法返回的是数字
* (2)pull可以在程序中控制想解析到哪里就可以停止解析
其实pull解析xml不仅适用于android,在我们的javase中也可以使用pull解析器来解析xml文件,不过需要导入相应的jar包:
kxml2-2.3.0.jar,下载地址:http://kxml.sourceforge.net/
xmlpull_1_1_3_4c.jar 下载地址:http://www.xmlpull.org/
以前我们还使用了DOM4J和JDOM来解析xml,可以参见我的博客,不过需要导入相应的支持jar包:
DOM4J解析XML:http://blog.csdn.net/harderxin/article/details/7285770
JDOM解析XML:http://blog.csdn.net/harderxin/article/details/7285754
评论(0)