Android-DOM、SAX、PULL解析网络xml

第一个例子是解析网络上的xml文件

我们要先把网络环境搭配好,具体操作在前面的博客里面已经介绍了,这里就不多说了

然后就是我们的互联网权限

<!--互联网的权限-->
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
解析xml,我们先写一个布局文件,一个按钮,加一个点击事件就行

 <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="解析xml"
        android:onClick="parser"
        />

在Activity中,我们记得把原本写在点击事件里面的代码,写在我们的子线程中去,因为在Android4.0之后,所有耗时的操作都必须写在子线程中,不然就会报一个错.NetWorkOnMainThreadException,通常报这样的错时,都是因为我们把耗时的操作写在了主线程中,所有,一定要记得


现在我们来看完整的源码:

public class ParserJsonActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_parser_json);
    }


    public void parser(View view){
       new MyTask().execute();

    }

    //android 4.0之后,所有的耗时操作,都必须写在子线程中
    //线程的通信机制 子线程+Handle
    //异步任务类 AsyncTask
    class MyTask extends AsyncTask{

        @Override
        protected Object doInBackground(Object[] params) {
            //01获取网络xml数据
            try {//输在浏览器上的地址
                URL url=new URL("http://192.168.1.100/person.xml");
                //相当于按下回车键
                HttpURLConnection connection= (HttpURLConnection) url.openConnection();
                //设置请求方式  post get
                connection.setRequestMethod("GET");
                //设置请求连接超时的时间(优化,在网络比较慢的情况下,没有设置这个时间的话,会一直在请求数据,消耗我们的资源,但是又拿不到,就会出现白花花的一片,)
                connection.setConnectTimeout(5000);
                //结果码 成功:200  未修改:304
                //获取结果码
                int code=connection.getResponseCode();
                if(code==200){
                    //获取服务器返回过来的结果  ,无论什么都会用流的方式返回过来
                    InputStream inputStream=connection.getInputStream();
                    //打印(读)
                    BufferedReader br=new BufferedReader(new InputStreamReader(inputStream));
                    String str=null;
                    while((str=br.readLine())!=null){
                        Log.i("test",str);
                    }
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Object o) {
            super.onPostExecute(o);
        }
    }
}

运行之后,我们就能在控制台上看到我们解析网络上的xml内容


然后我们第一种,通过DOM解析xml

DOM解析xml,是把整个xml文档当成一个对象来处理,会先把整个文档读入到内存里,通常需要加载整文档和结构DOM 树(所以这样也比较耗内存),然后才能开始工作,但是DOM解析也有它的好处,DOM技术可以让用户页面动态的变化,使得页面的交互性大大的增强。我们在下面的代码中就可以体会到

//01 使用Dom解析(占内存,因为要解析流)
                    DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();
                    DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
                    Document document=documentBuilder.parse(inputStream);
                    //获取根标签
                    Element root=document.getDocumentElement();
                    Log.i("test","根标签"+root.getNodeName());
                    //获取<persons>下面的所有子标签<person>
                    NodeList nodeList=root.getElementsByTagName("person");
                    for (int i = 0; i <nodeList.getLength() ; i++) {
//                        Log.i("test",)
                        //获取单个
                        Element PersonElement= (Element) nodeList.item(i);
                        //获取<person>属性的id
                        String id=PersonElement.getAttribute("id");
                        Log.i("test",id);
                        //获取<person>下面子标签的<name><age><image>
                        Element nameElement= (Element) PersonElement.getElementsByTagName("name").item(0);
                        String name=nameElement.getTextContent();
                        Element ageElement= (Element) PersonElement.getElementsByTagName("age").item(0);
                        String age=nameElement.getTextContent();
                        Element imageElement= (Element) PersonElement.getElementsByTagName("image").item(0);
                        String image=nameElement.getTextContent();
                        Log.i("test",name+"--"+age+"--"+image);
                    }
只要把这一段代码替换打印后面的那些代码就可以了


第二种解析,SAX解析

SAX是一个用于处理XML事件驱动的“推”模型,优点是解析速度快并且占用的内存少,它需要哪些数据再去加载和解析。缺点就是它不会记录标签的关系,而让你的应用程序自己处理,这样就增加了你程序的负担,具体的我们来看代码


      //02.SAX(边读边解析,基于事件(方法)驱动方式)
                    SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();
                    SAXParser saxparser=saxParserFactory.newSAXParser();

                    saxparser.parse(inputStream,new DefaultHandler(){
                        @Override//这些方法都是自动调用
                        public void startDocument() throws SAXException {
                            super.startDocument();
                        }

                        @Override
                        public void endDocument() throws SAXException {
                            super.endDocument();
                        }

                        @Override//开始标签
                        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
                            super.startElement(uri, localName, qName, attributes);
                            currentTag=localName;
                            //获取开始标签的名字
                            if("person".equals(localName)){
                                //取属性的值
                                String id=attributes.getValue(0);
                                Log.i("test",id);
                            }
                        }


                        @Override
                        public void endElement(String uri, String localName, String qName) throws SAXException {
                            super.endElement(uri, localName, qName);
                            currentTag=null;//如果不赋为空,就会多打印出两行空的值,因为一路下来循环赋值的原因
                        }

                        @Override//正文
                        public void characters(char[] ch, int start, int length) throws SAXException {
                            super.characters(ch, start, length);
                            if("name".equals(currentTag)){
                                //获取<name>的值
                                String name=new String(ch,start,length);
                                Log.i("test",name);
                            }else if("age".equals(currentTag)){
                                //获取<name>的值
                                String age=new String(ch,start,length);
                                Log.i("test",age);
                            }else if("image".equals(currentTag)){
                                //获取<name>的值
                                String image=new String(ch,start,length);
                                Log.i("test",image);
                            }
                        }
                    });


第三种,PULL解析

PULL解析器的运行方式和SAX类似,它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相对应的事件。和SAX不同的是,PULL解析器产生的事件是一个数字,而非方法,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个next类型节点的值,pull解析速度也是非常快的,又小巧轻便,所以在Android官方文档中,都是推荐开发者们使用pull解析技术


 //03.PULL解析
                    XmlPullParser xmlPullParser= Xml.newPullParser();
                    xmlPullParser.setInput(inputStream,"UTF-8");

                    //获取解析的标签的类型
                    int type=xmlPullParser.getEventType();
                    while (type!=XmlPullParser.END_DOCUMENT){
                        switch (type){
                            case XmlPullParser.START_TAG:
                                //获取开始标签的名字
                                String starttagName=xmlPullParser.getName();
                                if("person".equals(starttagName)){
                                    //获取id的值
                                    String id=xmlPullParser.getAttributeName(0);
                                    Log.i("test",id);
                                }else if("name".equals(starttagName)){
                                    String name=xmlPullParser.nextText();
                                    Log.i("test",name);
                                }else if("age".equals(starttagName)){
                                    String age=xmlPullParser.nextText();
                                    Log.i("test",age);
                                }else if("image".equals(starttagName)){
                                    String image=xmlPullParser.nextText();
                                    Log.i("test",image);
                                }
                                break;
                            case XmlPullParser.END_TAG:
                                break;
                        }
                        //细节
                        type=xmlPullParser.next();
                    }


总结
DOM方式最直观和容易理解,但是只适合XML文档较小的时候使用,而SAX方式更适合在移动终端系统中使用,因为相比DOM占用内存少,适合处理比较大的XML文档,最后的Pull方式使用场合和SAX类似,但是更适合需要提前结束XML文档解析的场合。

SAX是一个用于处理XML事件驱动的“推”模型, 
优点是一种解析速度快并且占用内存少的xml解析器,它需要哪些数据再加载和解析哪些内容。 
缺点是它不会记录标签的关系,而要让你的应用程序自己处理,这样就增加了你程序的负担。

Pull解析和Sax解析很相似,Pull解析和Sax解析不一样的地方是pull读取xml文件后触发相应的事件调用方法返回的是数字,还有pull可以在程序中控制想解析到哪里就可以停止解析。

猜你喜欢

转载自blog.csdn.net/qiuqiu_qiuqiu123/article/details/55252796