Android初級開發(九)——網絡交互—解析XML格式數據

一、前言

首先我們先搭建一個web服務器,我這裏用的是tomcat,搭建過程可參見tomacat服務器的搭建:http://blog.csdn.net/qq_28585471/article/details/77449526。然後在這個服務器下提供一段XML文本,然後,我們在這個程序裏去訪問這個服務器,再對得到的XML文本進行解析。

這裏寫圖片描述
文本內容爲:
這裏寫圖片描述

我們可以在網頁中輸入地址預覽一下:

這裏寫圖片描述

預覽成功說明tomcat成功連接,且文本設置正確。

二、 PULL解析
我們在OkHttp的項目上進行修改,佈局文件不用變,修改MainActivity.java就可以

public class MainActivity extends AppCompatActivity {

    Button sendRequest;
    TextView responseText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        responseText = (TextView) findViewById(R.id.response_text);
        sendRequest = (Button) findViewById(send_request);
        sendRequest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try{
                            OkHttpClient client = new OkHttpClient();
                            //將HTTP請求的地址改爲http://10.0.2.2:8080/zwj/zwj.xml
                            //模擬器是連接不到localhost的,10.0.2.2對於模擬器來說就是電腦本機的IP地址
                            Request request = new Request.Builder().url("http://10.0.2.2:8080/zwj/zwj.xml").build();
                            Response response = client.newCall(request).execute();
                            String responseData = response.body().string();
                            //得到服務器返回的數據後,調用parseXMLWithPull()方法解析服務器返回的數據
                            parseXMLWithPull(responseData);
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        });
    }

    private void parseXMLWithPull(String xmlData) {
        try{
            //首先獲取一個XmlPullParserFactory實例
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            //藉助這個XmlPullParserFactory實例得到XmlPullParser對象
            XmlPullParser xmlPullParser = factory.newPullParser();
            //調用XmlPullParser的setInput()方法將服務器返回的XML數據設置進去
            xmlPullParser.setInput(new StringReader(xmlData));
            //開始解析
            //通過getEventType得到當前的解析事件
            int eventType = xmlPullParser.getEventType();
            String id = "";
            String name = "";
            String version = "";
            //在一個while循環中不斷地進行解析
            //如果當前的解析事件不等於XmlPullParser.END_DOCUMENT,說明解析工作還未完成,調用next()方法後獲取下一個解析事件
            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();
                        }else if ("version".equals(nodeName)){
                            version = xmlPullParser.nextText();
                        }
                        break;
                    }
                    //完成解析某個節點
                    case XmlPullParser.END_TAG:{
                        if("app".equals(nodeName)){
                            Log.d("MainActivity","id is" + id);
                            Log.d("MainActivity","name is" + name);
                            Log.d("MainActivity","version is" + version);
                        }
                        break;
                    }
                    default:
                        break;
                }
                eventType = xmlPullParser.next();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

看一下打印的日誌:
這裏寫圖片描述

解析成功啦~
那就再看一下SAX解析吧!


三、SAX解析
1、首先新建個ContentHandler類繼承自DefaultHandler,並重寫父類的5個方法

public class ContentHandler extends DefaultHandler {

    private String nodeName;
    private StringBuilder id;
    private StringBuilder name;
    private StringBuilder version;


    /**
     * 在開始XML解析的時候調用
     * @throws SAXException
     */
    @Override
    public void startDocument() throws SAXException {
        id = new StringBuilder();
        name = new StringBuilder();
        version = new StringBuilder();
    }

    /**
     * 在開始解析某個節點的時候調用
     * @param uri
     * @param localName
     * @param qName
     * @param attributes
     * @throws SAXException
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        //記錄當前節點名
        nodeName = localName;
    }

    /**
     * 在獲取節點內容的時候調用
     * @param ch
     * @param start
     * @param length
     * @throws SAXException
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        //根據當前的節點名判斷內容添加到哪一個StringBulider對象中
        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);
        }
    }

    /**
     * 在完成解析某個節點的時候調用
     * @param uri
     * @param localName
     * @param qName
     * @throws SAXException
     */
    @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);
        }
    }

    /**
     * 在完成整個XML解析的時候調用
     * @throws SAXException
     */
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }
}

這裏我們首先給id,name,version節點分別定義了一個StringBuilder對象,並在startDocument()方法裏對它們進行了初始化;每當開始解析某個節點的時候,startElement()方法就會得到調用,其中localName參數記錄着當前節點的名字。接着在解析節點中具體內容的時候就會調用character()方法,然後我們根據當前節點名進行判斷、將解析出的內容添加到哪一個StringBuilder對象中。最後在endElement()方法中進行判斷,如果app節點已經解析完成,就打印出id,name,version的內容。打印完成後,要將StringBuilder的內容清空掉。

2、修改MainActivity.java

public class MainActivity extends AppCompatActivity {

    Button sendRequest;
    TextView responseText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        responseText = (TextView) findViewById(R.id.response_text);
        sendRequest = (Button) findViewById(R.id.send_request);
        sendRequest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try{
                            OkHttpClient client = new OkHttpClient();
                            //將HTTP請求的地址改爲http://10.0.2.2:8080/zwj/zwj.xml
                            //模擬器是連接不到localhost的,10.0.2.2對於模擬器來說就是電腦本機的IP地址
                            Request request = new Request.Builder().url("http://10.0.2.2:8080/zwj/zwj.xml").build();
                            Response response = client.newCall(request).execute();
                            String responseData = response.body().string();
                            //得到服務器返回的數據後,調用parseXMLWithPull()方法解析服務器返回的數據
                            parseXMLWithSAX(responseData);
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        });
    }

    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()方法來解析XML數據,首先創建一個SAXParserFactory對象,然後再獲取到XMLReader對象,接着將ContentHandler實例設置到XMLReader中,最後調用parse()方法開始執行解析。

3、看一下logcat中的日誌
這裏寫圖片描述

和PULL解析一樣的效果~~解析成功!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章