Android SAX解析xml文件 – Android移動開發技術文章_手機開發 Android移動開發教學課程

andorid讀取xml文件內容方法有三種 sax dom pull,其中 pull是android自帶的
1.先認識一下xml文件中的些術語
Xml代碼 
<?xml version="1.0" encoding="UTF-8"?>    
<persons>    
    <person id="23">    
        <name>李明</name>    
        <age>23</age>    
    </person>    
    <person id="22">    
        <name>李量</name>    
        <age>25</age>    
    </person>    
</persons>   


xml中的標簽和內容都可以叫做節點,其中的persons  person  name age 這些都叫做元素(element).而像李明 25 這些值叫做文本節點.那麼有個問題 中<persons>到<person>之間的是什麼,什麼都沒有? 答案是他也是節點,是文本節點,你會說他裡面什麼都沒有啊,錯瞭,它有回車和空格.這個在sax解析xml中你debug一下就會發現.回車和空格(或者是tab)是會被讀取出來的.id是屬性.
2.sax
sax是采用事件驅動,就是說他不需要完全讀完xml文件,他是讀到一個節點就解析一個節點是否符合xml語法,如果符合就調用相對應的方法其實就是回調方法,並且沒有記憶功能.下面提到的這些方法都是在ContentHander()接口中的方法.
    startDocumnet() :當開始解析xml文件的聲明的時候就會觸發這個事件, 可以做一些初始化的工作
    startElement()   當開始解析元素的開始標簽的時候,就會觸發這個事件
    characters()     當讀到文本元素的時候要觸發這個事件.
    endElement()     當讀到結束標簽的時候 就會觸發這個事件

    sax就是這樣按照順序來解析的.
3.sax讀取xml文件舉例
3-1創建一個項目 ReadXml
3-2將xml文件拷貝到根目錄下.
Xml代碼 
<?xml version="1.0" encoding="UTF-8"?>    
<persons>    
    <person id="23">    
        <name>李明</name>    
        <age>23</age>    
    </person>    
    <person id="22">    
        <name>李量</name>    
        <age>25</age>    
    </person>    
</persons>  

可以看出這個xml文件中有一個可以抽象出來的對象 就是person 屬性有id name age
那麼我們就建立一個bean
3-3:創建bean
Java代碼 
package com.leequer.service.demo;    
/**  
 * <person id="23">  
        <name>李明</name>  
        <age>23</age>  
    </person>  
    <person id="22">  
        <name>李量</name>  
        <age>25</age>  
    </person>  
 * @author leequer  
 *   
 * xml文件對應的bean  
 */   
public class Person {    
        
    private Integer id;    
    private String name;    
    private int age;    
        
    public Person ()    
    {}    
    public Person (String name ,int age)    
    {    
        this.name = name;    
        this.age = age;    
    }    
    public Integer getId() {    
        return id;    
    }    
    public void setId(Integer id) {    
        this.id = id;    
    }    
    public String getName() {    
        return name;    
    }    
    public void setName(String name) {    
        this.name = name;    
    }    
    public int getAge() {    
        return age;    
    }    
    public void setAge(int age) {    
        this.age = age;    
    }    
    @Override   
    public String toString() {    
        // TODO Auto-generated method stub    
        return this.id+",name  "+this.name+"  age  "+this.age+"\n";    
    }    
        
}   


3-4:遵循mvc的架構,我們建立一個service用來讀取xml
Java代碼 
package com.leequer.service;    
   
import java.io.InputStream;    
import java.util.List;    
   
   
import javax.xml.parsers.SAXParser;    
import javax.xml.parsers.SAXParserFactory;    
   
import org.xml.sax.XMLReader;    
   
   
   
import com.leequer.service.demo.Person;    
   
public class SaxReadxml {    
    public static  List<Person> readXml(InputStream inStream)throws Exception {    
        SAXParserFactory spf = SAXParserFactory.newInstance(); // 初始化sax解析器    
        SAXParser sp = spf.newSAXParser(); // 創建sax解析器    
        //XMLReader xr = sp.getXMLReader();// 創建xml解析器    
        XMLContentHandler handler = new XMLContentHandler();    
        sp.parse(inStream, handler);    
        return handler.getPersons();    
    }    
}   


sp.parse(inStream, handler); 
這句可以看出xml文件是以流的形式傳進來的,參數handler就是回調函數的實例,當sax解析器解析xml文件的時候當遇到符合xml的內容就會去handle類中調用對應的上面提到的方法.那我們建立這個XMLContentHandler 就要求這個類要實現ContentHandler()這個接口,但是這個接口中有很多需要實現的方法.sax提供瞭一個DefaultHandler接口 隻要實現這個接口中你感興趣的方法就可以瞭.

3-5:創建XMLContentHandler 並完成讀取時的事件的實現 註意看註釋
Java代碼 
package com.leequer.service;    
   
import java.util.ArrayList;    
import java.util.List;    
   
import org.xml.sax.Attributes;    
import org.xml.sax.SAXException;    
import org.xml.sax.helpers.DefaultHandler;    
   
import com.leequer.service.demo.Person;    
   
public class XMLContentHandler extends DefaultHandler {    
    private List<Person> persons;    
        
    private Person person;    
    private String tempString;    
    private static final String NAMESTRING = "name";    
    private static final String AGESTRING = "age";    
    private static final String PERSONSTRING = "person";    
    private static final String IDSTRING = "id";    
   
    public List<Person> getPersons() {    
        return persons;    
    }    
        
    /**  
     * sax 解析文件不帶記憶,隻讀取 對xml文件中的 <person id="23"> <name>李明</name> <age>23</age>  
     * </person> <person id="22"> <name>李量</name> <age>25</age> </person> 這部分感興趣  
     * 那麼這部分包含瞭person這個節點元素的開始和結尾,那麼就要有startElement和endElement  
     * 這兩個方法;還有text的節點元素,(就是像節點之間的回車和空格還有標簽中的像李明這樣的文字都是文本節點 元素  
     * (text節點元素)那麼要解析文本節點元素就要用到characters 這個方法來獲取信息。)  
     */   
/**  
 * 要開始讀取xml文件的時候調用的方法  
 * 初始化persons  
 */   
    @Override   
    public void startDocument() throws SAXException {    
        //這裡做list的初始化工作    
        persons = new ArrayList<Person>();    
    }    
   
/**  
 * sax 讀取到文本節點的時候調用瞭這個方法  
 */   
    @Override   
    public void characters(char[] ch, int start, int length)    
            throws SAXException {    
            
        if (person != null) {    
            String valueString = new String(ch, start, length);    
            if (NAMESTRING.equals(tempString)) {    
                // 如果當前解析到的節點是name 就要將name中的文本節點元素的值得到    
                person.setName(valueString);    
            } else if (AGESTRING.equals(tempString)) {    
                person.setAge(new Integer(valueString).intValue());    
            }    
        }    
    }    
/**  
 * sax 讀取到元素節點的時候用到這個方法;  
 */   
    @Override   
    public void startElement(String uri, String localName, String name,    
            Attributes attributes) throws SAXException {    
        // 先判斷讀到的元素是否是person    
        if (PERSONSTRING.equals(localName)) {    
            // 如果讀到的是person這個元素 就要保存起來,保存在我們創建的那個person的類中 所以我們要new一個person類    
            person = new Person();    
            // attributes是屬性。    
            person.setId(new Integer(attributes.getValue(IDSTRING)));    
        }     
        tempString = localName;    
   
    }    
/**  
 * 這個方法是每次遇到結束的標簽都會執行的 並不是隻遇到最後的結尾才調用  
 *   
 * 讀取完畢遇到person'的結尾 就將封裝好的一個personbean保存到list中 並且清空person對象  
 *   
 */   
        
    @Override   
    public void endElement(String uri, String localName, String name)    
            throws SAXException {    
        if(PERSONSTRING.equals(localName)&&person!=null)    
        {    
            persons.add(person);    
            person = null;    
        }    
        tempString = null;    
            
    }    
        
        
        
   
}   


3-6:寫個測試類來實驗 將xml文件裝載入 然後讀取
package com.leequer.readxml;  
/** 
* 測試類 
*/ 
import java.io.InputStream;  
import java.util.Iterator;  
import java.util.List;  
 
import com.leequer.service.SaxReadxml;  
import com.leequer.service.demo.Person;  
 
import android.test.AndroidTestCase;  
import android.util.Log;  
 
public class SaxReadxmlTest extends AndroidTestCase {  
    private String PERSONSTRING = "ObjectPerson";  
    public void testReadXml() throws Exception  
    {//類裝載器  
        InputStream inputStream = SaxReadxmlTest.class.getClassLoader().getResourceAsStream("NewFile.xml");  
          
        List <Person> personsList = SaxReadxml.readXml(inputStream);  
          
        for (Iterator iterator = personsList.iterator(); iterator.hasNext();) {  
            Person person = (Person) iterator.next();  
            Log.i(PERSONSTRING, person.toString());  
        }  
          
    }  

發佈留言