本文是基于黎活明老师的传智博客android第7个和8个视频总结的,如果想更清楚的理解,建议观看视频
以下面这个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>
里面的所有东西都可以统称为节点<person> 李明 30 都为节点
而更准确的说 <person> <name> <age>为element,即为元素
而 李明 30 为text,即为文本节点
而 id 为属性,"23"为属性值
第2行与第3行之间的空格也是一个节点
新建一个person类在lyh.domain 根据xml文件设置相对应的变量和方法
package lyh.domain; public class Person { private int id; private String name; private short age; public Person() { } public Person(int id, String name, short age) { this.id = id; this.name = name; this.age = age; } public Person(String name, short age) { this.name = name; this.age = age; } public int getId() { return id; } public void setId(int 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() { // TODO Auto-generated method stub return "id="+id+",name="+ name + ",age="+ age; } }
编写业务bean
package lyh.service; import java.io.InputStream; import java.io.Writer; import java.util.ArrayList; import java.util.List; import lyh.domain.Person; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; import android.util.Xml; public class PullPersonService { public static void writeXml(List<Person> persons , Writer writer) throws Exception{ //1.使用android的XML工具类去创建一个序列化对象 XmlSerializer serializer = Xml.newSerializer(); //2.设置xml文件输出的位置 serializer.setOutput(writer); //3.设置xml字符编码和standalone属性 serializer.startDocument("UTF-8", true); //4.设置开始标签的命名空间前缀和标签的名称,startTag与endTag应成对出现 serializer.startTag(null, "persons"); //5.通过迭代从list中取出每个person以便写出 for(Person person : persons){ serializer.startTag(null, "person"); //6.设置id的值 serializer.attribute(null, "id", String.valueOf(person.getId())); //7.设置name的文本 serializer.startTag(null, "name"); serializer.text(person.getName()); serializer.endTag(null, "name"); //8.设置age的文本 serializer.startTag(null, "age"); serializer.text(String.valueOf(person.getAge())); serializer.endTag(null, "age"); serializer.endTag(null, "person"); } //9.设置结束标签的命名空间前缀和标签的名称 serializer.endTag(null, "persons"); //10.设置结束文档 serializer.endDocument(); //11.writer为缓冲输出类,需要刷出到文件,然后关闭 writer.flush(); writer.close(); } public static List<Person> readXml(InputStream inStream) throws Exception{ List<Person> persons = null; Person person = null; //1.使用android提供的Xml类new一个XmlPullerParser,即new一个XmlPull解析器 XmlPullParser parser = Xml.newPullParser(); //2.然后设置需要解析的xml文件,第一个参数为输入流,第二个参数为字符编码 parser.setInput(inStream, "UTF-8"); //3.触发事件,当这个方法遇到某个字符符合XML语法,就会触发这个语法所代表的数字 int eventCode = parser.getEventType(); //4.XML文件的第一行为开始文档事件START_DOCUMENT,最后一行为结束文档事件END_DOCUMENT,我们需要不断读取xml文件的内容 while( XmlPullParser.END_DOCUMENT != eventCode ){ //5.我们对这个事件进行处理,我们感兴趣的是<person>这个元素 switch(eventCode){ case XmlPullParser.START_DOCUMENT://开始文档事件 persons = new ArrayList<Person>();//初始化用来存放person的List break; case XmlPullParser.START_TAG://6.如果这个事件是开始元素(例如<persons>)事件 if("person".equals(parser.getName())){ person = new Person(); //7.使用解析器得到当前元素的属性,即id person.setId(new Integer(parser.getAttributeValue(0))); }else if(person!=null){ if("name".equals(parser.getName())){ //8.如果当前元素为开始标签,下一个元素为文本,就会返回这个文本 person.setName(parser.nextText()); }else if("age".equals(parser.getName())){ //8.如果当前元素为开始标签,下一个元素为文本,就会返回这个文本 person.setAge(new Short(parser.nextText())); } } break; case XmlPullParser.END_TAG://9.如果这个事件是结束元素(例如</persons>)事件 if("person".equals(parser.getName()) && person != null){ //往List里添加person,并把person置空,以便下次的读取 persons.add(person); person = null; } break; } //10.当我们第一次调用getEventType()方法,得到的是XML文件的第一行,即<?xml version="1.0" encoding="UTF-8"?>,所以需要再往下一行读取 //接着就遇到了<persons>,触发一个事件,再往下就是空格,触发一个事件,如此类推 eventCode = parser.next(); } //11.返回储存好的list return persons; } }
编写单元测试类,需要测试时,请把itcase.xml放入到src文件夹中
package lyh.xml; import java.io.InputStream; import java.util.List; import lyh.domain.Person; import lyh.service.PullPersonService; import android.test.AndroidTestCase; import android.util.Log; public class XmlPersonServiceTest extends AndroidTestCase{ private static final String TAG = "PullPersonServiceTest"; //使用pull解析xml内容 public void testPullReadXml() throws Exception{ InputStream inStream = XmlPersonServiceTest.class.getClassLoader().getResourceAsStream("itcase.xml"); List<Person> persons = PullPersonService.readXml(inStream); for(Person person : persons){ Log.i(TAG, person.toString()); } inStream.close(); } }
配置AndroidManifest.xml文件,为其配置单元测试环境
在<application android:icon="@drawable/icon" android:label="@string/app_name">
下面加入
<uses-library android:name="android.test.runner"/>
在 <uses-sdk android:minSdkVersion="10" />下面加入
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="lyh.xml" android:label="Tests for My App"/>
注意android:targetPackage="lyh.xml" 要与原配置文件中的package的一致
在通过了单元测试以后就可以在XmlActivity中编写了
将TextView的id设置为result,将xml文件内容输出到手机屏幕上
package lyh.xml; import java.io.InputStream; import java.util.List; import lyh.domain.Person; import lyh.service.PullPersonService; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.widget.TextView; import android.widget.Toast; public class XmlActivity extends Activity { private static final String TAG = "XmlActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView resultView = (TextView)this.findViewById(R.id.result); InputStream inStream = XmlActivity.class.getClassLoader().getResourceAsStream("itcase.xml"); try { List<Person> persons = PullPersonService.readXml(inStream); StringBuilder sb = new StringBuilder(); for( Person person : persons){ sb.append(person.toString()).append("/n"); } resultView.setText(sb.toString()); } catch (Exception e) { Log.e(TAG, e.toString()); Toast.makeText(this, "解析失败", Toast.LENGTH_LONG).show(); } } }
使用pull输出xml文件
在PullPersonService编写一个writeXml方法
public static void writeXml(List<Person> persons , Writer writer) throws Exception{ //1.使用android的XML工具类去创建一个序列化对象 XmlSerializer serializer = Xml.newSerializer(); //2.设置xml文件输出的位置 serializer.setOutput(writer); //3.设置xml字符编码和standalone属性 serializer.startDocument("UTF-8", true); //4.设置开始标签的命名空间前缀和标签的名称,startTag与endTag应成对出现 serializer.startTag(null, "persons"); //5.通过迭代从list中取出每个person以便写出 for(Person person : persons){ serializer.startTag(null, "person"); //6.设置id的值 serializer.attribute(null, "id", String.valueOf(person.getId())); //7.设置name的文本 serializer.startTag(null, "name"); serializer.text(person.getName()); serializer.endTag(null, "name"); //8.设置age的文本 serializer.startTag(null, "age"); serializer.text(String.valueOf(person.getAge())); serializer.endTag(null, "age"); serializer.endTag(null, "person"); } //9.设置结束标签的命名空间前缀和标签的名称 serializer.endTag(null, "persons"); //10.设置结束文档 serializer.endDocument(); //11.writer为缓冲输出类,需要刷出到文件,然后关闭 writer.flush(); writer.close(); }
在XmlPersonServiceTest中写一个单元测试,当然也可以在activity中写,不过最好先进行单元测试
//使用pull写入xml内容 public void testPullWriteXml() throws Exception{ //1.设置输出流,输出到persons.xml且这个文件的权限为可读的 FileOutputStream outStream = this.getContext().openFileOutput("persons.xml",Context.MODE_WORLD_READABLE); OutputStreamWriter writer = new OutputStreamWriter(outStream,"UTF-8"); List<Person> persons = new ArrayList<Person>(); persons.add(new Person(11,"老毛",(short)20)); persons.add(new Person(12,"撒旦",(short)30)); persons.add(new Person(13,"飞飞",(short)31)); PullPersonService.writeXml(persons,writer); outStream.flush(); outStream.close(); }
进行单元测试以后就可以使用文件浏览器到data.lyh.xml.files文件夹下查看到persons.xml文件了,可以使用右上方的 Pull a file from the device按钮把文件提取到电脑上查看