• PULL解析学习


    学习过程
     
    安卓中有三种对XML解析的方式,这个众所周知,DOM,SAX,PULL
    其中被推荐的方法是PULL,说是非常简单,但从一开始接触就觉得比较迷惑,总是云里雾里的感觉,甚至在自己写出了一个能用的代码, 我也解释不了为什么能用,也害怕去改,虽然有过几次小小的突击学习理解,但是没有什么进展
    直到这次我花了点心思和时间准备搞一搞,才有了通关性进展
     
    在开始研究并查看一些资料的时候,当我看到一篇文章里边介绍了 5种解析事件的时候眼睛一亮,以为自己找到了理解的关键
    但是在我继续往下理解的时候,发现那种生疏的感觉一点没少,感觉解析事件是关键,于是就继续找关于它的更多资料
     
    但是找了半天发现关于PULL解析事件的资料很少,另一方面我又了解到PULL是SAX的接替者,原理是差不多的,于是我又去找了SAX的解析事件相关的东西,可惜还是很少,然后之后不小心又找到DOM去了,DOM的事件类型庞大无比,看了一会感觉没什么用,就放弃了
     
    直到最后看到一篇不错的博文,然后又加上自己的分析,终于理解了问题的关键,就是:你得给我解释,那五种解析事件在一个XML文档中是在什么地方啊,你光说有五种事件怎么行。于是到最后我终于完全搞定了这块,并且重构了我的解析工具代码。
     

    PULL解析理解
     
    PULL是顺序扫描XML的每一行,并且根据扫描到的事件来做出不同的行为
     
    PULL一共有5种事件类型:
        * START_DOCUMENT:文档的开始,解析器尚未读取任何输入。
        * START_TAG:开始标签的解析。
        * TEXT:标签内元素的内容解析。
        * END_TAG:结束标签的解析。
        * END_DOCUMENT:文档的结束。
     
    主要用的是4个,他们与XML文件相应内容是这么对应的(他们在XML文件中的位置是这样)
     
    简单总结就是:
    1. 文档的开头和结束分别有文档开始和文档结束事件
    2. 文档中的每个节点,无论是根节点还是叶子节点,都在节点开始和节点结束的地方有事件
     
    具体使用的建议:
    1. 文档开始和文档结束事件是有固定位置的,你只要在这个位置做你要做的事情就好了,比如初始化一些资源
    2. 节点开始和节点结束的事件在很多位置都可能发生,为了精确控制,你可以使用【获取他们的节点名称(name)进行判断】这一方法
     

    三种解析方式对比
     
    JAVA 解析 XML 通常有两种方式:DOM 和SAX(PULL)
    1. DOM
      1. DOM是结构化解析,会在内存中维护一个完整的XML的树状结构,开销大,对某些复杂需求可能比较方便
      2. XML DOM 是 XML Document Object Model 的缩写,即 XML 文档对象模型。DOM(文档对象模型)是W3C标准,提供了标准的解析方式,但其解析效率一直不尽如人意,这是因为DOM解析XML文档时,把所有内容一次性的装载入内存,并构建一个驻留在内存中的树状结构(节点数)。如果需要解析的XML文档过大,或者我们只对该文档中的一部分感兴趣,这样就会引起性能问题。
      3. 它有一个非常庞大的事件库
    2. SAX(PULL)
      1. SAX和PULL的原理是一样的,都不维护什么完整的结构,而是逐行扫描,不保存结构关系,开销小,适合简单的需求
      2. (两者区别是,SAX使用回调的方式实现,PULL使用switch case的方式实现)
      3. SAX是事件驱动型XML解析的一个标准接口,SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。
     

    示例代码
     
    上图中XML的解析方法:
    public static List<EleTimeValue> parseToETVL(String xmlData) {
            
            //在这新建变量,万一try没有的话,还能返回null
            List<EleTimeValue> lists=null;  
            EleTimeValue eTV=null; 
            String value = "";
            String time ="";
            float valuef = 0;
            Date timed = null;
            
            SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
            
            try {
                
                XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
                XmlPullParser xmlPullParser = factory.newPullParser();
                xmlPullParser.setInput(new StringReader(xmlData));
                
                int eventType = xmlPullParser.getEventType();
                
                while (eventType != XmlPullParser.END_DOCUMENT) {
                    
                    String nodeName = xmlPullParser.getName();
                    
                    switch (eventType) {
                        
                    //用eventType来控制什么时候开始解析某个结点
                    case XmlPullParser.START_DOCUMENT:  
                        lists=new ArrayList<EleTimeValue>();  
                        break; 
                    
                    //碰到STARTTAG之后开始一行行(eventtype可以当做行号)输入下面的ifelse语句中进行判断,不符合就跳出switch,并且在后边把行号加1,然后继续while循环
                    case XmlPullParser.START_TAG: 
                        
                        //增加一个错误检测,当解析内容时候发现errcode不为0的时候,直接结束解析,跳出swith,也跳出while,直接返回null
                        //这里传不出msg
                        if ("ErrCode".equals(nodeName) && !xmlPullParser.nextText().equals("0") ){    
                            Log.d("t", "Null,要返回");
                            return null;
                        }else if("RegValue".equals(nodeName)) {
                            eTV = new EleTimeValue();
                        }else if("Value".equals(nodeName)) {
                            value = xmlPullParser.nextText();
                            valuef = Float.valueOf(value).floatValue()/10;
                            eTV.setValue(valuef); 
                        }else if("DevTime".equals(nodeName)) {
                            time = xmlPullParser.nextText();
                            try { 
                                timed = ft.parse(time); 
                            } catch (ParseException e) {
                                System.out.println("Unparseable using " + ft); 
                            }
                            eTV.setDate(timed); 
                        } 
                        break;
                    
                    // 完成解析某个结点
                    case XmlPullParser.END_TAG: 
                        if ("Reg".equals(nodeName)||"RegValue".equals(nodeName)) {
                            lists.add(eTV);
                            eTV = null;
                        }
                        break;
    
                    }
                    eventType = xmlPullParser.next();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            return lists;
        }

    参考文章:

    http://baike.baidu.com/link?url=jyDUMCrvG56wJKcAxwDzBn6nuSy-m1yTxQCwNuT5N9Nu21crEkcibkg7DqOIZZGsDv4Mzi2gF48ak3EYAVVaMK
     
  • 相关阅读:
    10003 Cutting Sticks(区间dp)
    Cocos2d-x init() 和 onEnter() 区别
    HDU1181【有向图的传递闭包】
    空间参考系统与WKT解析
    面试经典-分金条
    uvalive 3971
    lua学习:使用Lua处理游戏数据
    面试经典--两个房间 每间房间三盏灯
    浙江大学PAT上机题解析之2-11. 两个有序链表序列的合并
    顺序队列之C++实现
  • 原文地址:https://www.cnblogs.com/bellkosmos/p/5333894.html
Copyright © 2020-2023  润新知