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

Android解析XML数据

程序员文章站 2022-06-16 15:22:44
...

XML是超文本标记语言,是各种应用程序之间进行数据传输的最常用的工具。Android中布局文件也是使用XML格式来写的。
在Android中常用PULL解析器,SAX解析器和DOM解析器来解析XML格式数据。

PULL解析器:
XmlPull和Sax类似,是基于流(stream)操作文件,然后根据节点事件来解析的。因为是基于流的处理,因此Xmlpull和 Sax都比较节约内存资源,不会象Dom那样要把所有节点以对象树的形式展现在内存中。 但Xmlpull比Sax更简明,而且不需要扫描完整个流。

SAX解析器:
SAX(Simple API for XML),它并不是由W3C官方所提出的标准,虽然如此,使用SAX的还是不少,几乎所有的XML解析器都会支持它。与DOM比较而言,SAX是一种轻量型的方法。我们知道,在处理DOM的时候,需要读入整个的XML文档,然后在内存中创建DOM树,生成DOM树上的每个Node对象。SAX在概念上与DOM完全不同。它不同于DOM的文档驱动,它是事件驱动的,它并不需要读入整个文档,而文档的读入过程也就是SAX的解析过程。所谓事件驱动,是指一种基于回调(callback)机制的程序运行方法。

DOM解析器:
DOM(Document Object Model,文档对象模型)是W3C制定的一套规范标准,即规定了解析文件的接口。各种语言可以按照DOM规范去实现这些接口,给出解析文件的解析器。各种基于DOM规范解析器必须按照DOM规范在内存中建立数据,DOM规范的核心是DOM树模型。对于解析XML文件的解析器,解析器通过读入XML文件在内存中建立一个树,也就是说XML文件的标记、标记的文本内容、实体等都会和内存中树的某个节点相对应。一个应用程序可以方便地操作内存中树的节点来处理XML文档,获取自己所需要的数据。

下面来解析如下的XML数据:

<?xml version="1.0" encoding="utf-8"?>
<all>
    <music group="1" id="1">
        <name>七月上</name>
        <author>Jam</author>
    </music>
    <music group="2" id="2">
        <name>有点甜</name>
        <author>汪苏泷</author>
    </music>
    <music group="3" id="3">
        <name>大胆说爱</name>
        <author>落落</author>
    </music>
</all>

使用PULL解析:

/**
 * 使用pull解析
 *
 * @param in
 */
private List<Music> pullParseXML(InputStream in) {
    ArrayList<Music> musics = null;
    try {
        XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance();
        XmlPullParser xmlPullParser = xmlPullParserFactory.newPullParser();
        xmlPullParser.setInput(in, "UTF-8");

        int eventType = xmlPullParser.getEventType();
        Music music = null;
        while (eventType != XmlPullParser.END_DOCUMENT) {
            String nodeName = xmlPullParser.getName();
            switch (eventType) {
                case XmlPullParser.START_DOCUMENT://文档开始
                    musics = new ArrayList<>();
                    break;
                case XmlPullParser.START_TAG://开始节点
                    if ("music".equals(nodeName)) {
                        music = new Music();
                        music.group = Integer.parseInt(xmlPullParser.getAttributeValue(0));
                        music.id = Integer.parseInt(xmlPullParser.getAttributeValue(1));
                    } else if ("name".equals(nodeName)) {
                        music.name = xmlPullParser.nextText();
                    } else if ("author".equals(nodeName)) {
                        music.author = xmlPullParser.nextText();
                    }
                    break;
                case XmlPullParser.END_TAG://结束节点
                    if (music != null) {
                        musics.add(music);
                    }
                    music = null;
                    break;
                default:
                    break;
            }
            //触发下一个事件
            eventType = xmlPullParser.next();
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
    return musics;
}

使用SAX解析:

/**
 * 使用sax解析
 *
 * @param in
 */
private List<Music> saxParseXML(InputStream in) {
    try {
        SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
        SaxParseXML parseXML = new SaxParseXML();
        saxParser.parse(in, parseXML);
        return parseXML.getData();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

注意使用sax解析要创建解析类继承DefaultHandler类,代码如下:

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

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

/**
 * Created by Administrator on 2017/8/29.
 */

public class SaxParseXML extends DefaultHandler {
    private List<Music> data = new ArrayList<>();
    private Music music;
    private String tagName;

    public List<Music> getData() {
        return data;
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if ("music".equals(qName)) {
            music = new Music();
            music.group = Integer.parseInt(attributes.getValue(0));
            music.id = Integer.parseInt(attributes.getValue(1));
        }
        this.tagName = qName;
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if ("music".equals(qName)) {
            if (music != null) {
                data.add(music);
            }
        }
        this.tagName = null;
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if (tagName != null) {
            String data = new String(ch, start, length);
            if ("name".equals(tagName)) {
                music.name = data;
            } else if ("author".equals(tagName)) {
                music.author = data;
            }
        }
    }
}

使用DOM解析:

/**
 * 使用dom解析
 *
 * @param in
 */
private List<Music> domParseXML(InputStream in) {
    List<Music> data = new ArrayList<>();
    //创建DOM工厂对象
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

    try {
        //DocumentBuilder对象
        DocumentBuilder documentBuilder = factory.newDocumentBuilder();
        //获取文档对象
        Document document = documentBuilder.parse(in);
        //获取文档对象的root
        Element root = document.getDocumentElement();
        //获取all根节点中所有的person节点对象
        NodeList musicNodes = root.getElementsByTagName("music");
        //遍历所有的music节点
        for (int i = 0; i < musicNodes.getLength(); i++) {
            Music music = new Music();
            //根据item(index)获取该索引对应的节点对象
            Element musicNode = (Element) musicNodes.item(i);
            music.group = Integer.parseInt(musicNode.getAttribute("group"));
            music.id = Integer.parseInt(musicNode.getAttribute("id"));

            //获取该节点下面的所有字节点
            NodeList musicChildNodes = musicNode.getChildNodes();
            //遍历music的字节点
            for (int index = 0; index < musicChildNodes.getLength(); index++) {
                //获取字节点
                Node node = musicChildNodes.item(index);
                //判断node节点是否是元素节点
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    //把节点转换成元素节点
                    Element element = (Element) node;
                    if ("name".equals(element.getNodeName())) {
                        music.name = element.getFirstChild().getNodeValue();
                    } else if ("author".equals(element.getNodeName())) {
                        music.author = element.getFirstChild().getNodeValue();
                    }
                }
            }
            data.add(music);
        }
    } catch (Exception e) {

    }
    return data;
}

Android解析XML数据

完整代码如下:
目录结构
Android解析XML数据

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.xmlparse.MainActivity">

    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/pull_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="使用PULL解析" />

    <Button
        android:id="@+id/sax_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="使用SAX解析" />

    <Button
        android:id="@+id/dom_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="使用DOM解析" />
</LinearLayout>

MainActivity代码

import android.content.res.AssetManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView tv;
    private Button pullBtn, saxBtn, domBtn;

    private List<Music> data = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initEvent();
    }

    private void initView() {
        tv = (TextView) findViewById(R.id.tv);
        pullBtn = (Button) findViewById(R.id.pull_btn);
        saxBtn = (Button) findViewById(R.id.sax_btn);
        domBtn = (Button) findViewById(R.id.dom_btn);
    }

    private void initEvent() {
        pullBtn.setOnClickListener(this);
        saxBtn.setOnClickListener(this);
        domBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        data.clear();
        switch (v.getId()) {
            case R.id.pull_btn:
                data.addAll(pullParseXML(getXMLStream()));
                break;
            case R.id.sax_btn:
                data.addAll(saxParseXML(getXMLStream()));
                break;
            case R.id.dom_btn:
                data.addAll(domParseXML(getXMLStream()));
                break;
            default:
                break;
        }
        showXMLdata();
    }

    /**
     * 获取XML文件流
     *
     * @return
     */
    private InputStream getXMLStream() {
        AssetManager assets = getAssets();
        InputStream open = null;
        try {
            open = assets.open("musics.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return open;
    }

    /**
     * 显示获取的数据
     */
    private void showXMLdata() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < data.size(); i++) {
            sb.append(data.get(i).toString());
            sb.append("\n");
        }
        tv.setText(sb.toString());
    }

    /**
     * 使用pull解析
     *
     * @param in
     */
    private List<Music> pullParseXML(InputStream in) {
        ArrayList<Music> musics = null;
        try {
            XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance();
            XmlPullParser xmlPullParser = xmlPullParserFactory.newPullParser();
            xmlPullParser.setInput(in, "UTF-8");

            int eventType = xmlPullParser.getEventType();
            Music music = null;
            while (eventType != XmlPullParser.END_DOCUMENT) {
                String nodeName = xmlPullParser.getName();
                switch (eventType) {
                    case XmlPullParser.START_DOCUMENT://文档开始
                        musics = new ArrayList<>();
                        break;
                    case XmlPullParser.START_TAG://开始节点
                        if ("music".equals(nodeName)) {
                            music = new Music();
                            music.group = Integer.parseInt(xmlPullParser.getAttributeValue(0));
                            music.id = Integer.parseInt(xmlPullParser.getAttributeValue(1));
                        } else if ("name".equals(nodeName)) {
                            music.name = xmlPullParser.nextText();
                        } else if ("author".equals(nodeName)) {
                            music.author = xmlPullParser.nextText();
                        }
                        break;
                    case XmlPullParser.END_TAG://结束节点
                        if (music != null) {
                            musics.add(music);
                        }
                        music = null;
                        break;
                    default:
                        break;
                }
                //触发下一个事件
                eventType = xmlPullParser.next();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return musics;
    }


    /**
     * 使用sax解析
     *
     * @param in
     */
    private List<Music> saxParseXML(InputStream in) {
        try {
            SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
            SaxParseXML parseXML = new SaxParseXML();
            saxParser.parse(in, parseXML);
            return parseXML.getData();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 使用dom解析
     *
     * @param in
     */
    private List<Music> domParseXML(InputStream in) {
        List<Music> data = new ArrayList<>();
        //创建DOM工厂对象
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        try {
            //DocumentBuilder对象
            DocumentBuilder documentBuilder = factory.newDocumentBuilder();
            //获取文档对象
            Document document = documentBuilder.parse(in);
            //获取文档对象的root
            Element root = document.getDocumentElement();
            //获取all根节点中所有的person节点对象
            NodeList musicNodes = root.getElementsByTagName("music");
            //遍历所有的music节点
            for (int i = 0; i < musicNodes.getLength(); i++) {
                Music music = new Music();
                //根据item(index)获取该索引对应的节点对象
                Element musicNode = (Element) musicNodes.item(i);
                music.group = Integer.parseInt(musicNode.getAttribute("group"));
                music.id = Integer.parseInt(musicNode.getAttribute("id"));

                //获取该节点下面的所有字节点
                NodeList musicChildNodes = musicNode.getChildNodes();
                //遍历music的字节点
                for (int index = 0; index < musicChildNodes.getLength(); index++) {
                    //获取字节点
                    Node node = musicChildNodes.item(index);
                    //判断node节点是否是元素节点
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        //把节点转换成元素节点
                        Element element = (Element) node;
                        if ("name".equals(element.getNodeName())) {
                            music.name = element.getFirstChild().getNodeValue();
                        } else if ("author".equals(element.getNodeName())) {
                            music.author = element.getFirstChild().getNodeValue();
                        }
                    }
                }
                data.add(music);
            }
        } catch (Exception e) {

        }
        return data;
    }
}

xml对应JavaBean类:

public class Music {
    public int group;
    public int id;
    public String name;
    public String author;

    @Override
    public String toString() {
        return "Music{" +
                "group=" + group +
                ", id=" + id +
                ", name='" + name + '\'' +
                ", author='" + author + '\'' +
                '}';
    }
}

SaxParseXML类已经贴上了,这里就不重复写了。
到这里常用的3种解析方式已经写完了,相信大家可以根据不同的XML文件来解析对应的数据了。