Android入门(二十一)解析XML

原文链接: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()方法开始执行解析就好了。

 
上一篇:用premake5创建lua532工程


下一篇:阿里云ECS服务器Ubuntu配置MySQL远程访问