天天看點

三種解析xml的方式

在Android平台上可以使用Simple?API?for XML(SAX) 、 Document Object Model(DOM)和Android附帶的pull解析器解析XML檔案。

下面是本例子要解析的XML檔案:itcast.xml

    <?xml version="1.0" encoding="UTF-8"?>  

    <persons>  

      <person id="23">  

        <name>李明</name>  

        <age>30</age>  

      </person>  

      <person id="20">  

        <name>李向梅</name>  

        <age>25</age>  

    </persons>  

例子定義了一個javabean用于存放上面解析出來的xml内容, 這個javabean為Person,代碼:

    public class Person {  

        private Integer id;  

        private String name;  

    private Short 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 Short getAge() {  

            return age;  

        public void setAge(Short age) {  

            this.age = age;  

    }  

1. SAX解析XML檔案

SAX是一個解析速度快并且占用記憶體少的xml解析器,非常适合用于Android等移動裝置。?SAX解析XML檔案采用的是事件驅動,也就是說,它并不需要解析完整個文檔,在按内容順序解析文檔的過程中,SAX會判斷目前讀到的字元是否合法XML文法中的某部分,如果符合就會觸發事件。所謂事件,其實就是一些回調(callback)方法,這些方法(事件)定義在ContentHandler接口。

    public static List<Person> readXML(InputStream inStream) {  

        try {  

            //建立解析器  

            SAXParserFactory spf = SAXParserFactory.newInstance();  

            SAXParser saxParser = spf.newSAXParser();  

            //設定解析器的相關特性,true表示開啟命名空間特性  

            saxParser.setProperty("http://xml.org/sax/features/namespaces",true);  

            XMLContentHandler handler = new XMLContentHandler();  

            saxParser.parse(inStream, handler);  

            inStream.close();  

            return handler.getPersons();  

        } catch (Exception e) {  

            e.printStackTrace();  

        return null;  

    //SAX類:DefaultHandler,它實作了ContentHandler接口。在實作的時候,隻需要繼承該類,重載相應的方法即可。  

    public class XMLContentHandler extends DefaultHandler {  

        private List<Person> persons = null;  

        private Person currentPerson;  

        private String tagName = null;//目前解析的元素标簽  

        public List<Person> getPersons() {  

            return persons;  

        //接收文檔開始的通知。當遇到文檔的開頭的時候,調用這個方法,可以在其中做一些預處理的工作。  

        @Override  

        public void startDocument() throws SAXException {  

            persons = new ArrayList<Person>();  

        //接收元素開始的通知。當讀到一個開始标簽的時候,會觸發這個方法。其中namespaceURI表示元素的命名空間;  

        //localName表示元素的本地名稱(不帶字首);qName表示元素的限定名(帶字首);atts 表示元素的屬性集合  

        public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {  

            if(localName.equals("person")){  

                currentPerson = new Person();  

                currentPerson.setId(Integer.parseInt(atts.getValue("id")));  

            }  

            this.tagName = localName;  

        //接收字元資料的通知。該方法用來處理在XML檔案中讀到的内容,第一個參數用于存放檔案的内容,  

        //後面兩個參數是讀到的字元串在這個數組中的起始位置和長度,使用new String(ch,start,length)就可以擷取内容。  

        public void characters(char[] ch, int start, int length) throws SAXException {  

            if(tagName!=null){  

                String data = new String(ch, start, length);  

                if(tagName.equals("name")){  

                    this.currentPerson.setName(data);  

                }else if(tagName.equals("age")){  

                    this.currentPerson.setAge(Short.parseShort(data));  

                }  

        //接收文檔的結尾的通知。在遇到結束标簽的時候,調用這個方法。其中,uri表示元素的命名空間;  

        //localName表示元素的本地名稱(不帶字首);name表示元素的限定名(帶字首)  

        public void endElement(String uri, String localName, String name) throws SAXException {  

                persons.add(currentPerson);  

                currentPerson = null;  

            this.tagName = null;  

2. DOM解析XML檔案

DOM解析XML檔案時,會将XML檔案的所有内容讀取到記憶體中,然後允許您使用DOM API周遊XML樹、檢索所需的資料。使用DOM操作XML的代碼看起來比較直覺,并且,在某些方面比基于SAX的實作更加簡單。但是,因為DOM需要将XML檔案的所有内容讀取到記憶體中,是以記憶體的消耗比較大,特别對于運作Android的移動裝置來說,因為裝置的資源比較寶貴,是以建議還是采用SAX來解析XML檔案,當然,如果XML檔案的内容比較小采用DOM是可行的。

public static List<Person> readXML(InputStream inStream) {  

    List<Person> persons = new ArrayList<Person>();

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 

    try {  

        DocumentBuilder builder = factory.newDocumentBuilder();  

        Document dom = builder.parse(inStream);  

        Element root = dom.getDocumentElement();  

        NodeList items = root.getElementsByTagName("person");//查找所有person節點  

        for (int i = 0; i < items.getLength(); i++) {  

            Person person = new Person();  

            //得到第一個person節點  

            Element personNode = (Element) items.item(i);  

            //擷取person節點的id屬性值  

            person.setId(new Integer(personNode.getAttribute("id")));  

            //擷取person節點下的所有子節點(标簽之間的空白節點和name/age元素)  

            NodeList childsNodes = personNode.getChildNodes();  

            for (int j = 0; j < childsNodes.getLength(); j++) {  

                Node node = (Node) childsNodes.item(j); //判斷是否為元素類型  

                if(node.getNodeType() == Node.ELEMENT_NODE){     

                    Element childNode = (Element) node;  

                    //判斷是否name元素  

                    if ("name".equals(childNode.getNodeName())) {  

                        //擷取name元素下Text節點,然後從Text節點擷取資料  

                        person.setName(childNode.getFirstChild().getNodeValue());

                    } else if (“age”.equals(childNode.getNodeName())) {  

                        person.setAge(new Short(childNode.getFirstChild().getNodeValue()));  

                    }  

            }

            persons.add(person);  

        }

        inStream.close();  

    } catch (Exception e) {  

        e.printStackTrace();  

    }

    return persons;  

}  

3.Pull解析器解析XML檔案

Pull解析器的運作方式與SAX解析器相似。它提供了類似的事件,如:開始元素和結束元素事件,使用parser.next()可以進入下一個元素并觸發相應事件。事件将作為數值代碼被發送,是以可以使用一個switch對感興趣的事件進行處理。當元素開始解析時,調用parser.nextText()方法可以擷取下一個Text類型元素的值。

    //讀取XML  

        XmlPullParser parser = Xml.newPullParser();  

            parser.setInput(inStream, "UTF-8");  

            int eventType = parser.getEventType();  

            Person currentPerson = null;  

            List<Person> persons = null;  

            while (eventType != XmlPullParser.END_DOCUMENT) {  

                switch (eventType) {  

                    case XmlPullParser.START_DOCUMENT://文檔開始事件,可以進行資料初始化處理  

                        persons = new ArrayList<Person>();  

                        break;  

                    case XmlPullParser.START_TAG://開始元素事件  

                        String name = parser.getName();  

                        if (name.equalsIgnoreCase("person")) {  

                            currentPerson = new Person();  

                            currentPerson.setId(new Integer(parser.getAttributeValue(null, "id")));  

                        } else if (currentPerson != null) {  

                            if (name.equalsIgnoreCase("name")) {  

                                currentPerson.setName(parser.nextText());// 如果後面是Text元素,即傳回它的值  

                            } else if (name.equalsIgnoreCase("age")) {  

                                currentPerson.setAge(new Short(parser.nextText()));  

                            }  

                        }  

                    case XmlPullParser.END_TAG://結束元素事件  

                        if (parser.getName().equalsIgnoreCase("person") && currentPerson != null) {  

                            persons.add(currentPerson);  

                            currentPerson = null;  

                        }

                eventType = parser.next();  

    //成XML檔案  

    //使用Pull解析器生成一個與itcast.xml檔案内容相同的myitcast.xml檔案。  

    public static String writeXML(List<Person> persons, Writer writer){  

        XmlSerializer serializer = Xml.newSerializer();  

            serializer.setOutput(writer);  

            serializer.startDocument("UTF-8", true);  

            //第一個參數為命名空間,如果不使用命名空間,可以設定為null  

            serializer.startTag("", "persons");  

            for (Person person : persons){  

                serializer.startTag("", "person");  

                serializer.attribute("", "id", person.getId().toString());  

                serializer.startTag("", "name");  

                serializer.text(person.getName());  

                serializer.endTag("", "name");  

                serializer.startTag("", "age");  

                serializer.text(person.getAge().toString());  

                serializer.endTag("", "age");  

                serializer.endTag("", "person");  

            serializer.endTag("", "persons");  

            serializer.endDocument();  

            return writer.toString();  

    //使用代碼如下(生成XML檔案):  

    File xmlFile = new File("myitcast.xml");  

    FileOutputStream outStream = new FileOutputStream(xmlFile);  

    OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream, "UTF-8");  

    BufferedWriter writer = new BufferedWriter(outStreamWriter);  

    writeXML(persons, writer);  

    writer.flush();  

    writer.close();  

    //如果隻想得到生成的xml内容,可以使用StringWriter:  

    StringWriter writer = new StringWriter();  

    String content = writer.toString();  

4.SAX和PULL使用

上一篇: Intent、Bundle