XML是eXtensible Markup Language的缩写,扩展标记语言XML
虽然XML占用的空间比二进制数据要占用更多的空间,但是XML极其简单易于掌握和使用
三种解析方法
1 DOM解析:
特点是先把dom全部文件读入到内存中,不适合大的XML数据
优点 她比较直观.
2 SAX是一种基于事件驱动的api有两部分:解析器和事件处理器,边读边解析.
3 PULL他也是边读边解析,它可以停止他主要是用next()方法来获取下一个解析时间getAttributte()方法来获取属性的值,也可以调用nextText()获取文本节点的值
代码
package com.example.wangye.androidxmlpasertest1609c;
import android.app.Activity;
import android.os.Bundle;
import android.support.constraint.solver.ArrayLinkedVariables;
import android.util.Xml;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class MainActivity extends Activity {
Button btDOM,btPULL,btSAX;
TextView tx;
InputStream is;
HashMap<String,String> map = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
void init(){
try {
//读取assets目录中的文件 assets目录中的文件在打包APK的时候不会被编译成二进制
is = getAssets().open("users.xml");
} catch (Exception e) {
e.printStackTrace();
}
btDOM = (Button) findViewById(R.id.button);
btDOM.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tx.setText(domParse(is).toString());
}
});
btPULL = (Button) findViewById(R.id.button2);
btPULL.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tx.setText("当前解析:\n"+pullParse(is).toString());
}
});
btSAX = (Button) findViewById(R.id.button3);
btSAX.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tx.setText("SAX解析:\n"+saxParse(is).toString());
}
});
tx = (TextView) findViewById(R.id.textView);
}
// DOM解析 把文件缓存至内存中 比较占内存 不适合大文件的读取
ArrayList<HashMap<String,String>> domParse( InputStream is){
ArrayList<HashMap<String,String>> alist= new ArrayList<HashMap<String,String>>();
try {
//创建解析对象工厂类
DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
//由工厂类对象创建解析对象
DocumentBuilder db = df.newDocumentBuilder();
//把需要读取的数据流或者文件 缓存至内存中Document中
Document dt = db.parse(is);
//获取Document中的所有节点信息
Element root = dt.getDocumentElement();
//获取有用节点信息
NodeList fatherList = root.getElementsByTagName("person");
for(int i = 0;i<fatherList.getLength();i++){
//node节点不可以直接提取信息 需要转换成Element才可以提取信息
Node node = fatherList.item(i);
//强制转换成元素节点
Element et = (Element) node;
HashMap<String,String> map = new HashMap<String,String>();
//获取person标签的属性值
map.put("id",et.getAttribute("id"));
//如果当前标签所携带的信息 是以子标签的形式的展示的 那么不可以直接提取 需要在分级
NodeList childList = et.getChildNodes();
//将父标签中子标签挨个循环读取
for(int j = 0;j<childList.getLength();j++){
Node childNode = childList.item(j);
//判断当前读取的子标签是否是元素节点
if(childNode.getNodeType() == Node.ELEMENT_NODE){
//如果是 则可以直接提取信息
if(childNode.getNodeName().equals("name")){
map.put("name",childNode.getFirstChild().getNodeValue());
}else if(childNode.getNodeName().equals("age")){
map.put("age",childNode.getFirstChild().getNodeValue());
}
}
}
alist.add(map);
}
} catch (Exception e) {
e.printStackTrace();
}
return alist;
}
//PULL解析 采用事件驱动的方式(边读边解析) pull解析可以在任意位置停止 适合大文件的解析
ArrayList<HashMap<String,String>> pullParse( InputStream is){
ArrayList<HashMap<String,String>> alist = new ArrayList<HashMap<String,String>>();
//创建解析工具
XmlPullParser pull = Xml.newPullParser();
try {
//参数2 编码格式
pull.setInput(is,"UTF-8");
//获取当前读取数据的节点类型 START_DUCUMENT END_DOCUMENT START_TAG END_TAG
int type = pull.getEventType();
while(type != XmlPullParser.END_DOCUMENT){
switch (type){
case XmlPullParser.START_DOCUMENT://文档开始
break;
case XmlPullParser.START_TAG://标签开始
if(pull.getName().equals("person")){
map = new HashMap<String,String>();
//根据位置获取节点里的属性信息
map.put("id",pull.getAttributeValue(0));
}
//获取节点信息
if(pull.getName().equals("name")){
map.put("name",pull.nextText());
}
if(pull.getName().equals("age")){
map.put("age",pull.nextText());
}
break;
case XmlPullParser.END_TAG://标签结束
if(pull.getName().equals("person")){
alist.add(map);
}
break;
case XmlPullParser.END_DOCUMENT://文档结束
break;
}
//pull不会自动跳到下一个标签 手动指向下一个节点
// if(){
//
// }
pull.next();
type = pull.getEventType();
}
} catch (Exception e) {
e.printStackTrace();
}
return alist;
}
//SAX解析 跟PULL类似 采用的也是事件驱动的方式(边读边解析) 一旦解析停不下来
ArrayList<HashMap<String,String>> saxParse( InputStream is){
ArrayList<HashMap<String,String>> alist = new ArrayList<HashMap<String,String>>();
try {
//创建解析工厂类
SAXParserFactory sf = SAXParserFactory.newInstance();
//由工厂类创建解析对象
SAXParser sp = sf.newSAXParser();
//由解析对象使用解析工具进行解析
//参数1 数据流 参数2 解析工具 需要单独创建工具类继承DefaultHandler
SAXHandler handler = new SAXHandler();
sp.parse(is,handler);
alist = handler.alist;
} catch (Exception e) {
e.printStackTrace();
}
return alist;
}
class SAXHandler extends DefaultHandler{
ArrayList<HashMap<String,String>> alist = new ArrayList<HashMap<String,String>>();
HashMap<String,String> map = null;
String tag;
@Override//表示文档的开始 相当于PULL解析的 START_DOCUMENT
public void startDocument() throws SAXException {
super.startDocument();
}
@Override//表示文档的结束 相当于PULL解析的 END_DOCUMENT
public void endDocument() throws SAXException {
super.endDocument();
}
@Override// 获取开始标签 相当于PULL解析的 START_TAG
//参数2 表示标签名称 参数4 获取属性信息
// 属性信息的提取在这里获取 正文信息在characters方法里获取
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if(localName.equals("person")){
map = new HashMap<String,String>();
map.put("id",attributes.getValue(0));
}
tag = localName;
}
@Override// 获取结束标签 相当于PULL解析的 END_TAG\
//在结束标签里 把开始标签中获取的标签名清空 否则获取不到数据
public void endElement(String uri, String localName, String qName) throws SAXException {
if(localName.equals("person")){
alist.add(map);
map = null;
}
tag = null;
}
@Override//获取开始标签之后的标签文本 不是属性信息
public void characters(char[] ch, int start, int length) throws SAXException {
// byte b[] = new byte[3];
// try {
// String s = new String(b,"utf-8");
// } catch (UnsupportedEncodingException e) {
// e.printStackTrace();
// }
// Math.random();//[0,1)
String data = new String(ch,start,length);
if(map!=null){
if("name".equals(tag)){
map.put("name",data);
}
if("age".equals(tag)){
map.put("age",data);
}
}
}
}
}
解析的XML文件
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="23">
<name>李雷</name>
<age>30</age>
</person>
<person id="20">
<name>韩梅梅</name>
<age>25</age>
</person>
</persons>