android應用開發之利用SAX、DOM和Pull實現對XML文件的解析並進行單元測試 – Android移動開發技術文章_手機開發 Android移動開發教學課程

首先我們有如下的xml文件,我要對其進行解析
school.xml

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/css" href="school.css"?> 
<!DOCTYPE schools SYSTEM "schools.dtd"> 
<schools> 
 
<school level="middle-school"> 
    <teacher> 
        <teacherName>Tom</teacherName> 
        <teacherAge>34</teacherAge> 
    </teacher> 
    <student> 
        <studentName>Jack</studentName> 
        <studentAge>20</studentAge> 
    </student> 
    <student> 
        <studentName>Mary</studentName> 
        <studentAge>20</studentAge> 
    </student> 
    <student> 
        <studentName>John</studentName> 
        <studentAge>20</studentAge> 
    </student> 
</school> 
 
<school level="primary-school"> 
    <teacher> 
        <teacherName>Tom</teacherName> 
        <teacherAge>34</teacherAge> 
    </teacher> 
    <student> 
        <studentName>Jack</studentName> 
        <studentAge>20</studentAge> 
    </student> 
    <student> 
        <studentName>Mary</studentName> 
        <studentAge>20</studentAge> 
    </student> 
    <student> 
        <studentName>Jhon</studentName> 
        <studentAge>20</studentAge> 
    </student> 
 
</school> 
 
</schools> 

我們現在要對其進行解析,首先要分析他的元素組成部分
大傢可以看到在根節點school中,含有如下的屬性
1.level 2.子節點techer3.子節點student
創建javabean文件 www.aiwalls.com
現在我們創建school.java 的bean文件

package song.domain; 
 
import java.util.List; 
 
public class School { 
    private String level; 
    private Teacher teacher; 
    private List<Student> student; 
    public School() { 
        super(); 
        // TODO Auto-generated constructor stub 
    } 
    public School(String level, Teacher teacher, List<Student> student) { 
        super(); 
        this.level = level; 
        this.teacher = teacher; 
        this.student = student; 
    } 
    public String getLevel() { 
        return level; 
    } 
    public void setLevel(String level) { 
        this.level = level; 
    } 
    public Teacher getTeacher() { 
        return teacher; 
    } 
    public void setTeacher(Teacher teacher) { 
        this.teacher = teacher; 
    } 
    public List<Student> getStudent() { 
        return student; 
    } 
    public void setStudent(List<Student> student) { 
        this.student = student; 
    } 
    @Override 
    public String toString() { 
        return "Schoool [level=" + level + ", teacher=" + teacher 
                + ", student=" + student + "]"; 
    } 
     

我們又可以註意到,子節點techer的屬性
1.teacherName2.techerAge
現在我們創建techer.java 的bean文件

package song.domain; 
 
public class Teacher { 
    private String teacherName; 
    private Integer teacherAge; 
    public Teacher() { 
        super(); 
        // TODO Auto-generated constructor stub 
    } 
    public Teacher(String teacherName, Integer teacherAge) { 
        super(); 
        this.teacherName = teacherName; 
        this.teacherAge = teacherAge; 
    } 
    public String getTeacherName() { 
        return teacherName; 
    } 
    public void setTeacherName(String teacherName) { 
        this.teacherName = teacherName; 
    } 
    public Integer getTeacherAge() { 
        return teacherAge; 
    } 
    public void setTeacherAge(Integer teacherAge) { 
        this.teacherAge = teacherAge; 
    } 
    @Override 
    public String toString() { 
        return "Teacher [teacherName=" + teacherName + ", teacherAge=" 
                + teacherAge + "]"; 
    } 
     

子節點student的屬性
1.studentName2.studentAge
現在我們創建student的javabean文件

package song.domain; 
 
public class Student { 
    private String studentName; 
    private Integer studentAge; 
 
    public Student() { 
        super(); 
        // TODO Auto-generated constructor stub 
    } 
 
    public Student(String studentName, Integer studentAge) { 
        super(); 
        this.studentName = studentName; 
        this.studentAge = studentAge; 
    } 
 
    public String getStudentName() { 
        return studentName; 
    } 
 
    public void setStudentName(String studentName) { 
        this.studentName = studentName; 
    } 
 
    public Integer getStudentAge() { 
        return studentAge; 
    } 
 
    public void setStudentAge(Integer studentAge) { 
        this.studentAge = studentAge; 
    } 
 
    @Override 
    public String toString() { 
        return "Student [studentName=" + studentName + ", studentAge=" 
                + studentAge + "]"; 
    } 
 
     

好瞭,我們的Javabean文件到這裡就完成瞭。www.aiwalls.com
現在我們要分別使用三種解析方式,對schools.xml文件進行解析
1.使用SAX解析
要使用SAX對文件進行解析,所需步驟
1)創建Handler類,使之繼承DefaultHandler
2)讓工廠對象創建解析器對象,利用public void parse (InputStream is, DefaultHandler dh)進行解析
SchoolHandler.java

package song.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 song.domain.School; 
import song.domain.Student; 
import song.domain.Teacher; 
import android.util.Log; 
//創建Handler,使之遍歷xml文件 
public class SchoolHandler extends DefaultHandler { 
 
    List<School> schoolList = null; 
    List<Teacher> teacherList = null; 
    List<Student> studentList = null; 
    School school = null; 
    Teacher teacher = null; 
    Student student = null; 
    String elementTag = null; 
 
    public void characters(char[] ch, int start, int length) 
            throws SAXException { 
        String data = new String(ch, start, length); 
        //對teacher進行解析 
        if (elementTag != null && teacher != null) { 
            if ("teacherName".equals(elementTag)) { 
                teacher.setTeacherName(data); 
                Log.i("TAG", teacher.toString()); 
            } else if ("teacherAge".equals(elementTag)) { 
                teacher.setTeacherAge(Integer.valueOf(data)); 
                Log.i("TAG", teacher.toString()); 
            } 
        } 
        //對student進行解析 
        if (elementTag != null && student != null) { 
            if ("studentName".equals(elementTag)) { 
                student.setStudentName(data); 
            } else if ("studentAge".equals(elementTag)) {        
                student.setStudentAge(Integer.parseInt(data)); 
                Log.i("TAG",data); 
            } 
        } 
    } 
 
    public void endDocument() throws SAXException { 
    } 
 
    public void endElement(String uri, String localName, String qName) 
            throws SAXException { 
        if ("teacher".equals(localName)) { 
            Log.i("TAG", teacher.toString()); 
            teacherList.add(teacher); 
            school.setTeacher(teacher); 
            teacher = null; 
        } else if ("student".equals(localName)) { 
            studentList.add(student); 
            school.setStudent(studentList); 
            student = null; 
        } else if ("school".equals(localName)) { 
            school.setStudent(studentList); 
            schoolList.add(school); 
            studentList = null; 
            school = null; 
        } 
        elementTag = null; 
    } 
 
    public void startDocument() throws SAXException { 
        schoolList = new ArrayList<School>(); 
        teacherList = new ArrayList<Teacher>(); 
        studentList = new ArrayList<Student>(); 
    } 
 
    public void startElement(String uri, String localName, String qName, 
            Attributes attributes) throws SAXException { 
        if ("school".equals(localName)) { 
            school = new School(); 
            school.setLevel(attributes.getValue(0)); 
            studentList = new ArrayList<Student>(); 
            Log.i("TAG", attributes.getValue(0)); 
        } else if ("teacher".equals(localName)) { 
            teacher = new Teacher(); 
            Log.i("TAG", teacher.toString()); 
            if (teacher != null) { 
                Log.i("TAG", teacher.toString()); 
            } 
        } else if ("student".equals(localName)) { 
            student = new Student(); 
        } 
        elementTag = localName; 
    } 
 
    public List<School> setSchoollist() { 
        return schoolList; 
    } 

SAXSchoolService.java

package song.service; 
 
import java.io.InputStream; 
import java.util.List; 
 
import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 
 
import song.domain.School; 
 
/**
 * 利用SAX解析schools.xml文件*/ 
public class SAXSchoolService { 
    public List<School> getSchoolList(InputStream is) throws Exception{ 
        //得到創建SAX解析器的工廠對象 
        SAXParserFactory factory = SAXParserFactory.newInstance(); 
        //讓工廠對象創建解析器對象 
        SAXParser parser = factory.newSAXParser(); 
         
        //創建DefaultHandler對象 
        SchoolHandler handler = new SchoolHandler(); 
        //使用parser的parser(InputStream is,ContentHandler handler)進行解析 
        parser.parse(is, handler); 
         
        List<School> schoollist = handler.setSchoollist(); 
        return schoollist; 
    } 

2.使用Dom進行解析
DomSchoolService.java直接解析,此法較為簡便

package song.service; 
 
import java.io.InputStream; 
import java.util.ArrayList; 
import java.util.List; 
 
import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
 
import org.w3c.dom.Document; 
import org.w3c.dom.Element; 
import org.w3c.dom.Node; 
import org.w3c.dom.NodeList; 
 
import song.domain.School; 
import song.domain.Student; 
import song.domain.Teacher; 
 
public class DomSchoolService { 
    public static List<School> getSchoolList(InputStream in) throws Exception{ 
        List<School> schoolList=new ArrayList<School>(); 
         
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); 
        DocumentBuilder builder=factory.newDocumentBuilder(); 
        Document document=builder.parse(in); 
         
        //取得根結點 
        Element root=document.getDocumentElement(); 
        NodeList nodes=root.getElementsByTagName("school"); 
        for(int i=0;i<nodes.getLength();i++){ 
            Element schoolElement=(Element) nodes.item(i); 
            School school=new School(); 
            Teacher teacher=new Teacher(); 
            Student student=new Student(); 
            List<Student> studentList=new ArrayList<Student>(); 
            //為school添加level屬性 
            school.setLevel(schoolElement.getAttribute("level")); 
            NodeList chileNodes = schoolElement.getChildNodes(); 
            // 遍歷孩子節點,忽略文本節點,保留並處理元素節點 
            for (int j = 0; j < chileNodes.getLength(); j++) { 
                Node childNode = chileNodes.item(j);                 
                if("teacher".equals(childNode.getNodeName())){ 
                    NodeList teacherNodes=childNode.getChildNodes(); 
                    for(int t=0;t<teacherNodes.getLength();t++){ 
                        Node teacherNode=teacherNodes.item(t); 
                        if (teacherNode.getNodeType() == Node.ELEMENT_NODE) { 
                            if("teacherName".equals(teacherNode.getNodeName())){ 
                                teacher.setTeacherName(teacherNode.getFirstChild().getNodeValue()); 
                            }else if("teacherAge".equals(teacherNode.getNodeName())){ 
                                String age=teacherNode.getFirstChild().getNodeValue(); 
                                teacher.setTeacherAge(Integer.parseInt(age)); 
                            } 
                        } 
                        school.setTeacher(teacher); 
                    } 
                     
                }else if("student".equals(childNode.getNodeName())){ 
                    NodeList studentNodes=childNode.getChildNodes(); 
                    student=new Student(); 
                    for(int s=0;s<studentNodes.getLength();s++){ 
                        //System.out.println(s); 
                        Node studentNode=studentNodes.item(s); 
                        if(studentNode.getNodeType()==Node.ELEMENT_NODE){ 
                            if("studentName".equals(studentNode.getNodeName())){ 
                                student.setStudentName(studentNode.getFirstChild().getNodeValue());                              
                            }else if("studentAge".equals(studentNode.getNodeName())){ 
                                String age=studentNode.getFirstChild().getNodeValue(); 
                                student.setStudentAge(Integer.parseInt(age));    
                                //Log.i("TAG",student.toString()); 
                                studentList.add(student); 
                                student=null; 
                            } 
                        } 
                    }                    
                } 
                 
            } 
            school.setStudent(studentList); 
            studentList=null; 
            schoolList.add(school); 
        } 
        return schoolList;       
    } 

3.使用pull解析xml文件,並且寫入xml文件

package song.service; 
 
import java.io.InputStream; 
import java.io.Writer; 
import java.util.ArrayList; 
import java.util.List; 
 
import org.xmlpull.v1.XmlPullParser; 
import org.xmlpull.v1.XmlSerializer; 
 
import song.domain.School; 
import song.domain.Student; 
import song.domain.Teacher; 
import android.util.Xml; 
 
public class PullSchoolService { 
    public static List<School> getSchoolList(InputStream in) throws Exception{ 
        List<School> schoolList=null; 
        XmlPullParser parser=Xml.newPullParser(); 
        parser.setInput(in,"utf-8"); 
        School school=null; 
        Teacher teacher=null; 
        Student student=null; 
        List<Student> studentList=null; 
        int eventType=parser.getEventType(); 
        while(eventType!=XmlPullParser.END_DOCUMENT){ 
            switch(eventType){ 
            case XmlPullParser.START_DOCUMENT: 
                schoolList=new ArrayList<School>(); 
                break; 
            case XmlPullParser.START_TAG: 
                if("school".equals(parser.getName())){ 
                    school=new School(); 
                    school.setLevel(parser.getAttributeValue(0)); 
                    studentList=new ArrayList<Student>(); 
                }else if("teacherName".equals(parser.getName())){ 
                    teacher=new Teacher(); 
                    teacher.setTeacherName(parser.nextText()); 
                }else if("teacherAge".equals(parser.getName())){ 
                    teacher.setTeacherAge(Integer.parseInt(parser.nextText())); 
                }else if("studentName".equals(parser.getName())){ 
                    student=new Student(); 
                    student.setStudentName(parser.nextText()); 
                }else if("studentAge".equals(parser.getName())){ 
                    student.setStudentAge(Integer.parseInt(parser.nextText())); 
                } 
                break; 
            case XmlPullParser.END_TAG: 
                if("teacher".equals(parser.getName())&&teacher!=null){ 
                    school.setTeacher(teacher); 
                    teacher=null; 
                }else if("student".equals(parser.getName())&&student!=null){ 
                    studentList.add(student); 
                    student=null; 
                }else if("school".equals(parser.getName())&&school!=null){ 
                    school.setStudent(studentList); 
                    schoolList.add(school); 
                    school=null; 
                    studentList=null; 
                } 
                break; 
            } 
            // next方法的導致進行下一個節點的解析,同時返回下一個節點解析的事件類型代碼、 
            eventType = parser.next(); 
        } 
        return schoolList; 
    } 
    public static void writerPersonList(List<School> schoolList,Writer writer) throws Exception{ 
        XmlSerializer serializer=Xml.newSerializer(); 
        serializer.setOutput(writer); 
        //定入 
        serializer.startDocument("utf-8", true); 
        //寫入根標簽的起始 
        serializer.startTag(null, "schools"); 
         
        for(School school:schoolList){ 
            serializer.startTag(null, "school"); 
            //添加id屬性 
            serializer.attribute(null, "level", school.getLevel()); 
            serializer.startTag(null, "teacher"); 
            //老師姓名 
            serializer.startTag(null, "teacherName"); 
            serializer.text(school.getTeacher().getTeacherName());           
            serializer.endTag(null, "teacherName"); 
            //老師年齡 
            serializer.startTag(null, "teacherAge"); 
            serializer.text(school.getTeacher().getTeacherAge()+""); 
            serializer.endTag(null, "teacherAge");   
            serializer.endTag(null, "teacher"); 
             
            for(Student list:school.getStudent()){ 
                serializer.startTag(null, "student"); 
                //學生姓名 
                serializer.startTag(null, "studentName"); 
                serializer.text(list.getStudentName());          
                serializer.endTag(null, "studentName"); 
                //學生年齡 
                serializer.startTag(null, "studentAge"); 
                serializer.text(list.getStudentAge()+""); 
                serializer.endTag(null, "studentAge");   
                serializer.endTag(null, "student"); 
            } 
            serializer.endTag(null, "school"); 
        }        
        //結束標簽 
        serializer.endTag(null, "schools"); 
        //結束文檔的寫入 
        serializer.endDocument(); 
         
        writer.flush(); 
        writer.close(); 
    } 

3種解析方法都已完成,下面我們來寫單元測試
在song.activity中新建一個test類

package song.activity; 
 
import java.io.File; 
import java.io.FileWriter; 
import java.io.InputStream; 
import java.io.Writer; 
import java.util.ArrayList; 
import java.util.List; 
 
import song.domain.School; 
import song.domain.Student; 
import song.domain.Teacher; 
import song.service.DomSchoolService; 
import song.service.PullSchoolService; 
import song.service.SAXSchoolService; 
import android.test.AndroidTestCase; 
import android.util.Log; 
 
public class Test extends AndroidTestCase{ 
    public void testSAX() throws Exception { 
        List<School> schoolList = null; 
        SAXSchoolService service = new SAXSchoolService(); 
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("schools.xml"); 
        schoolList = service.getSchoolList(is); 
        for(int i = 0;i<schoolList.size();i++){ 
            Log.i("TAG", schoolList.get(i).toString()); 
        } 
        Log.i("TAG", schoolList.toString()); 
    } 
    public void testDOM() throws Exception{   
        List<School> schoolList=null;   
        InputStream in=this.getClass().getClassLoader().getResourceAsStream("schools.xml");   
        schoolList=DomSchoolService.getSchoolList(in);   
        for(School list:schoolList){   
            Log.i("TAG",list.toString());   
            Log.i("TAG",list.getStudent().toString());   
               
        }   
    }   
       
    public void pullTest() throws Exception{   
        InputStream in=this.getClass().getClassLoader().getResourceAsStream("schools.xml");   
        List<School> schoolList=PullSchoolService.getSchoolList(in);   
        for(School list:schoolList){   
            //Log.i("TAG",List.toString());   
            Log.i("TAG",list.getStudent().toString());   
        }   
           
    }   
    public void pullsave() throws Throwable{   
        List<School> schoolList=new ArrayList<School>();   
        School school=new School();   
        Teacher teacher=new Teacher();   
        List<Student> studentList=new ArrayList<Student>();   
           
        teacher.setTeacherName("Mary");   
        teacher.setTeacherAge(20);   
        studentList.add(new Student("Tom",20));   
        studentList.add(new Student("Jack",22));   
        studentList.add(new Student("Jimjarry",21));   
           
        school.setTeacher(teacher);   
        school.setStudent(studentList);   
        school.setLevel("middle-school");   
           
        schoolList.add(school);   
        schoolList.add(new School("primary-school",new Teacher("renhaili",20),studentList));   
           
        File file=new File(this.getContext().getFilesDir(),"new_student.xml");   
        Writer writer=new FileWriter(file);   
        PullSchoolService.writerPersonList(schoolList, writer);   
    }    
       
}   
     

當寫到此時測試類就寫完瞭,但是要註意我們還要在AndroidManifest.xmlAndroidManifest.xml中添加uses-library和test的聲明

<uses-sdk android:minSdkVersion="10" /> 
    <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="song.activity"></instrumentation> 
 
    <application 
        android:icon="@drawable/ic_launcher" 
        android:label="@string/app_name" > 
        <uses-library android:name="android.test.runner"/> 
    </application> 
好瞭,運行一下,測試類均可以通過

摘自 瀟灑哥的專欄

發佈留言