Android 解析XML文件

在現代技術中不論使用何種語言﹐解析XML文件資料已是很常見的方法﹐XML比起過去的INI格式更有彈性更能描述豐富的資料﹐且做為一種共同性的文件格式更能讓大家有同樣的規範遵詢﹐不會因為獨樹一格的格式使得使用技巧變得多樣而複雜。

在 Android 中解析XML的方式有三種DOM﹑SAX及PULL﹐這些使用的差異性在網路上已有多篇文章介紹﹐範例也有許多。然而凡事總要自己親自嘗試過才能知其中的奧妙。因此自己自訂了一個XML格式分別使用DOM及SAX方式來讀取做相同的事﹐親自感受當中有何不同。

 

XML檔(Books.xml)

01<?xml version="1.0" encoding="UTF-8"?>
02<books>
03    <book id="P631" name="Android 2.X 應用程式開發實戰" publishers="碁峯" price="580">
04        <auther name="林城"/>
05    </book>
06    <book id="P697" name="深入淺出 Android 遊戲程式開發範例大全" publishers="博碩文化" price="620">
07        <auther name="吳亞峰"/>
08        <auther name="蘇亞光"/>
09    </book
10    <book id="XP6037" name="Silverlight 4 商業級應用程式開發" publishers="悅知文化" price="590">
11        <auther name="Frank LaVigne. Cameron Albert"/>
12    </book>
13</books>

將Books.xml 這個檔案放在 src 之下﹐如下圖所示

xml_point

 

主畫面 Layout(main.xml)

01<?xml version="1.0" encoding="utf-8"?>
02<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
03    android:orientation="vertical"
04    android:layout_width="fill_parent"
05    android:layout_height="fill_parent"
06    >
07    <TextView  
08        android:layout_width="fill_parent" 
09        android:layout_height="wrap_content" 
10        android:text="讀取XML資料"/>
11    <Button android:layout_width="wrap_content" 
12        android:layout_height="wrap_content" 
13        android:text="使用SAX" 
14        android:id="@+id/saxbtn"/>
15    <Button android:layout_width="wrap_content" 
16        android:layout_height="wrap_content" 
17        android:text="使用DOM剖析" 
18        android:id="@+id/dombtn"/>
19</LinearLayout>

主畫面很簡單就只有兩個Button﹐分別表示將使用SAX方式與DOM方式來解析XML資料檔。

mail_layout2

接下來將分別使用SAX與DOM的方式讀取Books.xml然後以ListView元件呈現資料﹐而這裏要做的是用不同的技術分別呈現﹐使用的Layout都一樣﹐這裏會建立一個主要呈現的Layout檔booklist.xml

booklist.xml

01<?xml version="1.0" encoding="utf-8"?>
02<LinearLayout
04  android:layout_width="match_parent"
05  android:layout_height="match_parent" android:orientation="vertical">
06    <TextView android:id="@+id/list_title" 
07        android:layout_width="wrap_content" 
08        android:layout_height="wrap_content" 
09        android:text="書籍列表" 
10        android:layout_gravity="center"/>
11    <ListView android:id="@+id/bookListView" 
12        android:layout_width="fill_parent" 
13        android:layout_height="fill_parent"/>
14</LinearLayout>

這個layout很簡單﹐只有一個TextView當Title﹐還有一個ListView﹐這個ListView就是要用來顯示解析Books.xml的資料。為了這個ListView﹐需要再建一個layout檔book_data.xml﹐這個book_data.xml用來表示在ListView中的每一筆資料呈現方式。

book_data.xml

01<?xml version="1.0" encoding="utf-8"?>
02<LinearLayout
04  android:layout_height="match_parent" 
05  android:orientation="vertical" 
06  android:layout_width="fill_parent">
07    <LinearLayout android:id="@+id/linearLayout1" 
08        android:orientation="horizontal" 
09        android:layout_height="wrap_content" 
10        android:layout_width="fill_parent">
11        <TextView android:text="TextView" 
12            android:layout_width="wrap_content" 
13            android:layout_height="wrap_content" 
14            android:id="@+id/bookNameTxt" 
15            android:textColor="@color/yellow"/>
16    </LinearLayout>
17    <LinearLayout android:id="@+id/linearLayout2" 
18        android:orientation="horizontal" 
19        android:layout_height="wrap_content" 
20        android:layout_width="fill_parent">
21        <TextView android:text="TextView" 
22            android:textColor="@color/white" 
23            android:gravity="left" 
24            android:id="@+id/publishersTxt" 
25            android:layout_width="wrap_content" 
26            android:layout_height="wrap_content"></TextView>
27        <TextView android:text="TextView" 
28            android:textColor="@color/green" 
29            android:gravity="right" 
30            android:id="@+id/priceTxt" 
31            android:layout_height="wrap_content" 
32            android:layout_width="match_parent"></TextView>
33    </LinearLayout>
34</LinearLayout>

Layout還是以圖形來看比較容易看得懂﹐在book_data.xml的排版中每一筆資料的呈現方式第一列為書名(黃色的TextView)﹐第二列則有出版社(白色的TextView)及價錢(綠色的TextView)。

book_data_layout

 

根據 Books.xml的資料我們知道至少有id(書籍編號)﹑name(書名)﹑publishers(出版社)﹑price(價錢)...這些屬性值﹐而從我們想要顯示的資料來看至少也要有name(書名)﹑publishers(出版社)﹑price(價錢)這三個欄位﹐我們可以定義一個class檔(Book.java)來表示一本書籍的基本資料。

Book.java

package com.sample.AndroidUseXML;
  
public class Book {
    public String id;
    public String name;
    public String publishers;
    public String price;
      
    public Book(){}
      
    public Book(String id, String name, String publishers, String price){
        this.id=id;
        this.name=name;
        this.publishers=publishers;
        this.price=price;
    }
  
    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 getPublishers() {
        return publishers;
    }
  
    public void setPublishers(String publishers) {
        this.publishers = publishers;
    }
  
    public String getPrice() {
        return price;
    }
  
    public void setPrice(String price) {
        this.price = price;
    }
      
}

在這個專案一開始create的Activity是UseXML﹐這裏就是單純的去觸發兩個button的動作而已。

UseXML.java

01package com.sample.AndroidUseXML;
02  
03import android.app.Activity;
04import android.content.Intent;
05import android.os.Bundle;
06import android.view.View;
07import android.widget.Button;
08  
09public class UseXML extends Activity {
10    Button saxbtn;
11    Button dombtn;
12    String list_title;
13      
14    @Override
15    public void onCreate(Bundle savedInstanceState) {
16        super.onCreate(savedInstanceState);
17        setContentView(R.layout.main);
18          
19        findView();
20        setListener();
21    }
22      
23    private void findView(){
24        saxbtn=(Button)findViewById(R.id.saxbtn);
25        dombtn=(Button)findViewById(R.id.dombtn);
26    }
27      
28    private void setListener(){
29        saxbtn.setOnClickListener(saxbtnls);
30        dombtn.setOnClickListener(dombtnls);
31    }
32      
33    private Button.OnClickListener saxbtnls=new Button.OnClickListener(){
34        @Override
35        public void onClick(View arg0) {
36            Intent intent=new Intent();
37            intent.setClass(UseXML.this, UseSaxParse.class);
38              
39            //傳遞資料給Activity-------------
40            Bundle bundle = new Bundle();
41            list_title="使用SAX解析";
42            bundle.putString("list_title", list_title);
43            intent.putExtras(bundle);
44              
45            startActivity(intent);
46        }
47    };
48      
49    private Button.OnClickListener dombtnls=new Button.OnClickListener(){
50        @Override
51        public void onClick(View v) {
52            Intent intent=new Intent();
53            intent.setClass(UseXML.this, UseDomParse.class);
54              
55            //傳遞資料給Activity-------------
56            Bundle bundle = new Bundle();
57            list_title="使用DOM解析";
58            bundle.putString("list_title", list_title);
59            intent.putExtras(bundle);
60              
61            startActivity(intent);
62        }
63    };
64      
65  
66}

DOM篇

由UseXML中第53行﹐我們知道要使用DOM的方式我們呼叫了UseDomParse的Activity

UseDomParse.java

01package com.sample.AndroidUseXML;
02  
03import java.io.InputStream;
04import java.util.ArrayList;
05import java.util.List;
06  
07import android.app.Activity;
08import android.os.Bundle;
09import android.util.Log;
10import android.widget.ListView;
11import android.widget.TextView;
12  
13public class UseDomParse extends Activity {
14    String TAG="UseDomParse";
15    TextView list_title;
16    ListView bookList;
17      
18    @Override
19    protected void onCreate(Bundle savedInstanceState) {
20        super.onCreate(savedInstanceState);
21        setContentView(R.layout.booklist);
22          
23        findView();
24        ShowXMLData();      
25    }
26      
27    private void findView(){
28        list_title=(TextView)findViewById(R.id.list_title);
29        bookList=(ListView)findViewById(R.id.bookListView);
30    }
31      
32    private void ShowXMLData(){
33        Bundle bundle=this.getIntent().getExtras();
34        list_title.setText("書籍列表("+bundle.getString("list_title")+")");
35          
36        List<Book> books=new ArrayList<Book>();
37        books=getXMLData();
38          
39        bookList.setAdapter(new BookAdapter(this,books));
40    }
41  
42    private List<Book> getXMLData() {
43        List<Book> books = new ArrayList<Book>();
44        try {
45            InputStream inStream = UseDomParse.class.getClassLoader()
46                    .getResourceAsStream("Books.xml");  //讀取檔案
47  
48//          InputStream inStream = UseDomParse.class.getClassLoader()
49//          .getResourceAsStream("com/sample/AndroidUseXML/Books2.xml");  //讀取檔案
50              
51            books = DomParseXML.ReadBookXML(inStream);
52        } catch (Exception er) {
53            Log.e(TAG, er.getMessage());
54        }
55        return books;
56    }
57}

第21行指明了要用booklist.xml的layout。

第32行的ShowXMLData()是用來顯示資料。

第37行的books=getXMLData();是用來取得以DOM解析資料後得到的List物件。

第39行的bookList這一個ListView將使用自定的DataAdapter做為資料來源。

第45行的位置是讀取檔案﹐因為檔案是直接放在src之下。如果檔案是放在com.sample.AndroidUseXML之下﹐那麼就必須加上路徑﹐如48行。

在第48行books = DomParseXML.ReadBookXML(inStream); 這裏是我們主要用DOM去解析方法。

 

DomParseXML.java

01package com.sample.AndroidUseXML;
02  
03import java.io.InputStream;
04import java.util.ArrayList;
05import java.util.List;
06  
07import javax.xml.parsers.DocumentBuilder;
08import javax.xml.parsers.DocumentBuilderFactory;
09  
10import org.w3c.dom.Document;
11import org.w3c.dom.Element;
12import org.w3c.dom.NodeList;
13  
14/**
15 * 使用Dom讀取Books.xml的資料
16 * @author Kevin Chen
17 *InputStream可以是網路也可以是文件
18 */
19public class DomParseXML {
20    public static List<Book> ReadBookXML(InputStream inStream) throws Exception{
21        List<Book> books=new ArrayList<Book>();
22        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
23        DocumentBuilder builder=factory.newDocumentBuilder();
24        Document document=builder.parse(inStream);  //以樹狀格式存於記憶體中﹐比較耗記憶體
25        Element root=document.getDocumentElement();
26        NodeList nodes=root.getElementsByTagName("book");
27          
28        for(int i=0;i<nodes.getLength();i++){
29            Element bookElement=(Element)nodes.item(i);
30            Book book=new Book();
31            book.setId(bookElement.getAttribute("id"));
32            book.setName(bookElement.getAttribute("name"));
33            book.setPublishers(bookElement.getAttribute("publishers"));
34            book.setPrice(bookElement.getAttribute("price"));
35              
36            books.add(book);
37        }
38          
39        return books;
40    }
41}

 

BookAdapter.java

01package com.sample.AndroidUseXML;
02  
03import java.util.List;
04  
05import android.content.Context;
06import android.view.LayoutInflater;
07import android.view.View;
08import android.view.ViewGroup;
09import android.widget.BaseAdapter;
10import android.widget.TextView;
11  
12public class BookAdapter extends BaseAdapter {
13    private LayoutInflater inflater;
14    List<Book> books=null;
15      
16    public BookAdapter(Context context,List<Book> books){
17        inflater=LayoutInflater.from(context);
18        this.books=books;
19    }
20  
21    @Override
22    public int getCount() {
23        return books.size();
24    }
25  
26    @Override
27    public Object getItem(int arg0) {
28        return arg0;
29    }
30  
31    @Override
32    public long getItemId(int arg0) {
33        return arg0;
34    }
35  
36    @Override
37    public View getView(int arg0, View arg1, ViewGroup arg2) {
38        ViewHolder viewHolder;
39        if(arg1==null){
40            arg1=inflater.inflate(R.layout.book_data, null);
41            viewHolder=new ViewHolder();
42            viewHolder.bookNameTxt=(TextView)arg1.findViewById(R.id.bookNameTxt);
43            viewHolder.publishersTxt=(TextView)arg1.findViewById(R.id.publishersTxt);
44            viewHolder.priceTxt=(TextView)arg1.findViewById(R.id.priceTxt);
45            arg1.setTag(viewHolder);
46        }else{
47            viewHolder=(ViewHolder)arg1.getTag();
48        }
49//      String name1="";
50//      String publ1="";
51//      String price1="";
52//      name1=books.get(arg0).name;
53//      publ1=books.get(arg0).publishers;
54//      price1=books.get(arg0).price;
55          
56        viewHolder.bookNameTxt.setText(books.get(arg0).name);
57        viewHolder.publishersTxt.setText(books.get(arg0).publishers);
58        viewHolder.priceTxt.setText("NT."+books.get(arg0).price+" 元");
59          
60        return arg1;
61    }
62      
63    private class ViewHolder{
64        TextView bookNameTxt;
65        TextView publishersTxt;
66        TextView priceTxt;
67    }
68  
69}

 

SAX篇

以DOM的方式﹐可以看得出寫的程式並不多﹐如果改以SAX就不大一樣了。

由UseXML中第37行﹐我們知道要使用SAX的方式我們呼叫了UseSaxParse的Activity。

UseSaxParse.java

01package com.sample.AndroidUseXML;
02  
03import java.io.InputStream;
04import java.util.ArrayList;
05import java.util.List;
06  
07import android.app.Activity;
08import android.os.Bundle;
09import android.util.Log;
10import android.widget.ListView;
11import android.widget.TextView;
12  
13public class UseSaxParse extends Activity {
14    String TAG="UseSAX";
15    TextView list_title;
16    ListView bookList;
17      
18    @Override
19    protected void onCreate(Bundle savedInstanceState) {
20        super.onCreate(savedInstanceState);
21        setContentView(R.layout.booklist);
22          
23        findView();
24        ShowXMLData();
25    }
26  
27    private void findView(){
28        list_title=(TextView)findViewById(R.id.list_title);
29        bookList=(ListView)findViewById(R.id.bookListView);
30    }
31      
32    private void ShowXMLData(){
33        Bundle bundle=this.getIntent().getExtras();
34        list_title.setText("書籍列表("+bundle.getString("list_title")+")");
35          
36        List<Book> books=new ArrayList<Book>();
37        books=getXMLData();
38          
39        bookList.setAdapter(new BookAdapter(this,books));
40    }
41      
42    private List<Book> getXMLData(){
43        List<Book> books=new ArrayList<Book>();
44        try{
45            InputStream inStream=UseSaxParse.class.getClassLoader().getResourceAsStream("Books.xml");
46            books = SAXParseXML.readXML(inStream);
47        }catch(Exception er){
48            Log.e(TAG, er.getMessage());
49        }
50          
51        return books;
52    }
53}

第46行的SAXParseXML

SAXParseXML.java

01package com.sample.AndroidUseXML;
02  
03import java.io.InputStream;
04import java.util.List;
05  
06import javax.xml.parsers.SAXParser;
07import javax.xml.parsers.SAXParserFactory;
08  
09public class SAXParseXML {
10    public static List<Book> readXML(InputStream inStream) throws Exception{
11        SAXParserFactory factory=SAXParserFactory.newInstance();
12        SAXParser saxParse=factory.newSAXParser();  //建立解析器
13          
14        SAXContentHandler handler=new SAXContentHandler();
15        saxParse.parse(inStream, handler);
16        inStream.close();
17          
18        return handler.getBooks();
19    }
20}

第14行的SAXContentHandler是關鍵﹐必須建立一個class繼承自DefaultHandler﹐並且在這當中去實作以下以個方法

startDocument()

characters(char[] ch, int start, int length)

startElement(String uri, String localName, String qName, Attributes attributes)

public void endElement(String uri, String localName, String qName)

 

SAXContentHandler.java

01package com.sample.AndroidUseXML;
02  
03import java.util.ArrayList;
04import java.util.List;
05  
06import org.xml.sax.Attributes;
07import org.xml.sax.SAXException;
08import org.xml.sax.helpers.DefaultHandler;
09  
10public class SAXContentHandler extends DefaultHandler {
11    private List<Book> books;
12    private Book book;
13    private String preTag;
14      
15    public List<Book> getBooks(){
16        return books;
17    }
18  
19    /**
20     * 接收文件的開始
21     */
22    @Override
23    public void startDocument() throws SAXException {
24        books = new ArrayList<Book>();
25    }
26  
27    /**
28     * 接收字元資料的通知
29     */
30    @Override
31    public void characters(char[] ch, int start, int length)
32            throws SAXException {
33  
34    }
35  
36    /**
37     * 接收元素開始的通知
38     */
39    @Override
40    public void startElement(String uri, String localName, String qName,
41            Attributes attributes) throws SAXException {
42        if("book".equals(localName)){
43            book=new Book();
44            book.setId(attributes.getValue("","id"));
45            book.setName(attributes.getValue("", "name"));
46            book.setPublishers(attributes.getValue("publishers"));
47            book.setPrice(attributes.getValue("price"));
48        }
49        preTag=localName;
50    }
51  
52    /**
53     * 接收元素結尾的通知
54     */
55    @Override
56    public void endElement(String uri, String localName, String qName)
57            throws SAXException {
58        if("book".equals(localName) && book!=null){
59            books.add(book);
60            book=null;
61        }
62        preTag=null;
63    }
64      
65      
66}

實際的執行結果

result



相关文档:

http://blog.csdn.net/haha_mingg/article/details/6329694

http://www.cnblogs.com/zhangdongzi/archive/2011/04/14/2016434.html

http://www.cnblogs.com/khldragon/archive/2011/11/08/1968283.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值