(1)、在安卓平台上提供了三种解析xml文件的方式:SAX、DOM与PULL,有关前两种解析方式在java EE中用途较广,着重研究PULL技术。
(2)、PULL解析器是一个开源的java项目,既可以用在Android上,也可以用在java EE上,无需添加任何jar文件,但java EE需要添加jar文件,安卓系统本身用到许多xml文件,其内部也是采用PULL解析器进行解析的,运行方式与SAX相似,提供了类似的事件,如开始元素与结束元素事件,使用parse.next()可以进入下一个元素并触发相应事件,跟SAX不同的是,PULL解析器产生的事件是一个数字,,而非方法,因此可以使用一个switch对感兴趣的事件进行处理,当元素开始解析时,调用parse.nextText()的方法可以获取下一个Text类型的节点的值。
(3)、新建安卓项目:Xml,在src目录里新建一个person.xml文件,内容如下:
放在这里稍后进行解析
(4)、关于xml的语法:第一行:start document(开始文档语法),末尾看不见的地方叫end doucment(结束文档语法),结点类型有两种(Node type):Element Node/Text Node.
(5)、编写解析业务,写在service包下,名称为PersonService,在这里我们需要考虑一下,假设现在所有的数据已经被解析出来,应该使用javaBean对数据进行存储,再通过一个集合存储所有数据,javaBean属于实体,放在model包下,名为Person,里面有(id,name,age).
(6)、写一个业务方法,名称为getPersons,返回值为person的List类型,xml文件内容以输入流的方式传入进来。接下来使用PULL解析器。
(7)、创建一个XmlPullParser 对象,并且使用XmlPullParserFactory的工厂类的newInstance()方法再调用newPullParser()方法获得一个PULL解析器。在这里需要注意的是,有一种更加简单获得PULL解析器的方法,就是使用工具类Xml下面的new PullParser()方法同样能够获得解析器对象。下面要为破解器设置要解析的Xml数据,调用破解器的setInput(InputStream,inputEncoding)方法。
PULL的解析原理:
首先会将指定的xml文件内容读到一个字符数组当中(char[]={
(8)、因此,我们调用解析器的getEventType()方法产生第一个事件,所产生的是一个数字(int),对其进行存放:int event=pullParser.getEventType();接下来使用switch语句进行判断
Switch(){
Case XmlPullParser.START_DOCUMENT:
//首先在开头先定义一个person的List集合,对其进行初始化操作:List
Persons=new ArrayList
/*做到这里需要注意,pull解析器一旦读取完第一行的事件之后就不会主动地去解析下面的数据,如果希望解析器往后解析,需要调用解析器的next()这个API,她的作用是会将解析器的指针进入后一个节点并触发其相应的事件,例如上面例子中的
}
While(event!=XmlPullPraser.END_DOCUMENT){
Switch(){
}
}
(9)、继续解析,当解析到
If(pullPraser.getName().equals(“person”)){
Int id==new Integer(pullPraser.getAttributeValue(0));//获得属性值(intindex)
}
Text节点无需进行处理
If(pullPraser.getName().equals(“name”)){
String name==pullPraser.nextText();//取得后面文本节点的节点值
}
当读取到时,不作任何操作:case XmlPullPraser.END_TAG
读取到
If(pullPraser.getName().equals(“age”)){
Int age=new Integer(pullPraser.nextText());//取得后面文本节点的节点值
}
接下来将获取到的信息封装到一个person的javaBean里去,在开头创建一个person对象,
Person person=null;
在读取到开始标记时,new Person();
在以下的case语句中调用set方法对其进行赋值。在第一个person信息解析完成后,需要将结果放在List集合中,因此在END_TAG中进行判断:
If(pullPraser.getName().equals(“person”)){
Persons.add(person);
Person=null;
}
最后将persons返回
(10)、下面对其此方法进行测试:
这里需要注意,xml文件被创建在src目录下,一旦程序编译后,编译文件会在类路径上,因此可以调用该类的this.getClass().getClassLoader().getResourcesAsStream(“person.xml”);
Persons=调用get方法
For(Person person:persons){
Log.i();
}
源代码:
public class PersonService {
publicList
List
Personperson=null;
XmlPullParserpullParser=Xml.newPullParser();
//XmlPullParserpullParser=XmlPullParserFactory.newInstance().newPullParser();
pullParser.setInput(xml,"UTF-8");
intevent=pullParser.getEventType();
while(event!=XmlPullParser.END_DOCUMENT){
switch (event) {
caseXmlPullParser.START_DOCUMENT:{
persons=newArrayList
break;
}
caseXmlPullParser.START_TAG:{
if(pullParser.getName().equals("person")){
intid=Integer.parseInt(pullParser.getAttributeValue(0));
person=newPerson();
person.setId(id);
}
if(pullParser.getName().equals("name")){
Stringname=pullParser.nextText();
person.setName(name);
}
if(pullParser.getName().equals("age")){
intage=Integer.parseInt(pullParser.nextText());
person.setAge(age);
}
}
caseXmlPullParser.END_TAG:{
if(pullParser.getName().equals("person")){
persons.add(person);
person=null;
}
break;
}
}
pullParser.next();
}
return persons;
}
}
测试代码:
private static finalString TAG="PersonServiceTest";
public voidgetPersonsTest() throws Exception{
InputStreamxml=this.getClass().getClassLoader().getResourceAsStream("person.xml");
PersonServiceservice=new PersonService();
List
for(Personperson:persons){
Log.i(TAG,person.toString());
}
}
(11)、反过来,将指定的信息写入到xml文件中:
思路:可以使用Stringbuilder方法下的append()方法,这样做比较简单,但是有缺陷:其一,她不符合面向对象程序设计的思想;其二,在写入信息中有特殊字符的时候,用这种API可能会出错,造成乱码。
(12)、下面使用面向对象的方法进行实现:
1、首先创建一个save()方法,传入一个List集合对象与输出流对象,首先需要创建一个xmlpull的序列化器,同理,使用Xml工具类的newSeriazle()方法快速得到一个序列化器。
2、接下来为序列化器设置输出方向,调用setOutput(OutputStream,Encoding)。
3、首先输出START DOCUMENT内容,调用序列化器的startDocument(Encoding,standalone)API.第二个参数是一个布尔类型的值,用来指定该文件是否单独存在而不依赖于其他文件,一般设为true。
4、有开始文档语法,必然有结束文档语法:endDocument();
5、接下来输出主体内容:startTag(namespace,name) endTag(namespace,name)
6、在Tag中间使用增强型for循环迭代传入的List集合
7、starttAG(PERSON) endTag(person),中间调用序列化器的attribute(namespace,name,value)方法
8、以下同理
9、最后out.flush()并关闭
运行结果正确:
源代码:
public void save(List
//XmlSerializerserializer=XmlPullParserFactory.newInstance().newSerializer();
XmlSerializerserializer=Xml.newSerializer();
serializer.setOutput(xml,"UTF-8");
serializer.startDocument("UTF-8",true);
serializer.startTag(null,"persons");
for(Personperson: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();
xml.flush();
xml.close();
}
测试方法:
public void testSave() throws Exception{
List
Person p1=newPerson(1,"林月如",20);
Person p2=newPerson(2,"唐雨柔",19);
Person p3=newPerson(3,"赵灵儿",18);
persons.add(p1);
persons.add(p2);
persons.add(p3);
File xml=newFile(this.getContext().getFilesDir(),"students.xml");
FileOutputStreamout=new FileOutputStream(xml);
PersonServiceservice=new PersonService();
service.save(persons,out);
}