Android系列學習:xml 文本解析

Android 系列學習之XML文本數據解析

什麼是XML?  XML是一種擴展標誌語言。標準通用標記語言的子類,一種標記電子文件使其具有結構性的標記語言,一種可以有用戶自定義標誌的的源語言。

XMl的特點:

  1. 一種標記語言,很類似HTML
  2. 其宗旨是傳輸數據
  3. 標籤沒有被預定義,用戶需要自己定義標籤
  4. 具有較好的自我秒描述性
  5. 是W3C推薦標準
  6. 純文本信息
  7. 空格會被保留

XML與HTML有啥區別呢?

  1. XML旨在傳輸信息。XML被設置爲傳輸和儲存數據,焦點在數據內容;
  2. HTML旨在顯示信息。HTML被設計問顯示信息,焦點在信息的展示外觀;
  3. XML的標籤都沒有預定義,需要用戶自定義標籤,HTML則是所有表親都是預定義的。

常使用來解析XML數據的兩種方式:SAX解析,在Android中較爲流行的一種解析器;還有就是Document解析,在Android中,用的還是相對比較少的。

下面實例來比較一下兩種的區別。

Document 解析:



 

步聚

  1. 獲取document的解析工廠;DocumentBuilderFactory
  2. 獲取DocumentBuilderFactory
  3. 獲取Document實例

實例代碼:

      //獲取Documen的解析工廠
      DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
      //獲取解析的器的對象Document 
      // inputStream爲讀取本地XML文件獲取到的inputStream或者是web獲取的inputStream,
      // 這裏使用的是獲取web服務器上的XML文件的inputStream
      Document document = builder.parse(inputStream);

 這樣就可以輕鬆獲取到Document的實例了,下面看一下解析XML數據,其實也是挺簡單的。解析的數據文本是:

 根據上述XML文本,解析數據

           //獲取XML文件的“根”元素包括的內容,即最外從元素包含的內容
            Element documentElement = document.getDocumentElement();
            //獲取子對象的全部內容,返回一個包含全部子對象的隊列
            NodeList nodeList = documentElement.getElementsByTagName("user");
            for (int i = 0; i < nodeList.getLength(); i++) {
                //獲取到nodeList的每一個子對象
                Element node = (Element) nodeList.item(i);
                //獲取該對象node的屬性 即數據的id
                String id = node.getAttribute("id");

                //再獲取node下的子元素 隊列
                NodeList nameList = node.getElementsByTagName("name");
                NodeList sexList = node.getElementsByTagName("sex");
                NodeList classesList = node.getElementsByTagName("classes");

                //提取數據
                String name = nameList.item(0).getTextContent();
                String sex = sexList.item(0).getTextContent();
                String classes = classesList.item(0).getTextContent();

                Log.e("nodeAttribute", id);
                Log.e("name",name);
                Log.e("sex",sex);
                Log.e("classes",classes);

            }

 解析的結果:

 

 結果是結束正確的。

 

 

下面看一下SAX解析XML文本數據。

SAX解析XML文檔採用事件驅動模式。什麼是事件驅動模式?它將XML文檔轉換成一系列的事件,由單獨的事件處理器來決定如何處理。

基於事件驅動的處理模式主要是基於事件源和事件處理器(或者叫監聽器)來工作的。一個可以產生事件的對象叫做事件源,而一個可以針對事件做出響應的對象就被叫做事件處理器。

步聚:

  1. 創建DefaultHandler子類並實現一定相應的方法
  2. 創建解析器的工廠類SAXParserFactory
  3. 創建解析器的解析類SAXParser
  4. 獲取XMLReader的實例
  5. 創建DefaultHandler子類註冊到XMLReader當中
  6. 將從XML文件獲取到的inputStream丟給XMLReader開始解析

實例代碼:

 

            //獲取解析器工廠類
            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            //獲取解析器的解析類
            SAXParser saxParser = saxParserFactory.newSAXParser();
            //獲取XMLReader實例
            XMLReader xmlReader = saxParser.getXMLReader();
            //XMLReader 與創建DefaultHandler子類關聯(DefaultHandler註冊到XMLReader)
            xmlReader.setContentHandler(new XMLHandlers());
            //開始解析,InputStream爲從本地讀取XML文件獲得的InputStream
            // 或者是從web上獲取的InputStream
            xmlReader.parse(new InputSource(inputStream));

 解析開始了,怎麼來獲取數據呢?還是用上面的XML文本數據

 

解析數據至少需要在創建DefaultHandler子類中複寫以下三方法

 

 /**
     * 開始讀取元素
     *
     * @param uri
     * @param localName 無前綴的標籤
     * @param qName 有前綴的標籤
     * @param attributes 屬性集合
     * @throws SAXException
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        Log.e("startElement", "startElement");
        this.localName = localName;
        if ("user".equals(localName)) {
            for (int i = 0; i < attributes.getLength(); i++) {
                Log.e("user_id", attributes.getValue("id"));
            }
        }

    }

 

 /**
     * 讀取元素結束
     *
     * @param uri
     * @param localName 無前綴 的標籤
     * @param qName 有前綴的標籤
     * @throws SAXException
     */
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        Log.e("endElement", "endElement");
    }

 

 

 

/**
     * 解析數據
     *
     * @param ch 字符數組
     * @param start 開始位置
     * @param length 字符數組的長度
     * @throws SAXException
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        Log.e("characters", "characters");
        if (localName.equals("name")) {
            name = new String(ch, start, length);
            Log.e("name", name);
        } else if (localName.equals("sex")) {
            sex = new String(ch, start, length);
            Log.e("sex", sex);
        } else if (localName.equals("classes")) {
            classes = new String(ch, start, length);
            Log.e("classes", classes);
        }
    }

 

 

析出來的數據,有點兒難看,但是仔細看也不難,而且還會發現一點兒奇怪的東西。

 

09-17 15:05:10.637    2535-2553/? E/startDocument﹕ startDocument
09-17 15:05:10.639    2535-2553/? E/startElement﹕ startElement
09-17 15:05:10.639    2535-2553/? E/characters﹕ characters
09-17 15:05:10.639    2535-2553/? E/characters﹕ characters
09-17 15:05:10.639    2535-2553/? E/startElement﹕ startElement
09-17 15:05:10.639    2535-2553/? E/user_id﹕ 1
09-17 15:05:10.639    2535-2553/? E/characters﹕ characters
09-17 15:05:10.639    2535-2553/? E/characters﹕ characters
09-17 15:05:10.639    2535-2553/? E/startElement﹕ startElement
09-17 15:05:10.639    2535-2553/? E/characters﹕ characters
09-17 15:05:10.639    2535-2553/? E/name﹕ gaosi
09-17 15:05:10.639    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.639    2535-2553/? E/characters﹕ characters
09-17 15:05:10.639    2535-2553/? E/name﹕ [ 09-17 15:05:10.639  2535: 2553 E/characters ]
    characters
09-17 15:05:10.639    2535-2553/? E/name﹕ [ 09-17 15:05:10.639  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.639    2535-2553/? E/characters﹕ characters
09-17 15:05:10.639    2535-2553/? E/sex﹕ 男
09-17 15:05:10.639    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.640    2535-2553/? E/characters﹕ characters
09-17 15:05:10.640    2535-2553/? E/sex﹕ [ 09-17 15:05:10.640  2535: 2553 E/characters ]
    characters
09-17 15:05:10.640    2535-2553/? E/sex﹕ [ 09-17 15:05:10.640  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.640    2535-2553/? E/characters﹕ characters
09-17 15:05:10.640    2535-2553/? E/classes﹕ 3
09-17 15:05:10.640    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.640    2535-2553/? E/characters﹕ characters
09-17 15:05:10.640    2535-2553/? E/classes﹕ [ 09-17 15:05:10.640  2535: 2553 E/characters ]
    characters
09-17 15:05:10.640    2535-2553/? E/classes﹕ [ 09-17 15:05:10.640  2535: 2553 E/endElement ]
    endElement
09-17 15:05:10.640    2535-2553/? E/characters﹕ characters
09-17 15:05:10.640    2535-2553/? E/classes﹕ [ 09-17 15:05:10.640  2535: 2553 E/characters ]
    characters
09-17 15:05:10.640    2535-2553/? E/classes﹕ [ 09-17 15:05:10.640  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.640    2535-2553/? E/user_id﹕ 2
09-17 15:05:10.640    2535-2553/? E/characters﹕ characters
09-17 15:05:10.640    2535-2553/? E/characters﹕ characters
09-17 15:05:10.640    2535-2553/? E/startElement﹕ startElement
09-17 15:05:10.640    2535-2553/? E/characters﹕ characters
09-17 15:05:10.640    2535-2553/? E/name﹕ 張
09-17 15:05:10.641    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.641    2535-2553/? E/characters﹕ characters
09-17 15:05:10.641    2535-2553/? E/name﹕ [ 09-17 15:05:10.641  2535: 2553 E/characters ]
    characters
09-17 15:05:10.641    2535-2553/? E/name﹕ [ 09-17 15:05:10.641  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.641    2535-2553/? E/characters﹕ characters
09-17 15:05:10.641    2535-2553/? E/sex﹕ 男
09-17 15:05:10.641    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.641    2535-2553/? E/characters﹕ characters
09-17 15:05:10.641    2535-2553/? E/sex﹕ [ 09-17 15:05:10.641  2535: 2553 E/characters ]
    characters
09-17 15:05:10.641    2535-2553/? E/sex﹕ [ 09-17 15:05:10.642  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.642    2535-2553/? E/characters﹕ characters
09-17 15:05:10.642    2535-2553/? E/classes﹕ 3
09-17 15:05:10.642    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.642    2535-2553/? E/characters﹕ characters
09-17 15:05:10.642    2535-2553/? E/classes﹕ [ 09-17 15:05:10.642  2535: 2553 E/characters ]
    characters
09-17 15:05:10.642    2535-2553/? E/classes﹕ [ 09-17 15:05:10.642  2535: 2553 E/endElement ]
    endElement
09-17 15:05:10.642    2535-2553/? E/characters﹕ characters
09-17 15:05:10.642    2535-2553/? E/classes﹕ [ 09-17 15:05:10.643  2535: 2553 E/characters ]
    characters
09-17 15:05:10.643    2535-2553/? E/classes﹕ [ 09-17 15:05:10.643  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.643    2535-2553/? E/user_id﹕ 3
09-17 15:05:10.643    2535-2553/? E/characters﹕ characters
09-17 15:05:10.643    2535-2553/? E/characters﹕ characters
09-17 15:05:10.643    2535-2553/? E/startElement﹕ startElement
09-17 15:05:10.643    2535-2553/? E/characters﹕ characters
09-17 15:05:10.643    2535-2553/? E/name﹕ 李四
09-17 15:05:10.643    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.643    2535-2553/? E/characters﹕ characters
09-17 15:05:10.643    2535-2553/? E/name﹕ [ 09-17 15:05:10.643  2535: 2553 E/characters ]
    characters
09-17 15:05:10.643    2535-2553/? E/name﹕ [ 09-17 15:05:10.643  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.643    2535-2553/? E/characters﹕ characters
09-17 15:05:10.643    2535-2553/? E/sex﹕ 男
09-17 15:05:10.643    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.643    2535-2553/? E/characters﹕ characters
09-17 15:05:10.643    2535-2553/? E/sex﹕ [ 09-17 15:05:10.643  2535: 2553 E/characters ]
    characters
09-17 15:05:10.643    2535-2553/? E/sex﹕ [ 09-17 15:05:10.644  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.644    2535-2553/? E/characters﹕ characters
09-17 15:05:10.644    2535-2553/? E/classes﹕ 2
09-17 15:05:10.644    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.644    2535-2553/? E/characters﹕ characters
09-17 15:05:10.644    2535-2553/? E/classes﹕ [ 09-17 15:05:10.644  2535: 2553 E/characters ]
    characters
09-17 15:05:10.644    2535-2553/? E/classes﹕ [ 09-17 15:05:10.644  2535: 2553 E/endElement ]
    endElement
09-17 15:05:10.644    2535-2553/? E/characters﹕ characters
09-17 15:05:10.644    2535-2553/? E/classes﹕ [ 09-17 15:05:10.644  2535: 2553 E/characters ]
    characters
09-17 15:05:10.644    2535-2553/? E/classes﹕ [ 09-17 15:05:10.644  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.644    2535-2553/? E/user_id﹕ 4
09-17 15:05:10.644    2535-2553/? E/characters﹕ characters
09-17 15:05:10.644    2535-2553/? E/characters﹕ characters
09-17 15:05:10.644    2535-2553/? E/startElement﹕ startElement
09-17 15:05:10.644    2535-2553/? E/characters﹕ characters
09-17 15:05:10.644    2535-2553/? E/name﹕ 王
09-17 15:05:10.644    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.644    2535-2553/? E/characters﹕ characters
09-17 15:05:10.644    2535-2553/? E/name﹕ [ 09-17 15:05:10.644  2535: 2553 E/characters ]
    characters
09-17 15:05:10.644    2535-2553/? E/name﹕ [ 09-17 15:05:10.644  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.644    2535-2553/? E/characters﹕ characters
09-17 15:05:10.644    2535-2553/? E/sex﹕ 女
09-17 15:05:10.644    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.644    2535-2553/? E/characters﹕ characters
09-17 15:05:10.645    2535-2553/? E/sex﹕ [ 09-17 15:05:10.645  2535: 2553 E/characters ]
    characters
09-17 15:05:10.645    2535-2553/? E/sex﹕ [ 09-17 15:05:10.645  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.645    2535-2553/? E/characters﹕ characters
09-17 15:05:10.645    2535-2553/? E/classes﹕ 2
09-17 15:05:10.645    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.645    2535-2553/? E/characters﹕ characters
09-17 15:05:10.645    2535-2553/? E/classes﹕ [ 09-17 15:05:10.645  2535: 2553 E/characters ]
    characters
09-17 15:05:10.645    2535-2553/? E/classes﹕ [ 09-17 15:05:10.645  2535: 2553 E/endElement ]
    endElement
09-17 15:05:10.645    2535-2553/? E/characters﹕ characters
09-17 15:05:10.645    2535-2553/? E/classes﹕[ 09-17 15:05:10.645  2535: 2553 E/characters ]
    characters
09-17 15:05:10.645    2535-2553/? E/classes﹕ [ 09-17 15:05:10.645  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.645    2535-2553/? E/user_id﹕ 5
09-17 15:05:10.645    2535-2553/? E/characters﹕ characters
09-17 15:05:10.645    2535-2553/? E/characters﹕ characters
09-17 15:05:10.645    2535-2553/? E/startElement﹕ startElement
09-17 15:05:10.645    2535-2553/? E/characters﹕ characters
09-17 15:05:10.645    2535-2553/? E/name﹕ 道
09-17 15:05:10.645    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.645    2535-2553/? E/characters﹕ characters
09-17 15:05:10.645    2535-2553/? E/name﹕ [ 09-17 15:05:10.645  2535: 2553 E/characters ]
    characters
09-17 15:05:10.645    2535-2553/? E/name﹕ [ 09-17 15:05:10.645  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.646    2535-2553/? E/characters﹕ characters
09-17 15:05:10.646    2535-2553/? E/sex﹕ 男
09-17 15:05:10.646    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.646    2535-2553/? E/characters﹕ characters
09-17 15:05:10.646    2535-2553/? E/sex﹕ [ 09-17 15:05:10.646  2535: 2553 E/characters ]
    characters
09-17 15:05:10.646    2535-2553/? E/sex﹕ [ 09-17 15:05:10.646  2535: 2553 E/startElement ]
    startElement
09-17 15:05:10.646    2535-2553/? E/characters﹕ characters
09-17 15:05:10.646    2535-2553/? E/classes﹕ 1
09-17 15:05:10.646    2535-2553/? E/endElement﹕ endElement
09-17 15:05:10.646    2535-2553/? E/characters﹕ characters
09-17 15:05:10.646    2535-2553/? E/classes﹕ [ 09-17 15:05:10.646  2535: 2553 E/characters ]
    characters
09-17 15:05:10.646    2535-2553/? E/classes﹕ [ 09-17 15:05:10.646  2535: 2553 E/endElement ]
    endElement
09-17 15:05:10.647    2535-2553/? E/characters﹕ characters
09-17 15:05:10.647    2535-2553/? E/classes﹕ [ 09-17 15:05:10.647  2535: 2553 E/characters ]
    characters
09-17 15:05:10.647    2535-2553/? E/classes﹕ [ 09-17 15:05:10.648  2535: 2553 E/characters ]
    characters
09-17 15:05:10.648    2535-2553/? E/classes﹕ [ 09-17 15:05:10.648  2535: 2553 E/characters ]
    characters
09-17 15:05:10.648    2535-2553/? E/classes﹕ [ 09-17 15:05:10.649  2535: 2553 E/endElement ]
    endElement
09-17 15:05:10.649    2535-2553/? E/endDocument﹕ endDocument

 對比以下Document解析,你有沒有發現一點東西?

 

SAX  是逐行從上往下解析的,變掃描邊解析。而document解析則是將整個XML文本讀取掃描完畢,在從外往裏一層一層的解析。

聰明的人就會想到,這樣的話,我利用SAX解析,解析達到一定的條件,終止解析XML數據,這樣就會簡單很多了吧。對的。怎麼方法類中斷呢?

查看上面的解析結果,發現endDocument()是調用一次,可不可以到達特定的條件時候,調用該方法類終止解析呢?還有一種也可以使用return 來終止解析,是否可以呢?這兩個都是不行的。

不知道有沒有發現DefaultHandler子類的複寫方法都會拋異常, 我們只要在解析達到特定的條件時候,拋異常就OK了

在調用解析方法出捕獲一下異常

 

try{
                //XMLReader 與創建DefaultHandler子類關聯(DefaultHandler註冊到XMLReader)
                xmlReader.setContentHandler(new XMLHandlers());
                //開始解析,InputStream爲從本地讀取XML文件獲得的InputStream
                // 或者是從web上獲取的InputStream
                xmlReader.parse(new InputSource(inputStream));
            }catch (SAXException e){
                //TODO去幹中斷解析的工作吧
                //……
            }

 在characters()方法解析數據出等到達到特定條件就拋異常

 

 

if (localName.equals("name")) {
            name = new String(ch, start, length);
            Log.e("name", name);
            if (name.equals("gaosi")){
                super.endDocument();
                throw new SAXException("中斷掃描,解析完成");
            }
        }

 看一下區別:

 總結:

 

Document:
       解析器讀入整個文檔,然後構建一個駐留內存的樹結構,然後代碼就可以使用 DOM 接口來操作這個樹結構。
       優點:整個文檔樹在內存中,便於操作;支持刪除、修改、重新排列等多種功能;
       缺點:將整個文檔調入內存(包括無用的節點),浪費時間和空間;
       使用場合:一旦解析了文檔還需多次訪問這些數據;
SAX:
       事件驅動。當解析器發現元素開始、元素結束、文本、文檔的開始或結束等時,發送事件,程序員編寫響應這些事件的代碼,保存數據。
       優點:不用事先調入整個文檔,佔用資源少,可以隨時停止
       缺點:不是持久的;事件過後,若沒保存數據,那麼數據就丟了;無狀態性;從事件中只能得到文本,但不知該文本屬於哪個元素;
       使用場合:只需XML文檔的少量內容,很少回頭訪問;一次性讀取;
       注意:SAX 解析器不創建任何對象。

在Android平臺中,SAX解析更符合用戶的而需求,不僅是簡單,耗能少,耗時也少,內存需求少等

 

  • 82849acc-e2cb-34e5-94ce-0271bc03d2f0-thumb.png
  • 大小: 27.3 KB
  • 5a191fb5-c7b1-32b0-bfb3-99ec30405875-thumb.png
  • 大小: 38.3 KB
  • eb0da00c-ab11-3139-952c-2dcc9794045f-thumb.png
  • 大小: 25.6 KB
  • 71d8c230-59f1-36e0-95e2-26a3dacf65db-thumb.png
  • 大小: 44.8 KB
  • bbd4683c-c9ef-339e-8f6c-fc68761176ae-thumb.png
  • 大小: 23.6 KB
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章