zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    UVa 1451 Average (斜率优化)
    POJ 1160 Post Office (四边形不等式优化DP)
    HDU 3507 Print Article (斜率DP)
    LightOJ 1427 Substring Frequency (II) (AC自动机)
    UVa 10245 The Closest Pair Problem (分治)
    POJ 1741 Tree (树分治)
    HDU 3487 Play with Chain (Splay)
    POJ 2828 Buy Tickets (线段树)
    HDU 3723 Delta Wave (高精度+calelan数)
    UVa 1625 Color Length (DP)
  • 原文地址:https://www.cnblogs.com/yaozhenfa/p/np_android_DefaultHandler.html
Copyright © 2011-2022 走看看