Android解析XML数据
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;
}
完整代码如下:
目录结构
布局文件:
<?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文件来解析对应的数据了。