欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android入门(二十一)解析XML

程序员文章站 2022-07-07 21:33:56
...

原文链接:http://www.orlion.ga/685/

解析XML常用的方式有两种,一种是PULL解析一种是SAX解析。

假设解析数据为:

<apps>
    <app>
        <id>1</id>
        <name>Google Maps</name>
        <version>1.0</version>
    </app>
    <app>
        <id>2</id>
        <name>Chrome</name>
        <version>2.1</version>
    </app>
    <app>
        <id>3</id>
        <name>Google Play</name>
        <version>2.3</version>
    </app>
</apps>

一、PULL解析

   

try {
    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
    XmlPullParser xmlPullParser = factory.newPullParser();
    xmlPullParser.setInput(new StringReader(xmlData));
    int eventType = xmlPullParser.getEventType();
    String id = "";
    String name = "";
    String version = "";
    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();
}

 

    

    首先要获取到一个XmlPullParserFactory 的实例,并借助这个实例得到 XmlPullParser 对象,然后调用XmlPullParser的 setInput()方法将服务器返回的 XML数据设置进去就可以开始解析了。解析的过程也是非常简单,通过 getEventType()可以得到当前的解析事件,然后在一个 while循环中不断地进行解析,如果当前的解析事件不等于 XmlPullParser.END_DOCUMENT,说明解

析工作还没完成,调用 next()方法后可以获取下一个解析事件。在 while循环中,我们通过 getName()方法得到当前结点的名字,如果发现结点名等于id、name或 version,就调用 nextText()方法来获取结点内具体的内容,每当解析完一个 app

结点后就将获取到的内容打印出来。

 

二、SAX解析方式

 

    新建一个 ContentHandler类继承自 DefaultHandler,并重写父类的五个方法,如下所示:

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) throwsSAXException {
        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的内容清空掉,不然的话会影响下一次内容的读取

    

    解析XML:

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数据。parseXMLWithSAX()方法中先是创建了一个 SAXParserFactory的对象,然后再获取到XMLReader对象,接着将我们编写的 ContentHandler的实例设置到 XMLReader中,最后调用 parse()方法开始执行解析就好了。