Http网络传输中的数据组织格式主要有三种:
1.HTML方式
2.XML方式
3.JSON方式
其中XML方式的数据解析有三种:DOM解析,SAX解析,Pull解析。
下面主要讲解SAX解析。
因为SAX解析是解析XML格式的数据的,那么首先要大致了解下什么是XML,以及XML数据有什么特点。
下面是一个XML数据文件:
分析:XML文件和HTML文件很相似,都是由标签构成,但是XML比HTML更灵活,XML被称为可扩展性标记语言。其中第一行的是固定的格式,文件主体全部有双标签构成,且标签是自定义的,非常灵活。
总结:XML数据是网络传输数据的一种组织格式,其格式可以说灵活,但是也可以说非常固定,因为其中的每条数据的结构是完全相同的,这样做的目的是当从网络获取数据时,总是重复的采取相同的操作解析数据(循环遍历结构+选择对结构的不同部分采取不同的操作)。怎么说呢,如果从网络获取数据,那么数据一定是有一定格式的,如果是返回多条数据,那么每条数据的结构一定是完全相同的或者所有数据一定有一个结构且这个结构是每条数据结构的父集,这样的目的是方便客户端解析接收到的数据。
根据XML格式的定义我们可以写出各种XML数据:
以上代码可以很容易看出它们的结构可以说是固定可扩展,固定指的是每条数据的结构完全相同,可扩展是这些结构是自定义的,同时数据的条数是任意的。
SAX解析以事件通知的形式通知程序,对xml解析。
那么何为事件通知的形式呢?
SAX的解析是从文档的开头依次解析到文档的结尾的,当解析到上图第一行时,发生的事件就是解析到文档开头,当解析到文档结尾时,发生的事件就是解析到文档结尾,当解析到第二行<books>标签时,发生的事件是解析到开始标签,其中这里的开始标签就是books,对应的</books>发生的事件就是解析到结束标签,其中结束标签就是books,其中标签里还可能含有属性,如<book id ="1">中的id就是属性,当解析到english,15.5f等文本时,发生的事件就是解析到内容。
SAX解析的步骤:
1.定义数据的封装类,将要解析的数据封装到这个实体类中。
2.定义一个执行具体解析操作的类,即定义一个类继承DefaultHandler,实现这个类的五个方法,对不同的标签执行不同的操作。
2.1 public void startDocument():解析到文档开头时执行该方法
2.2 public void startElement(String uri, String localName, String qName,Attributes attributes):解析到开始标签时执行该方法
2.3 public void characters(char[] ch, int start, int length):解析到标签内容时执行该方法
2.4 public void endElement(String uri, String localName, String qName):解析到结束标签时执行该方法
2.5 public void endDocument():解析到文档结束时执行该方法
3.开始解析,具体的操作
3.1 创建SAX解析的工厂类
SAXParserFactory factory = SAXParserFactory.newInstance();
根据factory对象,创建 SAX解析对象
SAXParser parser = factory.newSAXParser();
3.2 创建读取xml文件的文件读取流
FileInputStream fis = new FileInputStream("user.xml");
创建Handler对象(即上面提到的一个执行具体解析操作的类的对象,其中Handler不是安卓中的Handler)
MyHandler handler = new MyHandler(); (MyHandler是一个自定义类,必须继承DefaultHandler)
解析
parser.parse(fis,handler)
3.3 获取解析的结果,是一个List<Object>集合
List<Person> list = handler.getList(); (getList()是Handler的一个自定义方法,用来返回解析的结果,且这个结果是Handler内部定义的一个成员变量,具体看示例)
示例1:解析person.xml文件
1 23 4 7张老师 521 68 11李老师 925 10
1 package com.qianfeng.sax1; 2 3 public class Person { 4 5 private String name; 6 private int age; 7 private String sex; 8 9 public Person(){}10 11 public Person(String name, int age, String sex) {12 super();13 this.name = name;14 this.age = age;15 this.sex = sex;16 }17 18 public String getName() {19 return name;20 }21 22 public void setName(String name) {23 this.name = name;24 }25 26 public int getAge() {27 return age;28 }29 30 public void setAge(int age) {31 this.age = age;32 }33 34 public String getSex() {35 return sex;36 }37 38 public void setSex(String sex) {39 this.sex = sex;40 }41 42 @Override43 public String toString() {44 return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";45 }46 47 48 49 }
1 package com.qianfeng.sax1; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import org.xml.sax.Attributes; 7 import org.xml.sax.SAXException; 8 import org.xml.sax.helpers.DefaultHandler; 9 10 public class MyHandler extends DefaultHandler {11 12 private Listlist;13 private Person person;14 private String tagName;//存储标签名15 16 //解析到文档开头时执行该方法17 @Override18 public void startDocument() throws SAXException {19 System.out.println("解析到文档开头....");20 list = new ArrayList ();21 }22 //解析到开始标签时执行该方法23 //qName接收的是开始标签的名字24 @Override25 public void startElement(String uri, String localName, String qName,26 Attributes attributes) throws SAXException {27 tagName = qName;28 System.out.println("解析到开始标签....."+qName);29 if("person".equals(qName))30 {31 person = new Person();32 }33 34 }35 //解析到标签内容时执行该方法36 //解析到到标签数据传给了ch37 @Override38 public void characters(char[] ch, int start, int length)39 throws SAXException {40 String data = new String(ch,start,length);41 System.out.println("解析到标签内容..."+data);42 if("name".equals(tagName))43 {44 person.setName(data);45 }46 else if("age".equals(tagName))47 person.setAge(Integer.parseInt(data));48 else if("sex".equals(tagName))49 person.setSex(data);50 51 }52 //解析到结束标签时执行该方法53 //qName接收结束标签的名字54 @Override55 public void endElement(String uri, String localName, String qName)56 throws SAXException {57 tagName = null;//结束标签后边的空白也被看成标签内容,所以会去执行characters()方法58 System.out.println("解析到结束标签...."+qName);59 if("person".equals(qName))60 {61 list.add(person);62 }63 }64 //解析到文档结束时执行该方法65 @Override66 public void endDocument() throws SAXException {67 System.out.println("解析到文档结束.....");68 }69 70 public List getList() {71 return list;72 }73 74 75 76 }
1 package com. qianfeng.sax1; 2 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.IOException; 6 import java.util.List; 7 8 import javax.xml.parsers.ParserConfigurationException; 9 import javax.xml.parsers.SAXParser;10 import javax.xml.parsers.SAXParserFactory;11 12 import org.xml.sax.SAXException;13 14 public class Test {15 16 /**17 * @param args18 * @throws SAXException 19 * @throws ParserConfigurationException 20 * @throws IOException 21 */22 public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {23 24 //创建SAX解析的工厂类25 SAXParserFactory factory = SAXParserFactory.newInstance();26 27 //创建 SAX解析对象--负责读取xml文件,并去调用handler中的方法28 SAXParser parser = factory.newSAXParser();29 30 //创建读取xml文件的文件读取流31 FileInputStream fis = new FileInputStream("user.xml");32 33 //创建Handler对象34 MyHandler handler = new MyHandler();35 36 //解析37 parser.parse(fis, handler);38 39 Listlist = handler.getList();40 41 for(Person person:list)42 {43 System.out.println(person);44 }45 }46 47 }
分析:总的来说SAX解析就涉及到3个类或者合并为更少的类,第一个是数据封装类,用来保存解析后得到的数据;第二个就是具体解析的类,必须继承DefaultHandler类,重写5个方法,执行具体的解析;第三个是执行解析的过程,核心方法就是parser.parse(fis,handler),"parser"是解析器,parser的获取先要获得解析器的工厂,然后由工厂对象获取SAXParser类对象,fis是一个文件字节输入流,指向xml文件的位置,handler是第二个类创建的一个对象,即具体解析类的对象,这就是SAX解析的主要框架。下面是解析一些XML文件中一些其他数据的示例。
示例2:解析worker.xml文件
1 23 4 10Mark 5男 6经理 7 北京 84000 911 17Luch 12女 13员工 14 上海151000 1618 24Lily 19女 20员工 21 北京222000 2325 31Lily 26女 27员工 28 北京292000 30
1 package com.qianfeng.sax2; 2 3 public class Worker { 4 5 private String id; 6 private String name; 7 private char sex; 8 private String status; 9 private String address;10 private double money;11 12 public Worker(){}13 14 public Worker(String id, String name, char sex, String status,15 String address, double money) {16 super();17 this.id = id;18 this.name = name;19 this.sex = sex;20 this.status = status;21 this.address = address;22 this.money = money;23 }24 25 public String getId() {26 return id;27 }28 29 public void setId(String id) {30 this.id = id;31 }32 33 public String getName() {34 return name;35 }36 37 public void setName(String name) {38 this.name = name;39 }40 41 public char getSex() {42 return sex;43 }44 45 public void setSex(char sex) {46 this.sex = sex;47 }48 49 public String getStatus() {50 return status;51 }52 53 public void setStatus(String status) {54 this.status = status;55 }56 57 public String getAddress() {58 return address;59 }60 61 public void setAddress(String address) {62 this.address = address;63 }64 65 public double getMoney() {66 return money;67 }68 69 public void setMoney(double money) {70 this.money = money;71 }72 73 @Override74 public String toString() {75 return "Worker [id=" + id + ", name=" + name + ", sex=" + sex76 + ", status=" + status + ", address=" + address + ", money="77 + money + "]";78 }79 80 81 82 }
1 package com.qianfeng.sax2; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import org.xml.sax.Attributes; 7 import org.xml.sax.SAXException; 8 import org.xml.sax.helpers.DefaultHandler; 9 10 public class MyHandler extends DefaultHandler {11 12 private Listlist;13 private Worker worker;14 private String tagName;15 16 @Override17 public void startDocument() throws SAXException {18 list = new ArrayList ();19 }20 21 22 @Override23 public void startElement(String uri, String localName, String qName,24 Attributes attributes) throws SAXException {25 //attributes参数用来接收属性的26 tagName = qName;27 if("worker".equals(tagName))28 {29 worker = new Worker();30 if(attributes!=null)31 {32 for(int i=0;i getList() {83 return list;84 }85 86 87 88 }
1 package com.qianfeng.sax2; 2 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.IOException; 6 import java.util.List; 7 8 import javax.xml.parsers.ParserConfigurationException; 9 import javax.xml.parsers.SAXParser;10 import javax.xml.parsers.SAXParserFactory;11 12 import org.xml.sax.SAXException;13 14 public class Test {15 16 /**17 * @param args18 * @throws SAXException 19 * @throws ParserConfigurationException 20 * @throws IOException 21 */22 public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {23 24 SAXParserFactory factory =SAXParserFactory.newInstance();25 26 SAXParser parser = factory.newSAXParser();27 28 FileInputStream fis = new FileInputStream("worker.xml");29 MyHandler handler = new MyHandler();30 31 parser.parse(fis, handler);32 33 Listlist = handler.getList();34 35 for(Worker worker:list)36 {37 System.out.println(worker);38 }39 40 41 42 }43 44 }
分析:该示例解决了当标签中还有属性该如何解析的问题。
未完,待续。