XML解析三种方式
DOM
通用性强,它会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树、检索所需的数据;
简单直观,但需要将文档读取到内存,并不太适合移动设备;SAX
SAX是一个解析速度快并且占用内存少的xml解析器;
采用事件驱动,它并不需要解析整个文档;
实现:继承DefaultHandler,覆写startElement、endElement、characters等方法;
PULL
Android自带的XML解析器,和SAX基本类似,也是事件驱动,不同的是PULL事件返回的是数值型;推荐使用。
PULL解析XML核心代码
- 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方法
- 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文件
- <?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>
- 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布局文件
- <?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 version=”1.0″ ?>
- <statuses>
- <status>
- <source1>a</source1>
- <source2>a</source2>
- <source2>a</source2>
- </status>
- <statuses>
- </xml>
解析代码.
- 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 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>
解析代码:
- 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>不循环.
可以使用.
- for (int i=0;i<3;i++){
- parser.nextTag();
- Log.v(“tag”,parser.getName()+”=”+ parser.nextText());
- }
代替.
开发过程中遇到 XmlPullParser.netText()方法造成的Bug
解决如下:
在android4.0中,改变了Xml.newPullParser()返回KxmlParser类,同时删除了ExpatPullParser类。这样就修正了
nextTag()的bug.
解决的办法是只有在调用
nextText()之后再跳用
nextTag(),仅当当前的位置不是
END_TAG。
上面的代码可以正确解析所有xml版本,如果应用程序广范的使用了
nextText(),那就在使用
nextText()的地方用下面的辅助方法。
使用单一的XmlPullParse简化了我们的维护,同时可以让我们有更多的精力花费在调高系统的性能。
开发过程中遇到 XmlPullParser.netText()方法造成的Bug
解决如下:
在Android上使用XmlPullParser是一中高效率和易维护解析XML的方法 。Android已经在历史上有两个实现这个接口实现类:
-
KXmlParser,通过XmlPullParserFactory.newPullParser() 。
-
ExpatPullParser,通过Xml.newPullParser() 。
实现Xml.newPullParser()
调用nextText()有个错误,nextText()
并不总是向文档中所提到优先于END_TAG执行
。
因此,一些应用可能会出现bug在额外调用next()或nextTag();
- 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版本的,下面是错误信息。
- 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)
- 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);
- }
- private String safeNextText(XmlPullParser parser)
- throws XmlPullParserException, IOException {
- String result = parser.nextText();
- if (parser.getEventType() != XmlPullParser.END_TAG) {
- parser.nextTag();
- }
- return result;
- }