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

Android上經常使用xml來傳遞和交換數據。SAX(Simple API for XML)作為一種解析速度快並且占用內存少的xml解析器,非常適合Android等移動設備。SAX解析采用事件驅動,會判斷當前讀取到的字符是否符合xml語法中的某部分,從而觸發相應事件。xml中的節點分為2種類型,分別是Element Node(元素節點)和Text Node(文本節點)。對於元素節點,當讀取到開始標簽時會觸發startElement事件,當讀取到結束標簽時會觸發endElement事件。對於文本節點,當讀取到文本時會觸發characters事件。另外,xml文檔開始和結束時會分別觸發startDocument和endDocument事件。所謂事件其實就是一些回調方法,這些方法定義在ContentHandler接口中,用SAX解析一個xml文件主要也就是要根據xml文件的節點等信息編寫一個實現ContentHandler接口的實現類。
 
以下會用SAX解析這個test.xml文件,並用AndroidTextCase測試結果是否正確。
text.xml文件內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="23">
<name>liming</name>
<age>30</age>
</person>
<person id="20">
<name>lixiang</name>
<age>25</age>
</person>
</persons>
過程如下:
在Eclipse下新建一個Android項目xml01
新建text.xml文件,放在src目錄下面
新建一個JavaBean:Person,屬性有id、name、age
編寫一個業務類:SAXPersonService,解析test.xml文件,這裡重點是根據test.xml文件中的節點名稱等信息編寫SAXParserHandler這個內部類,代碼如下:
package com.study.service;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.study.bean.Person;
/**
 * 使用SAX解析text.xml文件
 * @author Administrator
 *
 */
public class SAXPersonService {
 public List<Person> getPersons(InputStream inputStream) throws Throwable{
  SAXParserFactory factory = SAXParserFactory.newInstance();
  SAXParser parser = factory.newSAXParser();
  SAXParserHandler handler = new SAXParserHandler();
  parser.parse(inputStream, handler);
  return handler.getPersons();
 }
 
 private final class SAXParserHandler extends DefaultHandler{
 
  private List<Person> persons;
  // 記錄正在訪問的文本節點的前一個節點名稱
  private String tag;
  private Person person;
 
  public List<Person> getPersons() {
   return persons;
  }
  @Override
  public void characters(char[] ch, int start, int length)
    throws SAXException {
   if(tag != null){
    if("name".equals(tag)){
     // 根據文本節點取值設置name
     person.setName(new String(ch, start, length));
    }else if("age".equals(tag)){
     // 根據文本節點取值設置age
     person.setAge(Integer.parseInt(new String(ch, start, length)));
    }
   }
  }
  @Override
  public void endElement(String uri, String localName, String qName)
    throws SAXException {
   // localName是不帶命名空間前綴的標簽名
   if("person".equals(localName)){
    // 將person對象加入到集合中
    persons.add(person);
    // person對象設置為null
    person = null;
   }
  
   // 節點結束時一定要將tag設置為null
   // 否則會將空白字符賦值給name和age,從而出錯
   tag = null;
  }
  @Override
  public void startDocument() throws SAXException {
   persons = new ArrayList<Person>();
  }
  @Override
  public void startElement(String uri, String localName, String qName,
    Attributes attributes) throws SAXException {
   // localName是不帶命名空間前綴的標簽名
   if("person".equals(localName)){
    person = new Person();
    // 通過索引查找屬性的值
    person.setId(Integer.parseInt(attributes.getValue(0)));
   }
  
   tag = localName;
  }
 
 }
}
 
在AndroidManifest.xml加入Android測試所需要的組件
<uses-library android:name="android.test.runner" />
以及
<instrumentation android:name="android.test.InstrumentationTestRunner"
  android:targetPackage="com.study.action" android:label="Tests for My App" />
編寫一個AndroidTestCase:SAXPersonServiceTest,測試代碼如下:
package com.study.action;
import java.io.InputStream;
import java.util.List;
import android.test.AndroidTestCase;
import android.util.Log;
import com.study.bean.Person;
import com.study.service.SAXPersonService;
public class SAXPersonServiceTest extends AndroidTestCase {
 private static final String TAG = "SAXPersonServiceTest";
 public void testGetPersons() throws Throwable{
  SAXPersonService personService = new SAXPersonService();
  InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("test.xml");
  List<Person> persons = personService.getPersons(inputStream);
  for(Person person : persons){
   Log.i(TAG, person.getId() + ", " + person.getName() + ", " + person.getAge());
  }
 }
}
輸入日志,運行結果如下:

作者“新的啟程”

發佈留言