HTTP网络传输中的数据组织方式有三种方式:1、HTML方式2、XML方式 3、JSON方式
XML称为可扩展标记语言,它与HTML一样,都是SGML(标准通用标记语言)
XML是Internet环境中跨平台的,依赖于内容技术,是当前处理结构化文档信息的有力工具,可扩展标记语言XML是一种简单的数据存储语言,使用一系列简单的标记描述数据。
xml文件的节点的种类,一种是ElementNode,一种是TextNode。像<persons>、<person>这种节点就属于ElementNode,而name、age这种就属于TextNode。
XML结构示意图:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <persons> 3 <person id="23"> 4 <name>jack</name> 5 <age>30</age> 6 </person> 7 <person id="20"> 8 <name>rose</name> 9 <age>25</age> 10 </person> 11 </persons>
XML的结构解析如下:1、节点 2、元素 3 、属性和属性值
由于XML的扩展性强,致使它需要有稳定的基础规则来支持扩展,该语法规则是:1、开始和结束标签匹配;2、嵌套标签不能互相嵌套;3、区分大小写
Android中,常见的XML解析器分别为:
SAX解析器:SAX(org.xml.sax)Simple API for XML,以事件的形式通知程序,对Xml进行解析。
DOM解析器:DOM(org.w3c.dom)“文档对象模型”方式,解析完的Xml将生成一个树状结构的对象。
PULL解析器:XMLPULL(org.xmlpull.v1)类似于SAX方式,程序以“拉取”的方式对Xml进行解析。
---------------------
SAX解析器:是一种以事件驱动的XML api,由它定义的事件流可以指定从解析器传到专门的处理程序的代码的XML结构,
简单的讲,它解析速度快,占用内存少的解析器。这种解析器比较适合android 等移动设备。
使用SAX的优点是:因为SAX的优势是流的方式处理,当遇到一个标签的时候,并不会记录下当前所碰到的标签。也就是说,
startElement方法中,你所知道的信息,仅仅是当前的签名的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元素与其他结构相关的信息,都是不知道的。
xml文件被Sax解析器载入,由于Sax解析是按照xml文件的顺序来解析,当读入<?xml.....>时,会调用startDocument()方法;
当读入<books>的时候,由于它是个ElementNode,所以会调用startElement(String uri, String localName, String qName, Attributes attributes) 方法,其中第二个参数就是节点的名称,注意:由于有些环境不一样,有时候第二个参数有可能为空,所以可以使用第三个参数,因此在解析前,先调用一下看哪个参数能用,第4个参数是这个节点的属性;
这里我们不需要这个节点,所以从<book>这个节点开始,也就是图中1的位置,当读入时,调用startElement(....)方法,由于只有一个属性id,可以通过attributes.getValue(0)来得到;
然后在图中标明2的地方会调用characters(char[] ch, int start, int length)方法,不要以为那里是空白,Sax解析器可不那么认为,Sax解析器会把它认为是一个TextNode。
但是这个空白不是我们想要的数据,我们是想要<name>节点下的文本信息。这就要定义一个TAG,在characters(.....)方法中,判断当前节点是不是name,是再取值,才能取到thinking in java。
示例:将以上xml文件内容的id name age解析到hashmap中
第一步 定义handler类继承DefaultHandler并重写以下四个方法:
(org.xml.sax.helpers.DefaultHandler;)事件处理默认基类,需要用到的主要方法有:startDocument,接收到文档开始的通知;startElement,接收到元素开始的通知;characters,接收到元素中字符数据的通知;endElement,接收到结束解析的通知
1 定义变量:存储单个解析的完整对象HashMap<String, String> map
存储所有的解析对象 List<HashMap<String,String>> list
正在解析的元素的标签 String currentTag=null;
解析当前元素的值 String currentVal=null;
解析当前节点名称String nodeName=null;
并为list对象生成get方法和在构造方法中传递正在解析的节点名称
2.完成方法:
3.定义service 创建SAXParserFactory对象 SAXParser对象来解析xml,通过定义的list的get方法返回
4.定义http工具类 返回xml从服务器返回的输入流
5.建立测试类 指定网络路径
myHandler.java
1 package com.sax.handler; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 7 import org.xml.sax.Attributes; 8 import org.xml.sax.SAXException; 9 import org.xml.sax.helpers.DefaultHandler; 10 11 12 13 public class myHandler extends DefaultHandler{ 14 15 private HashMap<String, String> map=null;//存储单个解析的完整对象 16 private List<HashMap<String,String>> list=null;//存储所有的解析对象 17 private String currentTag=null;//正在解析的元素的标签 18 private String currentVal=null;//解析当前元素的值 19 private String nodeName=null;//解析当前节点名称 20 21 public List<HashMap<String, String>> getList() { 22 return list; 23 } 24 25 public myHandler(String nodeName) { 26 // TODO Auto-generated constructor stub 27 this.nodeName=nodeName; 28 } 29 30 //解析到开始文档 31 //当读到第一个开始标签的时候会触发这个方法 32 @Override 33 public void startDocument() throws SAXException { 34 // TODO Auto-generated method stub 35 System.out.println("--startDocument()--"); 36 list=new ArrayList<HashMap<String,String>>(); 37 } 38 39 //开始元素 40 //当遇到文档开头的时候会调用这个方法 41 @Override 42 public void startElement(String uri, String localName, String qname,Attributes attributes) throws SAXException { 43 // TODO Auto-generated method stub 44 //判断正在解析的元素是不是开始解析的元素 45 System.out.println("--startElement()--"+qname); 46 if(qname.equals(nodeName)){ 47 map=new HashMap<String, String>(); 48 } 49 if(attributes!=null&&map!=null){ 50 for (int i = 0; i < attributes.getLength(); i++) { 51 map.put(attributes.getQName(i), attributes.getValue(i)); 52 } 53 } 54 System.out.println(qname+":"+map); 55 currentTag=qname; 56 } 57 58 //元素内容 59 //用来处理xml文件所读取到的内容 60 @Override 61 public void characters(char[] ch, int start, int length) throws SAXException { 62 // TODO Auto-generated method stub 63 if(currentTag!=null&&map!=null){ 64 currentVal=new String(ch,start,length); 65 if(currentVal!=null&&!currentVal.trim().equals("")&&!currentVal.trim().equals("\n")){ 66 map.put(currentTag, currentVal); 67 } 68 } 69 System.out.println("--characters()--"+currentTag+" "+currentVal); 70 currentTag=null;//把当前节点对应标签和值设空 71 currentVal=null; 72 } 73 74 75 //结束解析 76 //遇到结束标记的时候会调用这个方法 77 @Override 78 public void endElement(String uri, String localName, String qName) 79 throws SAXException { 80 // TODO Auto-generated method stub 81 System.out.println("--endElement()--"+qName); 82 if(qName.equals(nodeName)){ 83 list.add(map); 84 map=null; 85 } 86 } 87 88 //结束解析文档 89 90 //结束解析文档,即解析根元素结束标签时调用该方法 91 @Override 92 public void endDocument() throws SAXException { 93 // TODO Auto-generated method stub 94 System.out.println("--endDocument()--"); 95 super.endDocument(); 96 } 97 }
httpUtils.java
1 package com.sax.http; 2 3 import java.io.InputStream; 4 import java.net.HttpURLConnection; 5 import java.net.URL; 6 7 public class httpUtils { 8 public httpUtils (){ 9 10 } 11 public static InputStream getXml(String path){ 12 InputStream inputStream=null; 13 try { 14 URL url=new URL(path); 15 if(url!=null){ 16 HttpURLConnection connection=(HttpURLConnection)url.openConnection(); 17 connection.setConnectTimeout(3000); 18 connection.setDoInput(true); 19 connection.setRequestMethod("GET"); 20 int code=connection.getResponseCode(); 21 if(code==200){ 22 inputStream=connection.getInputStream(); 23 } 24 25 } 26 } catch (Exception e) { 27 // TODO: handle exception 28 } 29 return inputStream; 30 } 31 }
saxService.java
1 package com.sax.service; 2 3 import java.io.InputStream; 4 import java.util.HashMap; 5 import java.util.List; 6 7 import javax.xml.parsers.SAXParser; 8 import javax.xml.parsers.SAXParserFactory; 9 10 import com.sax.handler.myHandler; 11 12 public class saxService { 13 14 public saxService() { 15 // TODO Auto-generated constructor stub 16 } 17 public static List<HashMap<String,String>> readXml(InputStream inputStream,String nodeName){ 18 try { 19 SAXParserFactory spf=SAXParserFactory.newInstance();//创建解析工厂对象 20 SAXParser parser=spf.newSAXParser();//用来解析xml 21 myHandler handler=new myHandler(nodeName); 22 parser.parse(inputStream,handler); 23 inputStream.close(); 24 return handler.getList(); 25 } catch (Exception e) { 26 // TODO: handle exception 27 } 28 return null; 29 } 30 31 }
test.java
1 package com.sax.test; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Map; 8 9 import com.sax.http.httpUtils; 10 import com.sax.service.saxService; 11 12 public class test { 13 14 /** 15 * @param args 16 */ 17 public static void main(String[] args) { 18 // TODO Auto-generated method stub 19 String path="http://122.206.79.193:8080/myhttp/person.xml"; 20 InputStream inputStream=httpUtils.getXml(path); 21 try { 22 List<HashMap<String,String>> list=saxService.readXml(inputStream, "person"); 23 for(HashMap<String,String> map:list){ 24 System.out.println(map.toString()); 25 } 26 } catch (Exception e) { 27 // TODO: handle exception 28 } 29 } 30 31 }
---------------------------------
XmlPull:
和Sax类似,是基于流(stream)操作文件,然后根据节点事件回调开发者编写的处理程序。
因为是基于流的处理,因此Xmlpull和 Sax都比较节约内存资源,不会象Dom那样要把所有节点以对橡树的形式展现在内存中。 但Xmlpull比Sax更简明,而且不需要扫描完整个流。
如开始元素和结束元素,使用parser.next()可以进行下一个元素并且触发相应的事件,事件将作为代码被发送,
因此可以使用一个switch来对事件进行选择,然后进行相应的处理。当开始解析元素时候,调用parser.nextText()方法可以获得下一个Text类型的元素。
ØPULL特点:
简单的结构:一个接口,一个例外,一个工厂组成的PULL解析器
Ø简单易用:PULL解析器只有一个重要的方法next方法,他被用来检索下一个事件,
而它只有5个常用的属性:START DOCUMENT;START_TAG;TEXT;END_TAG;END_DOCUMENT
优点:比sax简单
缺点:swtich时需要知道节点名称
务必记住需要导入kxml2-2.2.2.jar
示例:同上
person
httpUtils
pullXmlTools
test
-------------------------------
DOM(不推荐)
DOM是一种用于XML文档对象模型,DOM模式解析XML,是把整个XML文档当成一个对象来处理,会先把整个文档读入到内存里。
是基于树的结构,通常需要加载整文档和构造DOM树,然后才能开始工作。
可用于直接访问XML文档的各个部位,在DOM中文档被模拟为树状,其中XML语法的每一个组成部分都表示一个节点,DOM允许用户遍历文档树,从父节点移动到子节点和兄弟节点。并利用某节点类型特有的属性(元素具有属性,文本节点具有文本数据)
优点:a、由于整棵树在内存中,因此可以对xml文档随机访问
b、可以对xml文档进行修改操作
c、较sax,dom使用也更简单。
缺点:a、整个文档必须一次性解析完
b、由于整个文档都需要载入内存,对于大文档成本高
Ø节点(XML文档中的每一个成分都是一个节点)
DOM是这样规定的:整个文档是一个节点文档;每一个XML标签是一个元素节点;包含在XML元素中的文本是文本节点;每一个XML属性是一个属性节点
在这里当我们得到节点book时,也就是图中1所画的地方,如果我们调用它的getChildNodes()方法,它的子节点(不包括它的孙子节点,thinking in java这种的除外,因为它是孙子节点。)有5个,
分别是图中2、3、4、5、6所示的那样。所以在解析时,一定要小心,不要忽略空白的地方。
Ø从内存占用率来说: SAX和PULL比DOM占用的更少的内存解析方式,更加适合Android 手机开发。
person
http
dom
test