Android 之xml解析

Android 之xml解析

在网络上传输数据常用的格式有xml还有json。
常见的xml解析方式有Pull解析,SAX解析以及DOM解析。在Android中一般采用的是Pull解析以及SAX解析。

三种解析简述

  1. SAX(Simple API for XML) 使用流式处理的方式。它是一种基于事件模型的XML API,解析速度快,占用内存少。使用回调函数来实现。 缺点是不能倒退
  2. DOM(Document Object Model)一种用于XML文档的对象模型,可用于直接访问XML文档的各个部分。它是一次性全部将内容加载在内存中,生成DOM树。 缺点是加载大文档时效率低下。
  3. Pull与SAX有点类似,都提供了类似的事件,如开始元素和结束元素。不同的是,SAX的事件驱动是回调相应方法,需要提供回调的方法,而后在SAX内部自动调用相应的方法。而Pull解析器并没有强制要求提供触发的方法。因为他触发的事件不是一个方法,而是一个数字。它使用方便,效率高。

SAX和Pull解析区别

SAX解析器的工作方式是自动将事件推入注册的事件处理器处理,不能控制事件主动结束,会对整一个文档进行解析。pull的解析解析器允许代码出动从解析器获取事件,允许主动中断事件。

pull解析步骤

  1. 获取XmlPullParserFactory对象
  2. 通过XmlPullParserFactoru得到XmlParser对象
  3. 调用XmlPullParser对象的setInput方法将服务器的Xml数据进行解析
  4. 获取当前解析对象,指导解析事件为XmlPullParser.END_DOCUMENT,解析完成
            /**
             * Pull解析
             * @param xmlData
             */

            private void parseXMLWithPull(String xmlData) {
                try {
//                    获取XmlPullParserFactory对象
                    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//                    通过XmlPullParserFactoru得到XmlParser对象
                    XmlPullParser xmlPullParser = factory.newPullParser();
//                    调用XmlPullParser对象的setInput方法将服务器的Xml数据进行解析
                    xmlPullParser.setInput(new StringReader(xmlData));
//                    获取当前解析事件
                    int eventType = xmlPullParser.getEventType();
                    String id = "";
                    String name = "";
                    while (eventType != XmlPullParser.END_DOCUMENT){
                        String nodeName = xmlPullParser.getName();
                        switch (eventType){
                            case XmlPullParser.START_TAG:{
                                if ("id".equals(nodeName)){
                                    id = xmlPullParser.nextText();
                                } else if ("name".equals(nodeName)){
                                    name = xmlPullParser.nextText();
                                }
                                break;
                            }
                            case XmlPullParser.END_TAG:{//结束标志
                                if("app".equals(nodeName)){
                                    Log.d("ok", "id is " + id);
                                    Log.d("ok", "name is " + name);
                                }
                            }
                            default:
                                break;
                        }
                        eventType = xmlPullParser.next();
                    }
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }).start();
    }

pull是最常用也是最方便使用的xml的解析方式

SAX解析步骤

  1. 创建继承于DefaultHander类的处理类
  2. 创建SAXparserFactory对象
  3. 获取XMLReader对象
  4. 将新建的处理类放置到XMLReader中
  5. 通过parse()方法进行解析
    public class SaxHandler extends DefaultHandler {
    private StringBuilder id ;
    private StringBuilder name;
    private String nodeName;

    @Override
//    在开始XML解析的时候会调用
    public void startDocument() throws SAXException {
        id = new StringBuilder();
        name = new StringBuilder();
    }
//    在开始解析某个结点的时候会调用
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        nodeName = localName;
    }
//    在获取某个结点内容的时候会调用
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if ("id".equals(nodeName)){
            id.append(ch,start,length);
        } else if ("name".equals(nodeName)){
            name.append(ch, start, length);
        }
    }
//    在完成某个节点内容的时候会调用
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if ("app".equals(localName)){
            Log.d("ok", "id is" + id.toString().trim());
            Log.d("ok", "name is" + name.toString().trim());
            id.setLength(0);
            name.setLength(0);
        }
    }
//        在完成某个XML文件解析的时候调用
    @Override
    public void endDocument() throws SAXException {
    }
}

以上是第一步,创建继承DefaultHander的处理类

 private void paresXMLWithSAX(String xmlData) {
        try{
//            获取SAXParserFactory对象
            SAXParserFactory factory = SAXParserFactory.newInstance();
//            获取XMLReader对象
            XMLReader xmlReader = factory.newSAXParser().getXMLReader();
//            将新建的处理类放入XMLReader中
            SaxHandler handler = new SaxHandler();
            xmlReader.setContentHandler(handler);
//            通过parse方法进行解析
            xmlReader.parse(new InputSource(new StringReader(xmlData)));
        } catch (Exception e){
            e.printStackTrace();
        }
    }

DOM解析步骤

  1. 创建DocumentBuilderFactory对象
  2. 获取DocumentBuilder对象
  3. 获取根节点root
  4. 对DOM进行遍历解析
    /**
     * xmlData为xml文件的数据流
     * @param xmlData
     */
    private void parasXMLWithDOM(InputStream xmlData) {
//        创建DOcumentBuilderFactory对象
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
//            创建DocumentBuilder对象
            DocumentBuilder documentBuilder = factory.newDocumentBuilder();
//            解析xml文件
            Document document = documentBuilder.parse(xmlData);
//            获取文件的根节点
            Element root = document.getDocumentElement();
            NodeList personNodes =  root.getElementsByTagName("app");
//            遍历DOM树
            for (int i = 0;i < personNodes.getLength();i++){
                Element personElement = (Element) personNodes.item(i);
                NodeList chileNodes = personElement.getChildNodes();
                for (int y = 0;y < chileNodes.getLength();y++){
                    if (chileNodes.item(y).getNodeType() == Node.ELEMENT_NODE){
                        if ("id".equals(chileNodes.item(y).getNodeName())){
                            String id = chileNodes.item(y).getFirstChild().getNodeValue();
                            Log.d("ok", "id is " + id);
                        } else if ("name".equals(chileNodes.item(y).getNodeName())){
                            String name = chileNodes.item(y).getFirstChild().getNodeValue();
                            Log.d("ok","name is "+ name);
                        }
                    }
                }
            }
            xmlData.close();

        } catch (Exception e){
            e.printStackTrace();
        }
    }

当然在遍历DOM树的时候也能通过递归的方式进行遍历


最后尽然忘记了,以上只给了函数的主体,解析的xml文件为

<apps>
    <app>
        <id>i</id>
        <name>first</name>
    </app>
    <app>
        <id>2</id>
        <name>second</name>
    </app>
</apps>

传入参数的方式为

private void sendRequsetWithHttpURLConnection() {
//        开启线程发起网络请求
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                String path = "http://10.0.2.2/get_data.xml";
                try{
                    URL url = new URL(path);
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    InputStream in = connection.getInputStream();

                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder iresponse = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null){
                        iresponse.append(line);
                    }
                    String response = iresponse.toString();
                //pull解析
                    parseXMLWithPull(response);
                } catch (Exception e){
                    e.printStackTrace();
                } finally {
                    if(connection != null){
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

这里偷懒使用了以前的代码,通过服务器的方式传递参数,如果进行DOM的话,直接将inputStream传进去就好啦~
(当然xml解析还有很多种方式,像JDOM,DOM4J等,只是Android不经常用而已)

发布了36 篇原创文章 · 获赞 8 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_32763643/article/details/75082274