Android中常見的XML解析方式

基本概念

  1. 概念:extensive markup language(可擴展的標記語言)
    XML是一種通用的數據存儲和交換格式,與平臺無關,與編程語言無關,與操作系統無關。給數據集成和交互提供了極大的便利。
    將數據格式化成XML文件後,真正實現了數據跨平臺的交互和共享。在不同語言中,xml的解析方式都一樣。

  2. XML文件格式
    1.每個xml文件中要有一個,且只能有一個xml根節點;
    2.xml文件的數據中不可以 出現”< “或者” >”;

  3. XML的解析方式
    DOM(document object model :文檔對象模型):藉助文檔樹模型對xml文檔進行分析。
    SAX(simple API for xml :xml的簡單api):利用事件流的形式解析XML
    PULL:利用事件流模型來解析XML。
    備註:DOM和SAX解析的優劣分析:DOM是將文檔一次性讀入到內存,然後以文檔樹模進行分析節點信息。獲取到希望獲取的數據;
    而SAX是事件流的形式去分析xml文件。DOM可以做到對文檔中部分節點的修改、刪除和新增,而SAX無法做到。

PULL解析xml

  1. PULL Parser中的幾種event值
    1、START_DOCUMENT: 0
    2、END_DOCUMENT: 1
    3、START_TAG: 2
    4、END_TAG: 3
    5、TEXT: 4

  2. 核心類:
    XmlPullParserFactory
    XmlPullParser

  3. 核心代碼:

    // 實例化一個xml pull解析的工廠
    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
    // 實例化一個xml pull解析對象
    XmlPullParser parser = factory.newPullParser();
    // xml解析對象接收輸入流對象
    parser.setInput(instream, "utf-8");
    int event = parser.getEventType();//獲取事件類型
    while (event != XmlPullParser.END_DOCUMENT) {
    switch (event) {
     case XmlPullParser.START_DOCUMENT:
           //開始讀取文檔
        break;
     case XmlPullParser.START_TAG:
          //讀取元素開始標籤
        break;
     case XmlPullParser.TEXT:
          //讀取文本
       break;
     case XmlPullParser.END_TAG:
          //讀取閉合標籤
       break;
    }
    event = parser.next();//獲取下一次解析事件
    }
  4. 常用api

 //獲取屬性名
 parser.getAttributeName()
 //獲取屬性值
 parser.getAttributeValue()
 //獲取文本值
 parser.getText();
 //獲取標籤名
 parser.getName();
 //獲取下一個文本解析事件,返回文本值(如果當前是START_TAG,且下一個節點是TEXT,則返回文本,如果下一個是END_TAG,返回null,否則則會拋出異常)
 parser.nextText();
 //獲取下一個標籤解析事件,返回事件類型,如果下一個事件不是START_TAG或END_TAG,則拋出異常
 parser.nextTag();
 //獲取下一個解析事件,返回事件類型
 parser.next();

SAX解析xml

SAX解析基本與PULL解析基本相同,也是通過事件流的形式解析xml,SAX的解析藉助於DefaultHandler這個處理類。該類實現如下:


     class MyXmlHandler extends DefaultHandler {

         /**
          * 開始讀取文檔
          *
          * @throws SAXException
          */
         @Override
         public void startDocument() throws SAXException {
             super.startDocument();
         }

         /**
          * 開始讀取元素
          */
         @Override
         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
             super.startElement(uri, localName, qName, attributes);
             //uri:命名空間
             //localName:不帶前綴(命名空間)的標籤名
             //qName:帶前綴的標籤名
             //attributes:屬性集合

         }

         /**
          * 開始讀取Text
          */
         @Override
         public void characters(char[] ch, int start, int length) throws SAXException {
             super.characters(ch, start, length);

         }

         /**
          * 結束讀取元素
          */
         @Override
         public void endElement(String uri, String localName, String qName) throws SAXException {
             super.endElement(uri, localName, qName);
             //uri:命名空間
             //localName:不帶前綴(命名空間)的標籤名
             //qName:帶前綴的標籤名
         }

         /**
          * 結束讀取文檔
          */
         @Override
         public void endDocument() throws SAXException {
             super.endDocument();
         }
     }

核心代碼如下:

 SAXParserFactory factory=SAXParserFactory.newInstance();
 SAXParser parser=factory.newSAXParser();
 MyXmlHandler handler=new MyXmlHandler();//繼承自DefaultHandler
 parser.parse(in,handler);//插入一個自定義的xml處理器

DOM解析xml

  1. DOM樹中對節點(NODE)的分類如下
    1、文檔節點,Document
    2、元素節點,Element
    3、屬性節點,Attribute
    4、文本節點,Text
    5、註釋節點,Comment

  2. 核心類:
    DocumentBuilderFactory
    DocumentBuilder
    Doucment,一個xml就是一個Document
    Element ,…就是一個元素
    NodeList ,節點集合
    Node,節點,包括文檔、元素、屬性、文本節點等

  3. 核心代碼

    DocumentBuilderFactory factory =  DocumentBuilderFactory.newInstance();
    // 使用工廠來實例化一個構造Document的對象
    DocumentBuilder builder = factory.newDocumentBuilder();
    // 利用DocumentBuilder來構造一個Document對象
    Document document = builder.parse(filename);
    // 獲取Document文檔的根節點對象
    Element root = document.getDocumentElement();
    // 通過根節點,獲取到根節點下面的所有二級子節點
    NodeList nodeList = root.getChildNodes();
    // 遍歷子節點,獲取內部的每一個節點
    for (int i = 0; i < nodeList.getLength(); i++) {
     Node node = nodeList.item(i);
     ...
    }
    ...
  4. 常用api
//獲取屬性值
element.getAttribute();
//獲取屬性節點,沒有則null
element.getAttributeNode();
//根據標籤名返回當前節點下的後代(子子孫孫)節點
element.getElementsByTagName();
//獲取標籤名
element.getTagName();


//獲取當前節點及其子節點的所有文本內容
node.getTextContent();
//獲取兒子子節點           
node.getChildNodes();
//獲取節點名字(屬性節點返回屬性名字,元素節點返回標籤名,Text節點返回"#text",Document節點返回"#document")
node.getNodeName();
//獲取節點值(屬性節點返回屬性值,文本節點返回文本內容,Comment節點返回內容,CDATASection節點返回內容,其他節點返回null);
node.getNodeValue();
//返回當前節點的第一個子節點          
node.getFirstChild();
//返回當前節點的最後子節點
node.getLastChild();
//獲取節點類型
node.getNodeType();
//返回下一個兄弟節點
node.getNextSibling();
//返回上一個兄弟節點
node.getPreviousSibling();
//不包含命名空間的名字
node.getLocalName();
//以當前節點爲根節點獲取一個document對象
node.getOwnerDocument();

解析實戰

下面是一段顯示近三日天氣的xml,分別採用三種方式進行解析。

<weatherinfo>
    <data d_id="01">
        <date>2016-05-07</date>
        <icon>d04|n04</icon>
        <weather>雷陣雨</weather>
        <temperature>36℃~28℃</temperature>
        <winddirect>西南風3-4級</winddirect>
    </data>
    <data d_id="02">
        <date>2016-05-08</date>
        <icon>d04|n04</icon>
        <weather>雷陣雨</weather>
        <temperature>32℃~26℃</temperature>
        <winddirect>西風3-4級轉西北3-4級</winddirect>
    </data>
    <data d_id="03">
        <date>2016-05-09</date>
        <icon>d04|n04</icon>
        <weather>雷陣雨</weather>
        <temperature>32℃~26℃</temperature>
        <winddirect>西北風3-4級</winddirect>
    </data>
</weatherinfo>  

首先根據xml創建一個Weather類。實現如下:

public class Weather {
    private String id;
    private String date;
    private String icon;
    private String weather;
    private String temperature;
    private String winddirect;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    public String getWeather() {
        return weather;
    }

    public void setWeather(String weather) {
        this.weather = weather;
    }

    public String getTemperature() {
        return temperature;
    }

    public void setTemperature(String temperature) {
        this.temperature = temperature;
    }

    public String getWinddirect() {
        return winddirect;
    }

    public void setWinddirect(String winddirect) {
        this.winddirect = winddirect;
    }
}
  • PULL解析
public static List<Weather> pullParser(InputStream in) throws XmlPullParserException, IOException {
       //初始化核心類
        XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
        XmlPullParser parser=factory.newPullParser();
        parser.setInput(in,"utf-8");
        //初始化集合
        List<Weather> list=new ArrayList<>();
        Weather weather=null;
        boolean flag=false;//weather類實例化的標識
        //獲取事件類型
        int type=parser.getEventType();
        while(type!=XmlPullParser.END_DOCUMENT){
            switch (type) {
                //開始標籤
                case XmlPullParser.START_TAG:
                    //如果開始標籤是data,初始化Weather類
                   if(parser.getName().equals("data")){
                         weather=new Weather();
                         //讀取屬性值
                         String id=parser.getAttributeValue(null,"d_id");
                         weather.setId(id);
                         flag=true;
                         list.add(weather);

                    }
                   if(flag){//如果Weather類已實例化,就開始設置值
                       if(parser.getName().equals("date")){
                          //讀取當前START_TAG的下一個文本節點
                           weather.setDate(parser.nextText());
                       }
                       else if(parser.getName().equals("weather")){
                           weather.setWeather(parser.nextText());
                       }
                       else if(parser.getName().equals("icon")){
                           weather.setIcon(parser.nextText());
                       }
                       else if(parser.getName().equals("temperature")){
                           weather.setTemperature(parser.nextText());
                       }
                       else if(parser.getName().equals("winddirect")){
                           weather.setWinddirect(parser.nextText());
                       }
                   }

                    break;
                //閉合標籤
                case XmlPullParser.END_TAG:
                    if(parser.getName().equals("data")){
                        flag=false;
                        weather=null;
                    }
                    break;
            }
            //開始下一次解析事件
            type=parser.next();
        }
        return list;
    }
  • SAX解析
 public static List<Weather> saxParser(InputStream in) throws ParserConfigurationException, SAXException, IOException{
        SAXParserFactory factory=SAXParserFactory.newInstance();
        SAXParser parser=factory.newSAXParser();
        XmlHandler handler=new XmlHandler();//繼承自DefaultHandler
        parser.parse(in,handler);//插入一個自定義的xml處理器
        return handler.getList();
    }

    static class XmlHandler extends DefaultHandler{

        private List<Weather> list;
        private String tagName;
        private boolean flag=false;
        private Weather weather;

        /**
         * 開始讀取文檔
         * @throws SAXException
         */
        @Override
        public void startDocument() throws SAXException {
            super.startDocument();
            list=new ArrayList<>();
        }

        /**
         * 開始讀取元素
         */
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, qName, attributes);
            //uri:命名空間
            //localName:不帶前綴(命名空間)的標籤名
            //qName:帶前綴的標籤名
            //attributes:屬性集合
            this.tagName=localName;
            if(tagName.equals("data")){
                weather=new Weather();
                String id=attributes.getValue(0);
                weather.setId(id);
                flag=true;
            }
            //
        }

        /**
         * 開始讀取Text
         */
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            super.characters(ch, start, length);

            String str=new String(ch,start,length).trim();
            if(tagName!=null){
                if(flag){
                    if(tagName.equals("date")){
                        weather.setDate(str);
                    }else if(tagName.equals("icon")){
                        weather.setIcon(str);
                    }else if(tagName.equals("weather")){
                        weather.setWeather(str);
                    }else if(tagName.equals("temperature")){
                        weather.setTemperature(str);
                    }else if(tagName.equals("winddirect")){
                        weather.setWinddirect(str);
                    }
                }
            }

        }

        /**
         * 結束讀取元素
         */
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            super.endElement(uri, localName, qName);
            if(localName.equals("data")){
                list.add(weather);
                flag=false;
            }
            tagName=null;
        }

        /**
         * 結束讀取文檔
         */
        @Override
        public void endDocument() throws SAXException {
            super.endDocument();
        }


        public List<Weather> getList(){
            return list;
        }


    }
  • DOM解析
public static List<Weather> domParser(InputStream in) throws ParserConfigurationException, SAXException, IOException, XmlPullParserException {
        /**
         * 初始化核心API
         */
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
        DocumentBuilder builder=factory.newDocumentBuilder();
        Document document=builder.parse(in);
        List<Weather> list=new ArrayList<>();
        NodeList nodes=document.getElementsByTagName("data");

        for(int i=0;i<nodes.getLength();i++ ){
            Element element= (Element) nodes.item(i);
            Weather weather=new Weather();
            weather.setId(element.getAttribute("d_id"));
            NodeList childs=element.getChildNodes();
            for(int j=0;j<childs.getLength();j++){
                Node temp=childs.item(j);
                if(temp.getFirstChild()!=null){
                    if(temp.getNodeName().equals("date")){
                        weather.setDate(temp.getFirstChild().getNodeValue());
                    }else if(temp.getNodeName().equals("icon")){
                        weather.setIcon(temp.getFirstChild().getNodeValue());
                    }else if(temp.getNodeName().equals("weather")){
                        weather.setWeather(temp.getFirstChild().getNodeValue());
                    }else if(temp.getNodeName().equals("temperature")){
                        weather.setTemperature(temp.getFirstChild().getNodeValue());
                    }else if(temp.getNodeName().equals("winddirect")){
                        weather.setWinddirect(temp.getFirstChild().getNodeValue());
                    }

                }}
            list.add(weather);

        }
        return list;
    }

END

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章