本文参考学习了:
http://blog.csdn.net/liuhe688/article/details/6415593/
我这里主要考虑实战性,只学习pull方式,给出一些需要注意的地方!!!
通常Android下xml解析方式有三种:
1、sax解析
2、pull解析
3、dom解析
sax和pull都是基于事件驱动的,区别就是sax事件是系统指定的,
pull是程序员代码启动的。
dom是以树状结构进行解析,确定就是文件非常大,一下子加载在内存ram里面,太损耗内存了,卡死。
android推荐使用pull解析,自带解析器。所以个人认识把pull解析搞懂就可以了,当然,你有时间也可以学习其他两种模式!!!别学我偷懒啊
demo:
在工程的根目录下创建/assets/books.xml文件,内容:
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book
year="2001"
type="java技术"
>
<id> 1001
</id>
<name> Thinking In Java
</name>
<price> 80.00
</price>
</book>
<book
year="2002"
type="java技术"
>
<id> 1002
</id>
<name> Core Java
</name>
<price> 90.00
</price>
</book>
<book
year="2003"
type="android技术"
>
<id> 1003
</id>
<name> Hello, Andriod
</name>
<price> 100.00
</price>
</book>
<book
year="2004"
type="文学"
>
<id>1004</id>
<name>西游记</name>
<price>150.00</price>
</book>
<book
year="2005"
type="禁书"
>
<id> 1005
</id>
<name> 金瓶梅
</name>
<price> 200.00
</price>
</book>
</books>
对这个xml文件进行解析,之后再把解析出来的内容写到
data/data/应用包名/files/book2.xml中
对这个xml进行分析,抽象出一个
book.java
package com.example.pull_dom_parser;
public class Book {
/*
* <id> 1001 </id> <name> Thinking In Java </name> <price> 80.00 </price>
*/
private String yearString, type, id, name, price;
public Book() {
super();
}
public Book(String yearString, String type, String id, String name,
String price) {
super();
this.yearString = yearString;
this.type = type;
this.id = id;
this.name = name;
this.price = price;
}
public String getYearString() {
return yearString;
}
public void setYearString(String yearString) {
this.yearString = yearString;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
@Override
public String toString() {
return "Book [yearString=" + yearString + ", type=" + type + ", id="
+ id + ", name=" + name + ", price=" + price + "]";
}
}
为了实现pull\dom\sax三种模式的扩展,可以定义接口
BookParser.java:
/**
*
*/
package com.example.pull_dom_parser;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
/**
* @author lihui20
*
*/
public interface BookParser {
// 读取
public List<Book> readFromXML(InputStream inputStream);
// 写入
String writeToXML(List<Book> list);
}
后面可以根据不同的方式实现这个接口,重写接口方法。
这里我使用pull方式:
PullBookParse .java
package com.example.pull_dom_parser;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
import android.util.Log;
import android.util.Xml;
public class PullBookParse implements BookParser {
@Override
public List<Book> readFromXML(InputStream inputStream) {
// TODO Auto-generated method stub
XmlPullParser xmlPullParser = Xml.newPullParser();
List<Book> books = null;
Book book = null;
try {
xmlPullParser.setInput(inputStream, "UTF-8");
int eventType = xmlPullParser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
// 一次
books = new ArrayList<Book>();
break;
case XmlPullParser.START_TAG:
if (xmlPullParser.getName().equals("book")) {
book = new Book();
// year type
book.setYearString(xmlPullParser.getAttributeValue(0));
book.setType(xmlPullParser.getAttributeValue(1));
} else if (xmlPullParser.getName().equals("id")) {
book.setId(xmlPullParser.nextText());
} else if (xmlPullParser.getName().equals("name")) {
book.setName(xmlPullParser.nextText());
} else if (xmlPullParser.getName().equals("price")) {
book.setPrice(xmlPullParser.nextText());
}
break;
case XmlPullParser.END_TAG:
if (xmlPullParser.getName().equals("book")) {
books.add(book);
}
break;
case XmlPullParser.END_DOCUMENT:
break;
default:
break;
}
// next下一个事件
eventType = xmlPullParser.next();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return books;
}
@Override
public String writeToXML(List<Book> list) {
// TODO Auto-generated method stub
// 能读取,就可以写到xml里面
// 定义头标签
XmlSerializer xmlSerializer = Xml.newSerializer();
StringWriter stringWriter = new StringWriter();
String namespace = "";
try {
xmlSerializer.setOutput(stringWriter);
xmlSerializer.startDocument("UTF-8", true);
xmlSerializer.startTag(namespace, "books");
for (Book book : list) {
xmlSerializer.startTag(namespace, "book");
xmlSerializer
.attribute(namespace, "year", book.getYearString());
xmlSerializer.attribute(namespace, "type", book.getType());
//
xmlSerializer.startTag(namespace, "id");
xmlSerializer.text(book.getId());
xmlSerializer.endTag(namespace, "id");
//
xmlSerializer.startTag(namespace, "name");
xmlSerializer.text(book.getName());
xmlSerializer.endTag(namespace, "name");
//
xmlSerializer.startTag(namespace, "price");
xmlSerializer.text(book.getPrice());
xmlSerializer.endTag(namespace, "price");
//
xmlSerializer.endTag(namespace, "book");
}
xmlSerializer.endTag("", "books");
xmlSerializer.endDocument();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("test1448",
"stringWriter.toString()---" + stringWriter.toString());
// 开始写xml,标签、内容
return stringWriter.toString();
}
}
注解:
这里用到了stringbuffer,这个流不是把内容写到文件、xml、txt、数据库等里面的,是把文字写到RAM内存里的,临时存放。用于后续输出到book2.xml中。
pull解析主要是事件驱动
int eventType = xmlPullParser.getEventType();
事件类型:
1、解析文档开始事件
2、遇到开始标签事件
<xxxx>
3、遇到结束事件
</xxxx>
4、解析文档结束事件
文本类型
文本类型2个:
1、标签文本
<xxx></xxx>
这里的xxx就是标签文本
2、text内容文本
就是除了标签文本外出现的文字
hello<xxx>12312213</xxx>world
hello
12312213
world
这些是text文本
好了,工具写好了。
在activity中调用吧。
package com.example.pull_dom_parser;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener {
Button readButton, writeButton;
TextView showText;
Context mContext;
private List<Book> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
initView();
}
private void initView() {
// TODO Auto-generated method stub
readButton = (Button) findViewById(R.id.button1);
writeButton = (Button) findViewById(R.id.button2);
showText = (TextView) findViewById(R.id.textView1);
readButton.setOnClickListener(this);
writeButton.setOnClickListener(this);
}
@SuppressWarnings("resource")
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.button1:
PullBookParse pullBookParse = new PullBookParse();
AssetManager assetManager = getResources().getAssets();
InputStream inputStream = null;
try {
inputStream = assetManager.open("books.xml");
list = pullBookParse.readFromXML(inputStream);
StringBuffer stringBuffer = new StringBuffer();
for (Book book : list) {
stringBuffer.append(book.toString() + "\r\n");
}
showText.setText("从xml中读取内容:\r\n" + stringBuffer.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
break;
case R.id.button2:
// data/data/包名 下生成一个文件,把读取的内容写进去
PullBookParse bookParser = new PullBookParse();
File xmlFile = new File(getFilesDir().getAbsoluteFile(),
"books2.xml");
String xmlString = bookParser.writeToXML(list);
Log.d("xmlString", "xmlString---" + xmlString);
// OutputStream out = null;
try {
// out = new FileOutputStream(xmlFile);
FileOutputStream out = this.openFileOutput("books3.xml",
MODE_PRIVATE);
BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(out));
bufferedWriter.write(xmlString);
bufferedWriter.flush();
out.close();
bufferedWriter.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
case R.id.textView1:
break;
default:
break;
}
}
}
layout.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.pull_dom_parser.MainActivity" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="读取xml" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/button1"
android:layout_alignBottom="@+id/button1"
android:layout_toRightOf="@+id/button1"
android:text="写入xml" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button1"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/button1"
android:text="TextView" />
</RelativeLayout>
注解:
在每个目录下,一般有这么几个子目录经常使用到:
databases : 存放数据库
cache : 存放缓存数据
files : 存放应用程序自己控制的文件
lib : 存放使用的包
每个应用程序的代码,对自己的目录是有绝对的控制权限的。
我们使用了files目录。
获取可以使用:
FileOutputStream out = this.openFileOutput(“books3.xml”,
MODE_PRIVATE);
或者:
File xmlFile = new File(getFilesDir().getAbsoluteFile(),
“books2.xml”);
当用输出流bufferwriter需要
bufferedWriter.flush();之后,
out.close();
bufferedWriter.close();
否则无法写到文件中。
必须flush刷新一下!!!!
好了,android pull解析读取xml、写入xml,就这样吧~~~~