对于xml文件,一般有两种解析方式:

-----pull解析--------

-----Sax解析-------

如果xml文件是本地文件,那么就好说了

AssetManager assetManager = getAssets();// 文件保存在assets目录下,得到assetManager管理器
                InputStream is;
                is = assetManager.open("citylist.xml");// 打开文件,得到输入流


如果xml文件是网络文件,就首先需要下载

URL url = new URL(blogurl);
        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
        InputStream in = urlConn.getInputStream();
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        sp.parse(in, this);


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

PULL解析

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

在android系统中,很多资源文件中,很多都是xml格式,在android系统中解析这些xml的方式,是使用pul解析器进行解析的,它和sax解析一样(个人感觉要比sax简单点),也是采用事件驱动进行解析的,当pull解析器,开始解析之后,我们可以调用它的next()方法,来获取下一个解析事件(就是开始文档,结束文档,开始标签,结束标签),当处于某个元素时可以调用XmlPullParser的getAttributte()方法来获取属性的值,也可调用它的nextText()获取本节点的值。

在我看来,有点像面向过程的,从根节点开始,一个节点一个节点的判断,获取元素值。比sax解析效率高。

// 构建XmlPullParserFactory
        try {
            XmlPullParserFactory pullParserFactory = XmlPullParserFactory
                    .newInstance();
            // 获取XmlPullParser的实例
            XmlPullParser xmlPullParser = pullParserFactory.newPullParser();
            // 设置输入流 xml文件
            xmlPullParser.setInput(inputstream, "UTF-8");
            // 开始
            int eventType = xmlPullParser.getEventType();

            try {
                while (eventType != XmlPullParser.END_DOCUMENT) {
                    String nodeName = xmlPullParser.getName();
                    switch (eventType) {
                    // 文档开始
                    case XmlPullParser.START_DOCUMENT:
                        break;
                    // 开始节点
                    case XmlPullParser.START_TAG:
                        // 判断如果其实节点为BlogsInfo
                        if ("string".equals(nodeName)) {
                            // 设置Id属性
                            content=xmlPullParser.nextText();
                        }
                        break;
                    // 结束节点
                    case XmlPullParser.END_TAG:
                        break;
                    }
                    eventType = xmlPullParser.next();
                }
            } catch (NumberFormatException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }

 

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

SAX解析

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

这种方式解析是一种基于事件驱动的api,有两个部分,解析器和事件处理器,解析器就是XMLReader接口,负责读取XML文档,和向事件处理器发送事件(也是事件源),事件处理器ContentHandler接口,负责对发送的事件响应和进行XML文档处理。

下面是ContentHandler接口的常用方法

public abstract void characters (char[] ch, int start, int length)

这个方法来接收字符块通知,解析器通过这个方法来报告字符数据块,解析器为了提高解析效率把读到的所有字符串放到一个字符数组(ch)中,作为参数传递给character的方法中,如果想获取本次事件中读取到的字符数据,需要使用start和length属性。

public abstract void startDocument () 接收文档开始的通知

public abstract void endDocument () 接收文档结束的通知

public abstract void startElement (String uri, String localName, String qName, Attributes atts) 接收文档开始的标签

public abstract void endElement (String uri, String localName, String qName) 接收文档结束的标签

在一般使用中为了简化开发,在org.xml.sax.helpers提供了一个DefaultHandler类,它实现了ContentHandler的方法,我们只想继承DefaultHandler方法即可。

 另外SAX解析器提供了一个工厂类:SAXParserFactory,SAX的解析类为SAXParser 可以调用它的parser方法进行解析。

 

如果是专门建立一个sax解析类的话,该类一定要继承DefaultHandler,然后实现sax解析的5个基本方法。

/**
     * startDocument() XML文档的开始节点
     */
    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
    }

    /**
     * endDocument()XML文档的结束节点
     */
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }

    /**
     * startElement() 开始的元素
     */
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        tag = qName;
        sb.delete(0, sb.length());
        if(qName.equals("entry")){
            isFeed = true;
            blogerInfo = new CNBlogInfo();
        }else if(qName.equals("feed")){
            isFeed = false;
        }else if(qName.equals("link")&&isFeed){
            blogerInfo.setLink(attributes.getValue("href"));
        }
    }

    /**
     * endElement() 结束元素
     */
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        super.endElement(uri, localName, qName);
        tag = "";
        if(qName.equals("entry")){
            list.add(blogerInfo);
        }
    }

    /**
     * characters 特征
     */
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        super.characters(ch, start, length);
        sb.append(ch, start, length);
        String s = sb.toString();
        if(tag.equals("id")&&isFeed){
            blogerInfo.setBlogerId(s);
        }else if(tag.equals("title")&&isFeed){
            blogerInfo.setTitle(s);
        }else if(tag.equals("blogapp")){
            blogerInfo.setBlogapp(s);
        }else if(tag.equals("avatar")){
            blogerInfo.setAuthorAvatar(s);
        }else if(tag.equals("updated")&&isFeed){
            blogerInfo.setUpdated(s);
        }else if(tag.equals("postcount")){
            blogerInfo.setPostcount(Integer.parseInt(s));
        }
    }

sax解析,非常好用,但是用的多了,发现也挺占内存的。很多东西,我们都是处在会用的基础上,但是要理解它的底层原理,实属不易。

在以后的Android学习中,我应该注重一下原理的理解。