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 }
  • 相关阅读:
    Java多线程系列 JUC锁03 公平锁(一)
    Java多线程系列 JUC锁02 互斥锁ReentrantLock
    JDBC课程3--通过ResultSet执行查询操作
    JDBC课程2--实现Statement(用于执行SQL语句)--使用自定义的JDBCTools的工具类静态方法,包括insert/update/delete三合一
    JDBC_通过DriverManager获得数据库连接
    JDBC课程1-实现Driver接口连接mysql数据库、通用的数据库连接方法(使用文件jdbc.properties)
    [终章]进阶20-流程控制结构--if/case/while结构
    MySQL进阶19--函数的创建(举例)/设置mysql的创建函数的权限/查看(show)/删除(drop) / 举4个栗子
    MySQL进阶18- 存储过程- 创建语句-参数模式(in/out/inout-对应三个例子) -调用语法-delimiter 结束标记'$'- 删除/查看/修改-三个练习
    SQL进阶17-变量的声明/使用(输出)--全局变量/会话变量--用户变量/局部变量
  • 原文地址:https://www.cnblogs.com/yaozhenfa/p/np_android_DefaultHandler.html
Copyright © 2011-2022 走看看