本文參考學習了:
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,就這樣吧~~~~