Android中通过SAX方式解析XML

    每个访问网络的应用程序都有一个自己的服务器,我们可以向服务器提交数据,也可以从服务器上获取数据。那么,这些数据是用什么格式在网络上传输的呢?一般,我们会在网络上传输一些格式化的数据,这些数据有一定的结构和语义。另一方收到数据消息后就可以按照相同的结构规格来进行解析,从而获取到想要的那部分内容。

  网络上传输数据最常用的格式有两种,XML和JSON。下面,我们介绍通过SAX方式来解析XML。

  首先,进行准备一段XML格式的数据。 get_data.xml

 1 <apps>    
 2     <app>
 3         <id></id>
 4         <name>Google Maps</name>
 5         <version>1.0</version>
 6     </app>
 7     <app>
 8         <id>2</id>
 9         <name>Chrome</name>
10         <version>2.1</version>
11     </app>
12     <app>
13         <id>3</id>
14         <name>Google Play</name>
15         <version>2.3</version>
16     </app>
17 </apps>

   我们搭建的服务器网址为:http://10.0.105.36/get_data.xml

   接下来通过HttpURLConnection方式来获取服务器上的内容,代码如下

private void sendRequestWithHttpURLConnection(){
        //开启线程来发送网络请求
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection=null;
                try {
                    URL url=new URL("http://10.0.105.36/get_data.xml");
                    connection= (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    //获取输入流
                    InputStream in=connection.getInputStream();
                    //对获取到的流进行读取
                    BufferedReader br=new BufferedReader(new InputStreamReader(in));
                    StringBuilder response=new StringBuilder();
                    String line;
                    while ((line=br.readLine())!=null){
                        response.append(line);
                    }
                      parseXMLWithSAX(response.toString()); //这里调用的是下文中parseXMLWithSAX()方法

                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    if (connection!=null){
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

 

 

    一般情况我们会新建一个类ContentHandler继承自DefaultHandler ,并重写父类的五个方法 ,如下:

  

package com.example.NetTest21;

import android.util.Log;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Created by Demon on 2015/1/18.
 */
public class ContentHandler extends DefaultHandler {
    private String nodeName;
    private StringBuilder id;
    private StringBuilder name;
    private StringBuilder version;
    @Override
    public void startDocument() throws SAXException {
        id=new StringBuilder();
        name=new StringBuilder();
        version=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 {
        //根据当前的节点名判断将内容添加到哪一个StringBuilder对象中
        if ("id".equals(nodeName)){
            id.append(ch,start,length);
        }else if ("name".equals(nodeName)){
            name.append(ch, start, length);
        }else if ("version".equals(nodeName)){
            version.append(ch, start, length);
        }
    }
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if ("app".equals(localName)){
            Log.d("ContentHandler","id is "+id.toString().trim());
            Log.d("ContentHandler","name is "+name.toString().trim());
            Log.d("ContentHandler","version is "+version.toString().trim());
            //最后将StringBuilder清空
            id.setLength(0);
            name.setLength(0);
            version.setLength(0);
        }
    }
    @Override
    public void endDocument() throws SAXException {

    }
}

 

    我们首先给id、name和version节点分别定义了一个StringBuilder对象,并在startDocument()方法中对它们进行了初始化。每当开始解析某个节点的时候,startElement()方法就会得到调用。其中localName参数记录着当前结点的名字,我们将它记录下来。接着在解析结点中具体内容的时候就会调用characters()方法,我们根据当前的结点名进行判断,将解析出的内容添加到哪一个StringBuilder对象中。最后在endElement()方法中进行判断,如果app结点已经解析完成,就打印出id name  和version的内容。注意,目前id、name和version中可能包括回车或换行符,因此在打印之前我们还需要调用一下trim()方法,并且打印完成后还要将StringBuilder的内容清空掉,不然会影响下一次内容的读取。

    接下来新建一个parseXMLWithSAX(String xmlData)方法 用来解析数据。

 private void parseXMLWithSAX(String xmlData){
        try{
            SAXParserFactory factory=SAXParserFactory.newInstance();
            XMLReader xmlReader=factory.newSAXParser().getXMLReader();
            ContentHandler handler=new ContentHandler();
            //将ContentHandler的实例设置到XMLReader中
            xmlReader.setContentHandler(handler);
            //开始解析
            xmlReader.parse(new InputSource(new StringReader(xmlData)));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

 

   parseXMLWithSAX()方法中先是创建了一个SAXParseFactory的对象,然后再获取到XMLReader对象,接着将我们编写的ContentHandler的实例设置到XMLReader中,最后调用parse()方法开始执行解析。

 

 ---------------------------------------------------------------------------

 ---------------------------------------------------------------------------

 

  文章来自于郭霖大神的《第一行代码》,转载请注明出处。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。