这一章我们来学习Android中的XML解析器,Android中自带了三个XML解析器,有PULL,SAX,DOM解析器,其中PULL跟SAX都是以事件作为驱动导向的解析器,优点是占用内存小,处理速度快,DOM是将整个XML放入内存中再解析,处理速度要稍差一些,但DOM也有自己的优点,可以在解析的时候适当增加节点.OK,我们先来看一下我们要解析的xml文件
- <?xml
version="1.0" encoding="UTF-8"?> - <persons>
-
<person id = "1"> -
<status>大徙弟</status> -
<name>孙悟空</name> -
<tool>金箍棒</tool> -
<number>杀死了50只妖怪</number> -
</person> -
-
<person id = "2"> -
<status>二徙弟</status> -
<name>猪八戒</name> -
<tool>九齿钉耙 </tool> -
<number>杀死了40只妖怪</number> -
</person> -
-
<person id = "3"> -
<status>三徙弟</status> -
<name>沙和尚</name> -
<tool>降妖宝杖</tool> -
<number>杀死了30只妖怪</number> -
</person> -
- </persons>
这里面定义了一些个人的信息和其他具体信息,好了,存入模拟器的SD目录下,接下来,我们先定义JavaBean,Person.java
- public
class Person - {
-
private String id; -
private String status; -
private String name; -
private String tool; -
private String number; -
-
-
public String getId() -
{ -
return id; -
} -
public void setId(String id) -
{ -
this.id = id; -
} -
public String getStatus() -
{ -
return status; -
} -
public void setStatus(String status) -
{ -
this.status = status; -
} -
public String getName() -
{ -
return name; -
} -
public void setName(String name) -
{ -
this.name = name; -
} -
public String getTool() -
{ -
return tool; -
} -
public void setTool(String tool) -
{ -
this.tool = tool; -
} -
public String getNumber() -
{ -
return number; -
} -
public void setNumber(String number) -
{ -
this.number = number; -
} -
@Override -
public String toString() -
{ -
return "Person [id=" + id + ", status=" + status + ", name=" + name -
+ ", tool=" + tool + ", number=" + number + "]"; -
} -
- }
对应上面xml的文件中的数据,接下来就是重点喽,要好好学哦,呵呵,PULL解析类PullHandler.java
- import
java.io.InputStream; - import
java.util.ArrayList; - import
java.util.List; -
- import
org.xmlpull.v1.XmlPullParser; -
- import
android.util.Xml; -
- public
class PullHandler - {
-
private InputStream input; -
private List<Person> persons; -
private Person person; -
-
public PullHandler() -
{ -
} -
-
public void setInput(InputStream input) -
{ -
this.input = input; -
} -
-
public PullHandler(InputStream input) -
{ -
this.input = input; -
} -
-
public List<Person> getPersons() -
{ -
try -
{ -
XmlPullParser parser = Xml.newPullParser(); -
parser.setInput(input, "UTF-8"); -
int eventType = parser.getEventType(); -
-
while (eventType != XmlPullParser.END_DOCUMENT) -
{ -
-
switch (eventType) -
{ -
//XmlPullParser.START_DOCUMENT表示开始文档事件 -
case XmlPullParser.START_DOCUMENT: -
-
persons = new ArrayList<Person>(); -
-
break; -
-
// XmlPullParser.START_TAG: 开始标签 -
case XmlPullParser.START_TAG: -
-
//parser.getName()获取节点的名称 -
String tag = parser.getName(); -
-
if ("person".equals(tag)) -
{ -
person = new Person(); -
//parser.getAttributeName(0)取得<person id="1">中的第一个属性值 -
String id = parser.getAttributeValue(0); -
person.setId(id); -
} -
if (null != person) -
{ -
if ("status".equals(tag)) -
{ -
//parser.nextText();获取下一个text类型的节点 -
person.setStatus(parser.nextText()); -
} -
if ("name".equals(tag)) -
{ -
person.setName(parser.nextText()); -
} -
if ("tool".equals(tag)) -
{ -
person.setTool(parser.nextText()); -
} -
if ("number".equals(tag)) -
{ -
person.setNumber(parser.nextText()); -
} -
} -
-
break; -
-
// XmlPullParser.END_TAG:结束标签 -
case XmlPullParser.END_TAG: -
-
if ("person".equals(parser.getName())) -
{ -
persons.add(person); -
person = null; -
} -
-
-
break; -
-
} -
-
//event=parser.next();继续下一个元素 -
eventType = parser.next(); -
-
} -
-
input.close(); -
-
return persons; -
-
} catch (Exception e) -
{ -
e.printStackTrace(); -
} -
return null; -
-
} -
- }
OK,解析类写完了,测试一下吧,用上一节课的单元测试试一下呢,对于每个小方法做单元测试很重要,这要能及时解决出现的问题,呵呵,我快像唐僧一样了,阿弥陀佛,要是不明日章元测试的话,就看一下
Android[中级教程]第四章 单元测试AndroidTestCase
- import
java.io.File; - import
java.io.FileInputStream; - import
java.util.List; -
- import
android.os.Environment; - import
android.test.AndroidTestCase; -
- public
class PullHandlerTest extends AndroidTestCase - {
-
public void testGetPersons(){ -
-
//取得当前SD目录下的文件路径 -
File SD_Files = Environment.getExternalStorageDirect ory(); -
//取得persons.xml文件的路径,这里我是存在sdcard/persons.xml -
String file_path = SD_Files.getName() + File.separator + "persons.xml"; -
try -
{ -
FileInputStream fis = new FileInputStream(new File(file_path)); -
PullHandler pullHandler = new PullHandler(fis); -
List<Person> persons = pullHandler.getPersons(); -
//输出persons中的数据 -
System.out.println(persons); -
-
} catch (Exception e) -
{ -
// TODO Auto-generated catch block -
e.printStackTrace(); -
} -
-
-
} - }
测试类写完了,测试一下吧,OK,接下来就是定义main.xml了
- <?xml
version="1.0" encoding="utf-8"?> - <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" -
android:orientation="vertical" android:layout_width="match_parent" -
android:layout_height="match_parent"> -
<TextView android:textAppearance="?android:attr/textAppearanceMedium" -
android:layout_width="wrap_content" android:text="唐僧的三个徙弟" -
android:layout_height="wrap_content" android:id="@+id/textView1" -
android:paddingLeft="10dip" android:paddingBottom="10dip"></TextView> -
<ListView android:id="@+id/xml_list" android:layout_height="wrap_content" -
android:layout_width="match_parent"></ListView> -
- </LinearLayout>
定义了一个ListView和一个TextView,ListView是准备显示xml中的数据的
再定义一个list_item.xml是每一行要显示数据的样式
- <?xml
version="1.0" encoding="utf-8"?> - <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" -
android:orientation="vertical" android:layout_width="match_parent" -
android:layout_height="match_parent"> -
<LinearLayout android:layout_height="wrap_content" -
android:id="@+id/linearLayout1" android:layout_width="match_parent"> -
<TextView android:layout_height="wrap_content" -
android:textAppearance="?android:attr/textAppearanceMedium" -
android:layout_width="wrap_content" android:text="ID: " -
android:paddingLeft="10dp"></TextView> -
<TextView android:layout_height="wrap_content" -
android:textAppearance="?android:attr/textAppearanceMedium" -
android:layout_width="wrap_content" android:text="TextView" -
android:id="@+id/id"></TextView> -
<TextView android:layout_height="wrap_content" -
android:textAppearance="?android:attr/textAppearanceMedium" -
android:layout_width="wrap_content" android:text="TextView" -
android:id="@+id/name" android:paddingLeft="30dp"></TextView> -
</LinearLayout> -
<LinearLayout android:layout_height="wrap_content" -
android:id="@+id/linearLayout2" android:layout_width="match_parent"> -
<TextView android:layout_height="wrap_content" -
android:layout_width="wrap_content" android:text="杀死了" -
android:paddingLeft="10dp"></TextView> -
<TextView android:text="TextView" android:id="@+id/number" -
android:layout_width="wrap_content" android:layout_height="wrap_content" -
android:textColor="#FF0000"></TextView> -
<TextView android:text="只妖怪" android:layout_width="wrap_content" -
android:layout_height="wrap_content"></TextView> -
</LinearLayout> -
- </LinearLayout>
好了,都定义完了,最后就是我们的Activity了
- </pre><pre
class="java" name="code">import java.io.File; - import
java.io.FileInputStream; - import
java.util.ArrayList; - import
java.util.HashMap; - import
java.util.List; - import
java.util.Map; -
- import
android.app.Activity; - import
android.os.Bundle; - import
android.os.Environment; - import
android.widget.ListView; - import
android.widget.SimpleAdapter; -
- public
class PullActivity extends Activity - {
-
-
private ListView listView; -
private SimpleAdapter adapter; -
-
@Override -
protected void onCreate(Bundle savedInstanceState) -
{ -
// TODO Auto-generated method stub -
super.onCreate(savedInstanceState); -
setContentView(R.layout.xml_handler); -
-
listView = (ListView)findViewById(R.id.xml_list); -
try -
{ -
//自完义适配方法 -
getAdapter(); -
-
} catch (Exception e) -
{ -
e.printStackTrace(); -
} -
listView.setAdapter(adapter); -
} -
-
//自定义适配方法 -
private void getAdapter() throws Exception -
{ -
List<Map<String, String>> lists = new ArrayList<Map<String, String>>(); -
-
//这一部分就是刚才我们做测试用的部分 -
File SD_Files = Environment.getExternalStorageDirect ory(); -
String file_path = SD_Files.getName() + File.separator + "persons.xml"; -
FileInputStream input = new FileInputStream(new File(file_path)); -
PullHandler pullHandler = new PullHandler(input); -
List<Person> persons = pullHandler.getPersons(); -
-
//将persons中的数据转换到ArrayList<Map<String, String>>中,因为SimpleAdapter要用这个类型的数据进行适配 -
Map<String, String> map; -
for(Person p : persons){ -
map = new HashMap<String, String>(); -
-
map.put("id", p.getId()); -
map.put("status", p.getStatus()); -
map.put("name", p.getName()); -
map.put("tool", p.getTool()); -
map.put("number", p.getNumber()); -
-
lists.add(map); -
} -
-
//HashMap<String, String>中的key -
String[] from = {"id", "status", "name", "tool", "number"}; -
//list_item.xml中对应的控件ID -
int[] to = {R.id.item_id, R.id.item_status, R.id.item_name, R.id.item_tool, R.id.item_number}; -
-
adapter = new SimpleAdapter(this, lists, R.layout.handler_list_item, from, to); -
-
} - }
好了,最后就是上图了
这一章有点长,希望同学们都看完,因为接下来的SAX解析和DOM解析,我们还需要用到这里面的模板,谢谢