Android開發之使用DefaultHandler處理XML數據


一、定義規則

  1.    XML數據結構定義


    請記住上面的定義,后面我會用“標簽開始”、“文本”、“標簽結束”表示SAX正在處理哪部分XML數據

  2. 事件模型

      為什么這里我要談到這個,因為SAX處理XML數據是采用事件的形式來處理,下面我們來簡單的做個介紹。

    當我們處理XML數據中遇到一個開始標簽SAX會告訴你“我遇到了一個開始標簽,這個標簽是XXXX”,等你作出反應后,它會繼續往下
    這時它遇到了一段文本,SAX告訴你“我遇到了一段文本,是XXXX”,然后繼續等你作出反應,接着下去就遇到了結束標簽SAX仍然會
    告訴你“我到了一個結束標簽是XXX”。SAX就是以這樣的方式將整個XML數據全部處理完。


二、為何使用

  1. 節約內存

          這里我要聲明我的目標設備是手機,而不是電腦等等。而手機的內存是很小的,同時也十分珍貴。或許你會說現在手機都是1GB、
    2GB內存,根本不用着想。但是我們既然開發應用,當然是希望使用的人越多越好,而大多數手機設備是沒有那么多內存的,所以我們
    需要盡量使我們開發的應用能夠適合於很多的設備。

  2. 效率高

          手機不僅僅有着內存少的缺點,而且本身的CPU處理能力也是相對較慢的。所以我們要讓代碼的速度更快更快,否則用戶就會感覺
    使用你的應用總是卡頓半天,從而會選擇其他更優秀的應用。而SAX在執行效率方面也是很客觀的,當然這個前提是你的代碼夠簡潔,而
    不是把所有邏輯處理任務都放進處理XML數據的方法里面。

 

三、安卓如何使用

  1. DefaultHandler類

         這是安卓中內置的用於SAX處理XML的類,但是大多情況下我們都需要繼承該類重寫部分方法,才能達到處理XML數據的功能。

  2. startDocument方法

        這是第一個需要重寫的方法,每處理一個XML文檔都會響應一次。所以這個方法里可以寫需要初始化的代碼。

  3. startElement方法

        這是處理每個節點所觸發的方法,通過這個方法你可以直接當前處理的節點的名稱以及屬性。

  4. characters方法

        當處理一個節點之間的文本時候觸發該方法,但是該方法並不會告訴你當前文本的所屬標簽,而僅僅是告訴你文本內容。

  5. endElement方法

        遇到一個節點的結束標簽時,將會出發這個方法,並且會傳遞結束標簽的名稱。

  6. endDocument方法

        如果當前的XML文檔處理完畢后,將會觸發該方法,在此方法內你可以將最終的結果保存並且銷毀不需要使用的變量。

四、執行流程舉例

  1. 下面我將以下的XML文件為例,說明SAX具體如何處理XML文件。(部分文本因為是中文所以經過了URL編碼)

1 <notic>
2   <id>1</id>
3   <title>%3cs%3edsds%3c%2fs%3e</title>
4   <content>%e5%86%85%e5%ae%b91</content>
5   <author>1</author>
6 </notic>

   

2. 下面是具體的響應過程

方法名稱 localName(標簽名稱) ch[](文本名稱)
 startDocument  -- --
 startElement notic --
 startElement id --
 characters -- 1
 endElement id --
 startElement title --
 characters -- %3cs%3edsds%2c%2fs%3e
 endElement title --
 startElement content --
 characters -- %e5%86%85%e5%ae%b91
 endElement content --
 startElement author --
 characters -- 1
 endElement author --
 endElement notic --
 endDocument -- --

 

 

 

 

 

 

 

 

 

 

 

 

 

3.通過上面的分析我們可以清楚的看到,它是如何處理XML文檔的,下面是列舉的一個順序圖:   

 1 <!-- startDocument -->
 2 <notic>   ->  startElement(localName = 'notic')
 3 <id>        ->  startElement(localName = 'id')
 4 1             ->  characters(ch[] = '1')
 5 </id>       ->  endElement(localName = 'id')
 6 <title>     ->  startElement(localName = 'title')
 7 %3c...      ->  characters(ch[] = '略')
 8 </title>    ->  endElement(localName = 'title')
 9 <content> ->  startElement(localName = 'content')
10 %e5...      ->  characters(ch[] = '略')
11 </content> -> endElement(localName = 'content')
12 <author>   -> startElement(localName = 'author')
13 1               ->  characters(ch[] = '1')
14 </author>  -> endElement(localName = 'author')
15 </notic>     -> endElement(localName = 'notic')
16 <!-- endDocument -->

 

五、實例

         下面我們采用一個實例來學習如何使用SAX解析XML

  1. 下面是我們需要解析的XML文檔

     1 <result>
     2   <notic>
     3     <id>1</id>
     4     <title>%3cs%3edsds%3c%2fs%3e</title>
     5     <content>%e5%86%85%e5%ae%b91</content>
     6     <author>1</author>
     7     <time>2013-11-01 12-00-00</time>
     8     <section>%e4%bf%a1%e6%81%af%e5%a4%84</section>
     9     <warn>False</warn>
    10   </notic>
    11   <notic>
    12     <id>2</id>
    13     <title>%e6%b5%8b%e8%af%952</title>
    14     <content>%e5%86%85%e5%ae%b92</content>
    15     <author>2</author>
    16     <time>2013-11-02 12-00-00</time>
    17     <section>%e4%bf%a1%e6%81%af%e5%a4%84</section>
    18     <warn>True</warn>
    19   </notic>
    20   <notic>
    21     <id>3</id>
    22     <title>%e6%b5%8b%e8%af%953</title>
    23     <content>%e5%86%85%e5%ae%b93</content>
    24     <author>3</author>
    25     <time>2013-11-03 12-00-00</time>
    26     <section>%e4%bf%a1%e6%81%af%e5%a4%84</section>
    27     <warn>False</warn>
    28   </notic>
    29   <notic>
    30     <id>4</id>
    31     <title>%e6%b5%8b%e8%af%954</title>
    32     <content>%e5%86%85%e5%ae%b94</content>
    33     <author>4</author>
    34     <time>2013-11-04 12-00-00</time>
    35     <section>%e4%bf%a1%e6%81%af%e5%a4%84</section>
    36     <warn>False</warn>
    37   </notic>
    38   <notic>
    39     <id>5</id>
    40     <title>%e6%b5%8b%e8%af%955</title>
    41     <content>%e5%86%85%e5%ae%b95</content>
    42     <author>5</author>
    43     <time>2013-11-05 12-00-00</time>
    44     <section>%e4%bf%a1%e6%81%af%e5%a4%84</section>
    45     <warn>False</warn>
    46   </notic>
    47   <notic>
    48     <id>6</id>
    49     <title>%e6%b5%8b%e8%af%956</title>
    50     <content>%e5%86%85%e5%ae%b96</content>
    51     <author>6</author>
    52     <time>2013-11-06 12-00-00</time>
    53     <section>%e4%bf%a1%e6%81%af%e5%a4%84</section>
    54     <warn>True</warn>
    55   </notic>
    56   <notic>
    57     <id>7</id>
    58     <title>%e6%b5%8b%e8%af%956</title>
    59     <content>%e5%86%85%e5%ae%b96</content>
    60     <author>6</author>
    61     <time>2013-11-06 12-00-00</time>
    62     <section>%e4%bf%a1%e6%81%af%e5%a4%84</section>
    63     <warn>True</warn>
    64   </notic>
    65   <notic>
    66     <id>8</id>
    67     <title>%e6%b5%8b%e8%af%956</title>
    68     <content>%e5%86%85%e5%ae%b96</content>
    69     <author>6</author>
    70     <time>2013-11-06 12-00-00</time>
    71     <section>%e4%bf%a1%e6%81%af%e5%a4%84</section>
    72     <warn>True</warn>
    73   </notic>
    74   <notic>
    75     <id>9</id>
    76     <title>%e6%b5%8b%e8%af%956</title>
    77     <content>%e5%86%85%e5%ae%b96</content>
    78     <author>6</author>
    79     <time>2013-11-06 12-00-00</time>
    80     <section>%e4%bf%a1%e6%81%af%e5%a4%84</section>
    81     <warn>True</warn>
    82   </notic>
    83   <notic>
    84     <id>10</id>
    85     <title>%e6%b5%8b%e8%af%956</title>
    86     <content>%e5%86%85%e5%ae%b96</content>
    87     <author>6</author>
    88     <time>2013-11-06 12-00-00</time>
    89     <section>%e4%bf%a1%e6%81%af%e5%a4%84</section>
    90     <warn>True</warn>
    91   </notic>
    92 </result>
  2. 開始繼承DefaultHandler類

     1 public class SAXForHandler extends DefaultHandler {
     2           //用於保存當前處理的節點名稱
     3           private String preTag;
     4          //用於保存當前處理的節點數據
     5           private Map<String,String> curMap;
     6          //用於保存最終的結果
     7           private ArrayList<Map<String,String>> result;
     8 
     9           //重寫startDocument
    10           public void startDocument()
    11           {
    12                 //初始化
    13                 result = new ArrayList<Map<String,String>>();
    14            }
    15            
    16            public void startElement(String uri,String localName,String qName,Attributes attributes)
    17             {
    18                  //判斷當前節點是notic時表示是一項數據,創建一個新的項
    19                  if("notic".equals(localName))
    20                  {
    21                          curMap = new HashMap<String,String>();
    22                   }
    23                   //用於保存當前處理的節點名稱,用於后面判斷用
    24                   preTag = localName;
    25              }
    26               
    27              public void characters(char[] ch,int start,int length)
    28              {
    29                  //從char[]數據轉換成String
    30                  String data = new String(ch,start,length);
    31                  if("id".equals(preTag))
    32                  {
    33                        //表示當前的文本值是id標簽的
    34                        curMap.put("id",data);
    35                   }else if("title".equals(preTag))
    36                   {
    37                        //表示當前的文本值是title標簽的
    38                        curMap.put("title",data);
    39                    }else if("content".equals(preTag))
    40                    {
    41                        //表示當前的文本值是content標簽的
    42                        curMap.put("content",data);
    43                    }
    44                    else if("time".equals(preTag))
    45                    {
    46                        //表示當前的文本值是time標簽的
    47                        curMap.put("time",data);
    48                    }else if("section".equals(preTag))
    49                    {
    50                        //表示當前的文本值是section標簽的
    51                        curMap.put("section",data);
    52                    }else if("warn",equals(preTag))
    53                    {
    54                        //表示當前的文本值是warn標簽的
    55                        curMap.put("warn",data);
    56                    }
    57               }
    58                
    59               public void endElement(String uri,String localName,String qName)
    60               {
    61                    if("notic".equals(localName))
    62                    {
    63                           //表示一條數據處理完畢
    64                           result.add(curMap);
    65                           curMap = null;
    66                    }
    67                    //每次處理完一個節點都要將preTag重置
    68                    preTag = null;
    69               }
    70 
    71               public void endDocument()
    72               {
    73                    //XML處理結束,因為沒有使用到必須釋放的資源所以這里為空
    74               }
    75 }     
  3. 如何使用該SAXForHandler

    1 //in為InputStream表示讀取的XML文件流
    2 SAXParserFactory spf = SAXParserFactory.newInstance();
    3 SAXParser sp = spf.newSAXParser();
    4 SAXForHandler sfh = new SAXForHandler();
    5 sp.parser(in,sfh);
    6 //如果要想獲得處理后的結果
    7 //可以公開一個方法,用來將result通過return的方法傳遞給調用者.

 

六、以下是本人開發的一個工具類,可以方便的通過代碼調整SAXForHandler來處理不同的XML

  1 package com.ninesoft.newprower.xml;
  2 
  3 import java.io.UnsupportedEncodingException;
  4 import java.net.URLDecoder;
  5 import java.util.ArrayList;
  6 import java.util.HashMap;
  7 import java.util.Map;
  8 
  9 import org.xml.sax.Attributes;
 10 import org.xml.sax.SAXException;
 11 import org.xml.sax.helpers.DefaultHandler;
 12 
 13 public class SaxForXmlHandler extends DefaultHandler {
 14     private String[] _needTag;
 15     private ArrayList<Map<String,String>> _notics;
 16     private Map<String,String> current;
 17     private String preTag;
 18     private String _nodeTag;
 19     
 20     //構造函數
 21     public SaxForXmlHandler(String tag)
 22     {
 23         this._nodeTag = tag;
 24     }
 25     public SaxForXmlHandler(String[] need)
 26     {
 27         this._needTag = need;
 28     }
 29     public SaxForXmlHandler(String tag,String[] need)
 30     {
 31         this._nodeTag = tag;
 32         this._needTag = need;
 33     }
 34     
 35     //獲取設置每個節點數據的標簽名稱
 36     public void setNodeTag(String tag)
 37     {
 38         this._nodeTag = tag;
 39     }
 40     public String getNodeTag()
 41     {
 42         return this._nodeTag;
 43     }
 44     
 45     //獲取設置包含數據的標簽名稱數組
 46     public void setNeedTag(String[] need)
 47     {
 48         this._needTag = need;
 49     }
 50     public String[] getNeedTag()
 51     {
 52         return this._needTag;
 53     }
 54     
 55     //獲得最終處理后的數據
 56     public ArrayList<Map<String,String>> getResult()
 57     {
 58         return this._notics;
 59     }
 60     
 61     //文檔開始
 62     @Override
 63     public void startDocument() throws SAXException {
 64         this._notics = new ArrayList<Map<String,String>>();
 65         this.preTag = null;
 66         this.current = null;
 67         if(this._nodeTag == null){
 68             throw new IllegalArgumentException("節點標簽名稱未賦值");
 69         }else if(this._needTag == null){
 70             throw new IllegalArgumentException("數據標簽數據未賦值");
 71         }
 72         super.startDocument();
 73     }
 74     
 75     //節點開頭
 76     @Override
 77     public void startElement(String uri, String localName, String qName,
 78             Attributes attributes) throws SAXException {
 79         if(_nodeTag.equals(localName)){
 80             //實例化一個Map對象
 81             current = new HashMap<String,String>();
 82         }
 83         //將當前處理的標簽名稱保存至preTag中
 84         preTag = localName;
 85     }
 86     
 87     //節點中的文本
 88     @Override
 89     public void characters(char[] ch, int start, int length)
 90             throws SAXException {
 91         //提取標簽中的文本
 92         String data = new String(ch,start,length);
 93         String dedata = "";
 94         for(String item : this._needTag)
 95         {
 96             if(item.equals(preTag))
 97             {
 98                 try {
 99                     //將數據進行URL解碼
100                     dedata = URLDecoder.decode(data,"UTF-8");
101                 } catch (UnsupportedEncodingException e) {
102                     dedata = data;
103                 }finally{
104                     //將當前的數據放入map對象中
105                     current.put(item, dedata);
106                 }
107                 return;
108             }
109         }
110     }
111 
112     //節點結束
113     @Override
114     public void endElement(String uri, String localName, String qName)
115             throws SAXException {
116         if(this._nodeTag.equals(localName))
117         {
118             //將當前map對象放入ArrayList對象中
119             this._notics.add(current);
120             current = null;
121         }
122         //將當前標簽設置為null
123         preTag = null;
124     }
125     
126     //文檔結束
127     @Override
128     public void endDocument() throws SAXException {
129         current = null;
130         preTag = null;
131         super.endDocument();
132     }
133 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM