Android中XML文件解析、系列化及JSON解析

来源:互联网 发布:VB无印汉化下载 编辑:程序博客网 时间:2024/05/12 21:17

一、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>


二、DOM解析XML文件

这种解析方式在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){         //遍历listSystem.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;}@Overridepublic 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就可以完成解析了。