您的位置:首页 > 其它

XmlPullParser解析XML文件

2016-02-15 15:16 369 查看


XML解析三种方式


DOM

通用性强,它会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树、检索所需的数据;
简单直观,但需要将文档读取到内存,并不太适合移动设备;


SAX

SAX是一个解析速度快并且占用内存少的xml解析器;

采用事件驱动,它并不需要解析整个文档;

实现:继承DefaultHandler,覆写startElement、endElement、characters等方法;


PULL

Android自带的XML解析器,和SAX基本类似,也是事件驱动,不同的是PULL事件返回的是数值型;推荐使用。


PULL解析XML核心代码

[java] view
plain copy

XmlPullParserFactory factory
= XmlPullParserFactory.newInstance();

XmlPullParser parser=factory.newPullParser();

parser.setInput(fileInputStream, “utf-8”);//设置数据源编码

int eventCode = parser.getEventType();//获取事件类型

while(eventCode != XmlPullParser.END_DOCUMENT) {

switch (eventCode){

case XmlPullParser.START_DOCUMENT: //开始读取XML文档

//实例化集合类

break;

case XmlPullParser.START_TAG://开始读取某个标签

if("person".equals(parser.getName())) {

//通过getName判断读到哪个标签,然后通过nextText()获取文本节点值,或通过getAttributeValue(i)获取属性节点值

}

break;

case XmlPullParser.END_TAG://读完一个Person,可以将其添加到集合类中

break;

}

parser.next();

}

PULL解析XML示例方法

Java方法

[java] view
plain copy

public static List<Person> readXML(InputStream inStream) {

XmlPullParser parser = Xml.newPullParser();

try {

parser.setInput(inStream, "UTF-8");// 设置数据源编码

int eventType = parser.getEventType();// 获取事件类型

Person currentPerson = null;

List<Person> persons = null;

while (eventType != XmlPullParser.END_DOCUMENT) {

switch (eventType) {

case XmlPullParser.START_DOCUMENT:// 文档开始事件,可以进行数据初始化处理

persons = new ArrayList<Person>();// 实例化集合类

break;

case XmlPullParser.START_TAG://开始读取某个标签

//通过getName判断读到哪个标签,然后通过nextText()获取文本节点值,或通过getAttributeValue(i)获取属性节点值

String name = parser.getName();

if (name.equalsIgnoreCase("person")) {

currentPerson = new Person();

currentPerson.setId(new Integer(parser.getAttributeValue(null, "id")));

} else if (currentPerson != null) {

if (name.equalsIgnoreCase("name")) {

currentPerson.setName(parser.nextText());// 如果后面是Text元素,即返回它的值

} else if (name.equalsIgnoreCase("age")) {

currentPerson.setAge(new Short(parser.nextText()));

}

}

break;

case XmlPullParser.END_TAG:// 结束元素事件

//读完一个Person,可以将其添加到集合类中

if (parser.getName().equalsIgnoreCase("person")&& currentPerson != null) {

persons.add(currentPerson);

currentPerson = null;

}

break;

}

eventType = parser.next();

}

inStream.close();

return persons;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}


应用

XML文件

[html] view
plain copy

<?xml version="1.0" encoding="UTF-8"?>

<persons>

<person id="23">

<name>孙洋洋</name>

<age>30</age>

</person>

<person id="20">

<name>孙彬彬</name>

<age>25</age>

</person>

</persons>

Activity文件

[java] view
plain copy

package com.app.data;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.OutputStreamWriter;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import org.xmlpull.v1.XmlPullParser;

import org.xmlpull.v1.XmlPullParserException;

import org.xmlpull.v1.XmlPullParserFactory;

import com.app.other.Person;

import android.app.Activity;

import android.os.Bundle;

import android.util.Xml;

import android.widget.TextView;

public class XMLActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

// TODO Auto-generated method stub

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_xml);

StringBuilder sBuilder = new StringBuilder();

File xmlFile = new File("/mnt/sdcard/App/person.xml");

try {

FileInputStream inputStream = new FileInputStream(xmlFile);

// URL url = new URL("http://10.0.2.2:8888/android/person.xml");

// HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

// InputStream inputStream = urlConnection.getInputStream();

List<Person> list = readXML(inputStream);

for (int i = 0; i < list.size(); i++) {

Person person = list.get(i);

sBuilder.append("第-" + i + "-条记录:\n");

sBuilder.append("getName--" + person.getName() + "\n");

sBuilder.append("getAge--" + person.getAge() + "\n");

sBuilder.append("getId--" + person.getId() + "\n");

}

inputStream.close();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

TextView textView = (TextView)findViewById(R.id.textView2);

textView.setText(sBuilder);

}

public static List<Person> readXML(InputStream inStream) {

XmlPullParser parser = Xml.newPullParser();

try {

parser.setInput(inStream, "UTF-8");// 设置数据源编码

int eventType = parser.getEventType();// 获取事件类型

Person currentPerson = null;

List<Person> persons = null;

while (eventType != XmlPullParser.END_DOCUMENT) {

switch (eventType) {

case XmlPullParser.START_DOCUMENT:// 文档开始事件,可以进行数据初始化处理

persons = new ArrayList<Person>();// 实例化集合类

break;

case XmlPullParser.START_TAG://开始读取某个标签

//通过getName判断读到哪个标签,然后通过nextText()获取文本节点值,或通过getAttributeValue(i)获取属性节点值

String name = parser.getName();

if (name.equalsIgnoreCase("person")) {

currentPerson = new Person();

currentPerson.setId(new Integer(parser.getAttributeValue(null, "id")));

} else if (currentPerson != null) {

if (name.equalsIgnoreCase("name")) {

currentPerson.setName(parser.nextText());// 如果后面是Text元素,即返回它的值

} else if (name.equalsIgnoreCase("age")) {

currentPerson.setAge(new Short(parser.nextText()));

}

}

break;

case XmlPullParser.END_TAG:// 结束元素事件

//读完一个Person,可以将其添加到集合类中

if (parser.getName().equalsIgnoreCase("person")&& currentPerson != null) {

persons.add(currentPerson);

currentPerson = null;

}

break;

}

eventType = parser.next();

}

inStream.close();

return persons;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

}

XML布局文件

[html] view
plain copy

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:padding="15dp" >

<TextView

android:id="@+id/textView1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="XML文件读取"

android:layout_gravity="center_horizontal" />

<TextView

android:id="@+id/textView2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="TextView" />

</LinearLayout>

XML文件位置



执行结果:



===================================================================================================================
=====================================另一篇文章=================================================================

android xml 的解析.

1.普通型

Xml代码



<?xml version=”1.0″ ?>

<statuses>

<status>

<source1>a</source1>

<source2>a</source2>

<source2>a</source2>

</status>

<statuses>

</xml>

解析代码.

Java代码



try{

xpp.setInput( new StringReader ( “xml string” ) );

XmlPullParser parser = XmlPullParserFactory.newInstance()

.newPullParser();

int eventType = parser.getEventType();

while (eventType != XmlPullParser.END_DOCUMENT) {

if (eventType == XmlPullParser.START_TAG) {

String name = parser.getName();

Log.v(“tag”,parser.getName()+”=”+parser.next());

}

eventType = parser.next();

}

} catch (XmlPullParserException e) {

} catch (Exception e) {

}

2.嵌套子类.

Xml代码



<?xml version=”1.0″ encoding=”UTF-8″ standalone=”no”?>

<statuses>

<status>

<source1>a</source1>

<source2>a</source2>

<source2>a</source2>

<user>

<source1>a</source1>

<source2>a</source2>

<source2>a</source2>

</user>

</status>

<status>

<source1>a</source1>

<source2>a</source2>

<source2>a</source2>

<user>

<source1>a</source1>

<source2>a</source2>

<source2>a</source2>

</user>

</status>

<statuses>

</xml>

解析代码:

Java代码



try{

XmlPullParser parser = XmlPullParserFactory.newInstance()

.newPullParser();

xpp.setInput( new StringReader ( xml string ) );

parser.next();

parser.require(XmlPullParser.START_TAG, null, “statuses”);

while (parser.nextTag() != XmlPullParser.END_TAG) {

parser.require(XmlPullParser.START_TAG, null, “status”);

for (int i=0;i<3;i++){

parser.nextTag();

Log.v(“tag”,parser.getName()+”=”+ parser.nextText());

}

while (parser.nextTag() != XmlPullParser.END_TAG) {

parser.require(XmlPullParser.START_TAG, null, “user”);

while (parser.nextTag() != XmlPullParser.END_TAG) {

String name = parser.getName();

String text2 = parser.nextText();

Log.v(“tag”,”text2″+text2);

parser.require(XmlPullParser.END_TAG, null, name);

}

parser.require(XmlPullParser.END_TAG, null, “user”);

}

parser.require(XmlPullParser.END_TAG, null, “status”);

}

parser.require(XmlPullParser.END_TAG, null, “statuses”);

parser.next();

parser.require(XmlPullParser.END_DOCUMENT, null, null);

// global.userinfo.dump();

} catch (XmlPullParserException e) {

} catch (Exception e) {

}

最里面那个可以满足 <user>也是循环. 如果<user>不循环.
可以使用.

Java代码



for (int i=0;i<3;i++){

parser.nextTag();

Log.v(“tag”,parser.getName()+”=”+ parser.nextText());

}

代替.

开发过程中遇到XmlPullParser.netText()方法造成的Bug

解决如下:

在Android上使用XmlPullParser是一中高效率和易维护解析XML的方法 。Android已经在历史上有两个实现这个接口实现类:

KXmlParser,通过XmlPullParserFactory.newPullParser()

ExpatPullParser,通过Xml.newPullParser()

实现
Xml.newPullParser()
调用
nextText()有个错误,nextText()
并不总是向文档中所提到优先于
END_TAG执行


因此,一些应用可能会出现bug在额外调用next()或nextTag();

[html] view
plaincopy

throws XmlPullParserException, IOException {

XmlPullParser parser = Xml.newPullParser();

parser.setInput(reader);

parser.nextTag();

parser.require(XmlPullParser.START_TAG, null, "menu");

while (parser.nextTag() == XmlPullParser.START_TAG) {

parser.require(XmlPullParser.START_TAG, null, "item");

String itemText = parser.nextText();

parser.nextTag(); // this call shouldn’t be necessary!

parser.require(XmlPullParser.END_TAG, null, "item");

System.out.println("menu option: " + itemText);

}

parser.require(XmlPullParser.END_TAG, null, "menu");

}

public static void main(String[] args) throws Exception {

new Menu().parseXml(new StringReader("<?xml version='1.0'?>"

+ "<menu>"

+ " <item>Waffles</item>"

+ " <item>Coffee</item>"

+ "</menu>"));

}

在android4.0中,改变了Xml.newPullParser()返回KxmlParser类,同时删除了ExpatPullParser类。这样就修正了nextTag()的bug.

不幸的是,当前可能会崩溃的应用程序都是低于android4.0版本的,下面是错误信息。

[html] view
plaincopy

org.xmlpull.v1.XmlPullParserException: expected: END_TAG {null}item (position:START_TAG <item>@1:37 in java.io.StringReader@40442fa8)

at org.kxml2.io.KXmlParser.require(KXmlParser.java:2046)

at com.publicobject.waffles.Menu.parseXml(Menu.java:25)

at com.publicobject.waffles.Menu.main(Menu.java:32)

解决的办法是只有在调用nextText()之后再跳用nextTag(),仅当当前的位置不是END_TAG。

[html] view
plaincopy

while (parser.nextTag() == XmlPullParser.START_TAG) {

parser.require(XmlPullParser.START_TAG, null, "item");

String itemText = parser.nextText();

if (parser.getEventType() != XmlPullParser.END_TAG) {

parser.nextTag();

}

parser.require(XmlPullParser.END_TAG, null, "item");

System.out.println("menu option: " + itemText);

}

上面的代码可以正确解析所有xml版本,如果应用程序广范的使用了nextText(),那就在使用nextText()的地方用下面的辅助方法。

[html] view
plaincopy

private String safeNextText(XmlPullParser parser)

throws XmlPullParserException, IOException {

String result = parser.nextText();

if (parser.getEventType() != XmlPullParser.END_TAG) {

parser.nextTag();

}

return result;

}

使用单一的XmlPullParse简化了我们的维护,同时可以让我们有更多的精力花费在调高系统的性能。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: