一、XML文件系列化
XmlSerializer ser = Xml.newSerializer(); //生成XML序列化器
File file = new File(Environment.getExternalStorageDirectory(), "worker.xml");
try {
FileOutputStream output = new FileOutputStream(file);
ser.setOutput(output, "UTF-8"); //设置序列化器的编码方式和往哪里输出
ser.startDocument("UTF-8", true); // <?xml version="1.0" encoding="utf-8"?>
ser.startTag(null, "workers"); // <workers>
for(int i=0; i<3; i++){
ser.startTag(null, "worker");
ser.attribute(null, "id", i+1+""); //属性 <worker id = "1" >
ser.startTag(null, "name");
ser.text("duncan" + i); //内容 <name>duncan</name>
ser.endTag(null, "name");
ser.startTag(null, "age");
ser.text(i + 20 +"");
ser.endTag(null, "age");
ser.startTag(null, "money");
ser.text(i*100 + 5000 +"");
ser.endTag(null, "money");
ser.endTag(null, "worker");
}
ser.endTag(null, "workers");
ser.endDocument();
output.close();
}catch(Exception e){
e.printStackTrace();
}
上面的代码结果如下:
<?xml version="1.0" encoding="utf-8"?>
<workers>
<worker id = "1">
<name>duncan0</name>
<age>20</age>
<money>5000</money>
</worker>
<worker id = "2">
<name>duncan1</name>
<age>21</age>
<money>5100</money>
</worker>
<worker id = "3">
<name>duncan2</name>
<age>22</age>
<money>5200</money>
</worker>
</workers>
这种解析方式在Android中并不常用,因为它的缺点比较明显,它是整个XML文件加载进内存后才开始解析,对于手机这种内存吃紧的设备,不建议使用。
1、Worker.java
public class Worker {
private int id;
private String name;
private String age;
private String money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getMoney() {
return money;
}
public void setMoney(String money) {
this.money = money;
}
}
2、DOM.java
public static List<Worker> parseXml(InputStream input) throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //创建一个DOM解析工厂
DocumentBuilder builder = factory.newDocumentBuilder(); //由工厂创建一个DOM解析器
Document dc = builder.parse(input); //解析器解析输入流 得到文件对象
Element root = dc.getDocumentElement(); //获得根元素
List<Worker> list = new ArrayList<Worker>();
NodeList nodeList = root.getElementsByTagName("worker"); //获得节点名称为"worker"的节点,并把其放入NodeList链表里
for(int i=0; i<nodeList.getLength(); i++){ //遍历该链表
//获得链表的第一个元素,强制转换为其子类是因为Element这个类通过getAttribute能直接获得属性
Element e = (Element) nodeList.item(i);
Worker worker = new Worker();
worker.setId(Integer.parseInt(e.getAttribute("id"))); //获得属性 转为整型
NodeList childNode = e.getChildNodes(); //获得第一个元素下面的所有子元素,把它们同样放入链表中
for(int j=0; j<childNode.getLength(); j++){ //遍历放着子元素的链表
if(childNode.item(j).getNodeType() == Node.ELEMENT_NODE){ //判断是否是元素节点
if(childNode.item(j).getNodeName().equals("name")){
//记住一定要有getFirstChild这个方法
worker.setName(childNode.item(j).getFirstChild().getNodeValue());
}else if(childNode.item(j).getNodeName().equals("age")){
worker.setAge(childNode.item(j).getFirstChild().getNodeValue());
}else if(childNode.item(j).getNodeName().equals("money")){
worker.setMoney(childNode.item(j).getFirstChild().getNodeValue());
}
}
}
list.add(worker);worker = null;
}
return list;
}
3、MainActivity.java
把worker.xml放在/res/raw目录下
Resources res = getResources(); //获得资源对象
InputStream input = res.openRawResource(R.raw.worker); //把资源转为流
try {
List<Worker> list = DOM.parseXml(input);
for(Worker worker : list){ //遍历list
System.out.println(worker.getId() + " " + worker.getName() + " " +
worker.getAge() + " " + worker.getMoney());
System.out.println("----------------->");
}
} catch (Exception e) {
e.printStackTrace();
}
三、SAX解析XML文件
1、Worker.java
public class WorkerData {
private int id;
private String name;
private String age;
private String money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getMoney() {
return money;
}
public void setMoney(String money) {
this.money = money;
}
}
2、MyContentHandler.java
public class MyContentHandler extends DefaultHandler {
private List<WorkerData> list;
private WorkerData data;
private static String tempName;
private static int i = 0;
//当解析到<name>zhang</name>里的zhang时调用下面的方法,通过打印看出来如果不设i=0的条件。
//每个if语句里的内容在一个<worker> </worker>里会执行两次,而且第二次打印出来的是“ ”字符串,所以我猜可能是<name>zhang</name>后面这里的空格导致的
public void characters(char[] ch, int start, int length)throws SAXException {
if(i == 0){
i = 1;
if("name".equals(tempName)){
String name = new String(ch,start,length);
data.setName(name);
}else if("age".equals(tempName)){
String age = new String(ch,start,length);
data.setAge(age);
}else if("money".equals(tempName)){
String money = new String(ch,start,length);
data.setMoney(money);
}
}
}
//当本文件所有内容解析完成的时候调用
public void endDocument() throws SAXException {
System.out.println("endDocument");
}
//当解析到</name> </worker>等之类的时候会调用
public void endElement(String uri, String localName, String qName)throws SAXException {
if("worker".equals(localName)){
list.add(data);data = null;
}
}
//当开始解析<?xml version="1.0" encoding="utf-8"?>时调用
public void startDocument() throws SAXException {
System.out.println("startDocument");
list = new ArrayList<WorkerData>();
}
//碰到<workers> <worker> <name> <age> <money> <address>都会调用下面的方法
public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {
if("worker".equals(localName)){
data = new WorkerData();
data.setId(Integer.parseInt(attributes.getValue(0))); //获得<worker id = "100"> 里属性的值
}
tempName = localName;
i = 0;
}
public List<WorkerData> myReturn(){
return list;
}
}
3、MainActivity.java
SAXParserFactory factory = SAXParserFactory.newInstance(); //创建一个SAX解析工厂
try {
SAXParser parser = factory.newSAXParser(); //通过工厂获得SAX解析器
Resources res = getResources();
InputStream input = res.openRawResource(R.raw.worker);
MyContentHandler my = new MyContentHandler();
//开始解析,两个参数分别是:要解析的文件输入流,DefaultHandler的子类对象
parser.parse(input, my);
List<WorkerData> mylist = my.myReturn();
for(WorkerData wd : mylist){
System.out.println(wd.getId() + " " + wd.getName() + " " + wd.getAge() + " "+ wd.getMoney());
System.out.println("------------------>");
}
} catch (Exception e) {
e.printStackTrace();
}
四、Pull解析XML文件
1、res/raw/person.xml
<?xml version="1.0" encoding="utf-8"?>
<persons>
<person id = "1">
<name>duncan</name>
<age>20</age>
</person>
<person id = "2">
<name>zhang</name>
<age>25</age>
</person>
<person id = "3">
<name>mike</name>
<age>15</age>
</person>
</persons>
2、Person.java
public class Person {
private String id;
private String name;
private String age;
public Person(){}
public Person(String id, String name, String age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
3、PullService.java
public class PersonService {
public static ArrayList<Person> getData(InputStream is) throws Exception{
//通过Xml的静态方法获得Pull解析器
XmlPullParser parser = Xml.newPullParser();
//关联解析器和被解析的文件流
parser.setInput(is, "utf-8");
//通过解析器获得当前解析点所处的类型
int type = parser.getEventType();
Person p = null;
ArrayList<Person> list = null;
while(type != XmlPullParser.END_DOCUMENT){
switch(type){
case XmlPullParser.START_DOCUMENT :
list = new ArrayList<Person>();
break;
case XmlPullParser.START_TAG :
if(parser.getName().equals("person")){
p = new Person();
String id = parser.getAttributeValue(0);
p.setId(id);
}else if(parser.getName().equals("name")){
p.setName(parser.nextText());
}else if(parser.getName().equals("age")){
p.setAge(parser.nextText());
}
break;
case XmlPullParser.END_TAG :
if(parser.getName().equals("person")){
list.add(p);
p = null;
}
break;
}
type = parser.next(); //获得当前解析点所要解析的类型
}
return list;
}
}
解析person.xml文件的流程如下:
(1),解析器处于<?xml version="1.0" encoding="utf-8"?>时,是START_DOCUMENT状态
(2),解析器往下移,来到了<persons>处,是一个START_TAG。接着解析器继续往下移,来到
<persons>和<person>中间的空白处,这里是一个Text。
(3),解析器继续往下移,来到了<person id="1">处,这里又是一个START_TAG。通过解析器的
getAttributeValue方法获得属性"1"。然后解析器继续往下移,又来到空白处,依然是一个Text。
(4),解析器往下移,来到<name>处,是一个START_TAG。通过解析器的nextText()方法来获得
字符串"duncan"。当获取成功后,解析器自动会移到"duncan"这个位置。然后接着继续调用
parser.next()方法往下移,来到</name>,这里是END_TAG。接着往下移,来到空白处
,这里是一个Text。。。。。。。
4、MainActivity.java
Resources res = getResources();
//通过资源对象的openRawResource方法,把xml文件转为输入流
InputStream is = res.openRawResource(R.raw.person);
try {
//调用自己写的业务类的方法,该方法就是实现Pull解析的真正过程
ArrayList<Person> list = PersonService.getData(is);
for(Person p : list){
System.out.println(p.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
把XML文件转为流有两种比较常用的方式:1、本程序的做法,把XML文件放在res/raw文件夹下,通过资源对象的方法来获得。
2、把xml文件放在src目录下。通过类加载器的方式获得流
InputStream is=MainActivity.class.getClassLoader().getResourceAsStream("person.xml");
五、解析JSON格式数据
要解析的数据如下:
private String jsonString = "{\"persons\":[{\"id\":100,\"name\":\"zhang\",\"age\":25}," +
"{\"id\":200,\"name\":\"duncan\",\"age\":37}," +
"{\"id\":300,\"name\":\"binhua\",\"age\":24}]}";
解析代码:
private List<Map<String, Object>> parseJson(String jsonString) {
List<Map<String, Object>> list = null;
try {
list = new ArrayList<Map<String, Object>>();
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray("persons");
for (int i = 0; i < jsonArray.length(); i++) {
Map<String, Object> map = new HashMap<String, Object>();
JSONObject jObject = jsonArray.getJSONObject(i);
map.put("id", jObject.getInt("id"));
map.put("name", jObject.getString("name"));
map.put("age", jObject.getInt("age"));
list.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
return list;
}
通过JSONObject和JSONArray就可以完成解析了。