我们在开发Android应用的过程中难免会与网络请求接触,网路请求获得的数据一般都是有一定的格式或者约定的形式来返回,这时候我们就需要对返回的数据进行解析,然后从中提取出我们需要呈现在界面上的数据,一般我们遇到的最常见的两种便于网络传输的数据类型便是xml和json,下面就详细介绍一下有关他们的解析方式。
一、xml数据解析
首先我们先定义一段xml数据。
<apps>
<app>
<id>1</id>
<name>Google</name>
<version>1.0</version>
</app>
<app>
<id>2</id>
<name>Android</name>
<version>2.0</version>
</app>
<app>
<id>3</id>
<name>Play</name>
<version>3.0</version>
</app>
</apps>
方式一、Pull解析xml数据
1、获得XmlPullParserFactory实例
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
2、 获得XmlPullParser实例
XmlPullParser xmlPullParser = factory.newPullParser();
3、设置需要解析的数据
xmlPullParser.setInput(new StringReader(xmlData));
4、获得当前的解析事件
int eventType = xmlPullParser.getEventType();
5、解析结点,知道xml数据解析完成
下面是一个简单的小例子来解析最上面给出的xml数据
/**
* 使用Pull解析xml数据
*/
private void parseXmlDataWithPull(String xmlData) {
try {
//获得XmlPullParserFactory实例
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//获得XmlPullParser实例
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("xiao", "id " + id);
Log.d("xiao", "name " + name);
Log.d("xiao", "version " + version);
}
break;
default:
break;
}
//获取下一个解析事件
eventType = xmlPullParser.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
方式二、SAX解析xml数据
SAX解析虽然比Pull解析复杂一点,但在语义理解方面更加清楚,下面是它的具体用法。
1、创建一个类继承自DefaultHandler,并重写其中的5个方法。
public class MyHandler extends DefaultHandler {
private String nodeName;
private StringBuilder id;
private StringBuilder name;
private StringBuilder version;
//在开始进行xml解析的时候调用
@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) throws SAXException {
if ("app".equals(localName)){
//去掉可能包含的回车符和换行符
Log.d("GGGG", "id " + id.toString().trim());
Log.d("GGGG", "name " + name.toString().trim());
Log.d("GGGG", "version " + version.toString().trim());
//清空StringBuilder
id.setLength(0);
name.setLength(0);
version.setLength(0);
}
}
//完成整个xml解析的时候调用
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
}
2、获得SAXParserFactory的实例
SAXParserFactory factory = SAXParserFactory.newInstance();
3、获得XMLReader的实例
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
4、获得我们自己定义的处理类的实例
MyHandler handler = new MyHandler();
5、将MyHandler类的实例设置到XMLReader中
xmlReader.setContentHandler(handler);
6、开始解析
xmlReader.parse(new InputSource(new StringReader(xmlData)));
下面给出完整的代码,解析最上面给出的xml文件
/**
* 用Sax解析xml数据
* @param xmlData
*/
private void parseXmlDataWithSax(String xmlData){
//获得SAXParserFactory的实例
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
//获得XMLReader的实例
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
//获得我们自己定义的处理类的实例
MyHandler handler = new MyHandler();
//将MyHandler类的实例设置到XMLReader中
xmlReader.setContentHandler(handler);
//开始解析
xmlReader.parse(new InputSource(new StringReader(xmlData)));
} catch (SAXException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
方式三、Dom解析xml数据
Dom解析也是xml常用的一种解析方式,但由于它在解析时是将整个文档树全部加载到内存中,所以它一般只用来解析文档规模较小的场景,下面是一段简单的代码来解析文档最开头给出的那段xml文档。
/**
* 使用Dom解析xml
*
* @param xmlData
*/
private void parseXmlWithDom(String xmlData) {
//得到DOM解析器的工厂实例
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
//从DOM工厂中获得DOM解析器
DocumentBuilder dbBuilder = null;
try {
dbBuilder = dbFactory.newDocumentBuilder();
//把要解析的xml文档读入DOM解析器
Document doc = dbBuilder.parse(new InputSource(new StringReader(xmlData)));
//得到文档名称为app的元素的节点列表
NodeList nList = doc.getElementsByTagName("app");
//遍历该集合,显示集合中的元素及其子元素的名字
for(int i = 0; i< nList.getLength() ; i ++){
//Node转型WieElement
Element node = (Element)nList.item(i);
Log.d("MMMM", "id: "+ node.getElementsByTagName("id").item(0).getFirstChild().getNodeValue());
Log.d("MMMM", "name: "+ node.getElementsByTagName("name").item(0).getFirstChild().getNodeValue());
Log.d("MMMM", "version: "+ node.getElementsByTagName("version").item(0).getFirstChild().getNodeValue());
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}