Android笔记之网络编程—初识解析XML数据

我所学到的任何有价值的知识都是由自学中得来的。—— 达尔文

小弟初学安卓,该文算是小弟的学习过程,课后笔记与一些自己的思考,希望在自己的自学路上留下印记,也许有一些自己想的不对的地方,希望各位前辈斧正。

在网络中,数据的传输格式并不是随心所欲的,当我们想向服务器端传输数据或是从服务器端获取数据,这些数据都必须是格式化后的数据。这些数据有一定的结构规格和语义,任何一个接收数据方都必须对其进行解析才能获得他们想要得到的数据。

网络传输的数据有两种常见的格式:XML(可扩展标记语言)和JSON(JavaScript Object Notation,是一种轻量级的数据交换格式)

如何解析XML


首先我写了一个简易的XML文件:

<?xml version="1.0" encoding="UTF-8" ?>
<web>
    <item id="0" url="http://www.baidu.com">百度</item>
    <item id="1" url="http://www.taobao.com">淘宝</item>
</web>

1.SAX解析

SAX解析方法是一种高效的解析方法,它逐行扫描文档,边扫描边解析两不误。
  
  首先要新建一个类来继承DefaultHandler类,我重写了:

  • startDocument()
  • endDocument()
  • startElement(String uri, String localName, String qName, Attributes attributes)
  • characters(char[] ch, int start, int length)
  • endElement(String uri, String localName, String qName)

startDocument()就是整个文档(XML)解析前执行的方法,而endDocument()相反为解析后执行的方法。

startElement就开始动真格的了,Element意为元素,元素应该就如上面XML文件中的<web>内容</web>、<item...>内容</item>,这个方法就是各个元素进行解析,参数中uri是资源标识符,而这个localName是这个元素的元素名(元素又和标签不同,元素是由开始标签与结束标签组成并包含一些内容(content)的,单独的<web>、</web>才叫标签)。第三个参数qName暂时没用到,它应该是带前缀的localName即 “前缀:+localName” ,才疏学浅说不清楚所以推荐一下别人博客的讲解:[QName]。而attributes就是属性,如上面代码中,开始标签ITEM里的“id”、“url”就是其属性。(注意startElement是会多次执行的,每条元素都会执行一次

characters方法则是在解析元素所含内容时执行,比如上面代码中的“百度”、“淘宝”,第一个参数的字符数组,这个数组大家可以自己遍历一下它并不单单是元素内容的数组,所以第二个参数start才是内容在数组中开始的位置,而length不是数组的长度而是这段元素内容的长度。

endElement是解析结束后执行。

以下是自定义的WebUrl类 和 SAXParseHandler类(extends DefaultHandler )
**WebUrl类 **

package com.qdf.geekband_sixth_week.XML;


public class WebURL {
    private int mID;
    private String mUrl;
    private String mContent;

    public int getID() {
        return mID;
    }

    public void setID(int ID) {
        mID = ID;
    }

    public String getUrl() {
        return mUrl;
    }

    public void setUrl(String url) {
        mUrl = url;
    }

    public String getContent() {
        return mContent;
    }

    public void setContent(String content) {
        mContent = content;
    }
}


SAXParseHandler类

package com.qdf.geekband_sixth_week.XML;

import android.text.TextUtils;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.util.ArrayList;
import java.util.List;


public class SAXParseHandler extends DefaultHandler {

    List<WebURL> mWebURLs;
    WebURL mWebURL;
    boolean state = false;

    @Override
    public void startDocument() throws SAXException {
        //开始解析整个文档前
        super.startDocument();
        mWebURLs = new ArrayList<>();
    }

    @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);
        mWebURL = new WebURL();
        if (TextUtils.equals(localName, "item")) {
            for (int i = 0; i < attributes.getLength(); i++) {
                if (TextUtils.equals(attributes.getLocalName(i), "id")) {
           //attributes.getLocalName(i)是获取属性名
                    mWebURL.setID(Integer.parseInt(attributes.getValue(i).trim()));
                } else if (TextUtils.equals(attributes.getLocalName(i), "url")) {
                    mWebURL.setUrl(attributes.getValue(i).trim());
                }
            }
            state = true;
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        //元素解析后
        super.endElement(uri, localName, qName);
        if (TextUtils.equals(localName, "item")) {
            mWebURLs.add(mWebURL);
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        //characters()方法会在获取结点中内容的时候调用
        super.characters(ch, start, length);
        String content = new String(ch, start, length);
        if (state) {
            mWebURL.setContent(content);
            state = false;
        }
    }

    public List<WebURL> getXMLList() {
        return mWebURLs;
    }
}


首先,这个WebUrl里只有三个私有变量和它们的get和set方法,看变量名大家可以知道,我要将XML文件解析元素获得的属性id、url和内容content放入WebUrl的对象,一条元素做一个对象。

而在SAXParseHandler类中startElement方法,我先判断元素名,若元素名为“item”则继续遍历属性,attributes.getLength()为元素属性的数量,attributes.getLocalName()则是获得属性名,判断属性名并获得属性值的值并add()到我们的WebURL对象中。

characters方法中,我则是直接将元素包含的内容添加进WebURL对象,设置了一个布尔值state用来判断当时解析的元素名是不是指定的元素名,是的话为true才添加内容至WebURL对象。

最后endElement方法中,我们将WebURL对象添加到List<WebURL> mWebURLs集合中。我们这有两个元素,所以集合中有两个WebURL对象。这里还提供了个公共方法getXMLList()来让别的类获取到这个集合。

现在我们就来实验检测结果吧,我将这个本地xml文件方法了资源文件夹的raw文件夹中,然后我们在一个按钮的点击监听事件中解析xml吧。

代码如下:

SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();//获取XMLReader实例
SAXParseHandler saxParseHandler = new SAXParseHandler();
xmlReader.setContentHandler(saxParseHandler);
InputStream inputStream = getResources().openRawResource(R.raw.test);
InputSource inputSource = new InputSource(inputStream);
xmlReader.parse(inputSource);
saxParseHandler.getXMLList();

可以看到我们解析XML的主角是XMLReader,而我们要将我们的SAXParseHandler处理类对象设置给它,最后才是个完整的自定义解析器。

这里说一下,不管是从本地还是来自网络的数据,我们都要先将其转为输入流的形式来处理,这里可以看到我们将xml文件读入流,并转为InputSource对象(输入源)给XMLReader 解析,这个方法最后获得了集合,而我们通过集合各WebURL对象的get方法来获得我们要的数据,如下Log输出。

Log输出
2.PULL解析

PULL方法解析相对简单,但必须在线程中执行。

⑴解析本地的xml文件
  先获取XmlResourceParser对象并获得了xml资源,通过 getEventType()可以得到当前的解析事件,然后在循环中不断地进行解析(有些类似SAX解析各个元素),如果当前的解析事件不为 XmlResourceParser.END_DOCUMENT,说明解析工作还没完成,调用 next()方法后可以获取下一个解析事件。

new Thread(new Runnable() {
    @Override
    public void run() {
        XmlResourceParser xmlResourceParser = getResources().getXml(R.xml.test);
        try {
            while (xmlResourceParser.getEventType() != XmlPullParser.END_DOCUMENT) {
                //若文档未结束 则一直进行循环
                if (xmlResourceParser.getEventType() == XmlPullParser.START_TAG) {
                    String tagName = xmlResourceParser.getName();
                    if (TextUtils.equals(tagName, "item")) {
                        String id = xmlResourceParser.getAttributeValue(0);
                        String url = xmlResourceParser.getAttributeValue(1);
                        String content=xmlResourceParser.nextText();
                        Log.i("Pull", "id: " + id + "  url: " + url+" content: "+content);
                    }
                }
                xmlResourceParser.next();
            }
        } catch (XmlPullParserException | IOException e) {
            e.printStackTrace();
        }
    }
}).start();

⑵解析网络的xml(可能说的不对)
  解析步奏大致相同,但获取的是XmlPullParser对象如下,而最后xmlPullParser.setInput()方法有两种传参,一种是Reader in,一种是InputStream inputStream (输入流),String inputEncoding(编码)。下面代码中的xmlData为转换为字符串的xml文档。

XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(xmlData));

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容