Android 之xml解析

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

时间: 2024-10-26 17:45:16

Android 之xml解析的相关文章

Android学习xml解析大全之SAX和DOM

  随着android的学习解析xml成为了很多朋友面临的问.想学习如何解析xml就要先了解xml是什么. XML称为可扩展标记语言(Extensible Markup Language),由标准通用标记语言(SGML:Standard Generalized Markup Language)发展而来,允许开发者自定义标签,可以实现标签和内容的有效分离. 与HTML不同,XML不再侧重于数据如何表现,而是更多的关注数据如何存储和传输.因此,XML逐渐演变成为一种跨平台的数据交换格式.通过使用XM

Android实现XML解析技术

http://www.cnblogs.com/hanyonglu/archive/2012/02/28/2370675.html http://weizhulin.blog.51cto.com/1556324/311678 Android实现XML解析技术

Android中XML解析-PULL解析

前面写了两篇XML解析的Dom和SAX方式,Dom比较符合思维方式,SAX事件驱动注重效率,除了这两种方式以外也可以使用Android内置的Pull解析器解析XML文件. Pull解析器的运行方式与 SAX 解析器相似,也是事件触发的.Pull解析方式让应用程序完全控制文档该怎么样被解析,比如开始和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件.通过Parser.getEventType()方法来取得事件的代码值,解析是在开始时就完成了大部分处理.事件将作为数值代码

Android中XML解析-Dom解析

Android中需要解析服务器端传过来的数据,由于XML是与平台无关的特性,被广泛运用于数据通信中,有的时候需要解析xml数据,格式有三种方式,分别是DOM.SAX以及PULL三种方式,本文就简单以Dom解析为例,解析XML, DOM方式解析xml是先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据的,但是这样一来,如果xml文件很大,手机CPU处理能力比PC差,因此在处理效率方面就相对差了,使用Dom解析就不是太合适了. 基础维护 首先下assets目录下新建一个Bo

Android 简易XML解析

首先创建在Android工程中创建一个Assets文件夹 app/src/main/assets 在这里添加一个名为 data.xml的文件,然后编辑这个文件,加入如下XML格式内容 <?xml version="1.0" encoding="utf-8"?> <apps> <app> <id>1</id> <name>Google Maps</name> <version&g

Android中XML解析

package com.example.thebroadproject; public class Book { private int id; private String name; private float price; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setN

android之XML解析

所谓SAX,就是SAX simple API for XML,是一个解析XML文件的简单API. SAX解析XML的工作原理,是对文档进行顺序扫描,当扫描到文档开始与结束,元素开始与结束,触发相应的响应函数.是一种事件驱动型的解析方式.它可以在解析文档的任意时刻停止解析. 通过该图我们可以大概了解解析的过程. private void parse(String xmlString,List<Mp3Info> infos){ // SAXParserFactory 是一个使用工厂模式的类 SAX

Android自定义xml解析

<?xml version="1.0" encoding="utf-8"?> <resources> <Users> <User name="jason" age="12" location="Beijing"/> <User name="peter" age="18" location="Shangha

Android APK XML解析与反编译方法

APK中的XML为何不能直接打开,是否只是简单的二进制文件,难道被加密了?为什么AXMLPrinter2反编译的时候竟然报错了,如何解决? java.lang.ArrayIndexOutOfBoundsException: 128 at android.content.res.StringBlock.getShort(StringBlock.java:231) at android.content.res.StringBlock.getString(StringBlock.java:91) at