Android学习笔记(八)XML文档的解析

一、废话

  最近几天四川一直下雨,冷!今天到成都的时候,下午3点多的天和晚上天差不多,黑呼呼的... ...难道传说的2012来了?哈哈哈... ...

二、正文  

  在上一篇笔记中提到过说在Android系统中,存储数据的方式除了SQLite外,还有很多其他的方式,比较常用的就是XML方式。在Android中,比较常用的XML解析方式有SAX方式和DOM方式。下面就来看看这两种方式吧。

1、 SAX解析

  SAX——Simple API for XML,在org.xml.sax包中被提供使用。SAX是基于事件驱动的,有事件就一定有事件源,这个事件源就是SAX解析XML时的一个XMLReader对象。当XMLReader对象读取到XML文件的开始和结束标签时或者在取到一个节点内容时,都会触发在Handler(事件处理器)中注册的相应事件。

  在XMLReader中可以通过setContentHandler(ContentHandler handler)方法来调用我们自己的Handler,而这个Handler就是我们解析XML文件的核心。我们可以通过继承SDK中的DefaultHandler类来实现一个我们自己的Handler。针对我们今天的主题,主要需要实现以下几个方法。

  • public void startDocument() throws SAXException{}——读取到文档时触发的事件,通常可以通过这个事件来处理一些IO错误之类的事情。
  • public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException{}——读取到XML文档内容中的标签时触发,如<work></work>中的<work>标签。
    • uri  XML文档中NameSpace的URI,如果不清楚XML文档中Namespace的可以去网上看看。
    • localName  无前缀的标签名,如<works><work></work></works>标签,返回的可以是work字符串。
    • qName  有前缀具有完整路径的标签名,如<works><work></work></works>中返回的是/works/work字符串。
    • attributes  标签中的属性名,如<work id=”111”></work>这里面的id就是属性,而”111”就是属性值。
  • public void endElement(String uri, String localName, String qName)throws SAXException{}——读取到XML文档内容中的结束标签时触发。
  • public void endDocument() throws SAXException{}——读取到XML文档结尾时触发该事件。
  • public void characters(char[] ch, int start, int length)throws SAXException{}——读取到XML文档某个标签下的内容时,就会调用这个方法返回该内容。
    • ch  内容的字符值。
    • start   读取的开始位置。
    • length  读取的内容长度。

  a) 现在来理下要解析XML文档的整个思路

    • 新建一个SAXParserFactory对象,通过该对象的newSAXParser()方法来获得一个SAXParser对象。
    • 通过SAXParser对象的getXMLReader()方法来获得一个XMLReader对象。
    • 利用XMLReader对象的setConentHandler()方法来注册一个我们自己的Handler对象。
    • 利用XMLReader对象的parse()方法来开始处理我们的XML文档。
    • 实现自己的Handler类。

  b) 普通方式下的解析

 1 package LiB.XMLDemo;
2
3 import org.xml.sax.Attributes;
4 import org.xml.sax.SAXException;
5 import org.xml.sax.helpers.DefaultHandler;
6
7 public class SAXHandler extends DefaultHandler {
8
9 String tagName;
10 //当有值存在时,就调用该方法解析取值(如果是空值,也会调用这个方法)
11 @Override
12 public void characters(char[] ch, int start, int length)
13 throws SAXException {
14 String value= new String(ch, start,length);
15 if(tagName.equals("name"))
16 {
17 System.out.println("name="+ value);
18 }
19 if(tagName.equals("age"))
20 {
21 System.out.println("age="+value);
22 }
23 }
24   
25 @Override
26 public void endDocument() throws SAXException {
27
28 System.out.println("---end----");
29 }
30
31 @Override
32 public void endElement(String uri, String localName, String qName)
33 throws SAXException {
34 if(localName.equals("work"))
35 {
36 System.out.println("-----end----work");
37 }
38 }
39
40 @Override
41 public void startDocument() throws SAXException {
42
43 System.out.println("---begin----");
44 }
45
46 @Override
47 public void startElement(String uri, String localName, String qName,
48 Attributes attributes) throws SAXException {
49 tagName = localName;
50 if(localName.equals("work"))
51 {
52 for(int i=0;i< attributes.getLength();i++)
53 {
54 System.out.println(attributes.getLocalName(i)+"="+attributes.getValue(i));
55 }
56 }
57 }
58
59 }


  上面这个方法中存在一个问题:在读取出来的数据中,没区分开始标签和结束标签,所以出现了空值的状况。这个问题我一直都很奇怪,因为在不久前我处理的时候是不存在这个问题的,可是现在出现了。

  c) 改进后的解析

  解决的方法在网上也挺多的,而且大家都比较相似,就是在startElement和endElement方法中设置相应的标志位,然后在characters方法中通过标志位来决定是否需要读取它的内容。

  修改后的方法有兴趣的朋友可以把源码下载下来看看。

2、 DOM解析

  DOM方式解析XML文件呢,就需要将整个XML文档装入我们的手机内存中,如果文档过大,那么将非常的耗费内存,但是这样的好处是解析速度很快,同时DOM解析方式可以只解析你需要的那个部分,灵活性非常大。

  DOM解析的原理呢,其实就是把动过DOM API访问XML文档的树形结构,并获取相应的数据。在java中通过DOM解析XML文件,一般会涉及到以下几个类。

  • DocumentBuilderFactory——创建DocumentBuilder对象的工厂类。
  • DocumentBuilder——通过这个方法可以创建一个能够获取Document实例的API。
  • Document——加载XML文档的入口,这是解析文档的源所在。
  • Element——元素,在DOM中,所有的节点都可以称作Element。
  • NodeList——节点的集合。

  来看看通过DOM方式解析XML文档的步骤吧:

  • 通过javax.xml.parsers包中的DocumentBuilderFactory类的newInstance()方法新建一个DocumentBuilderFactory对象。
  • 通过DocumentBuilderFactory对象的newDocumentBuilder ()方法创建一个DoucumentBuilder对象。
  • 通过DoucumentBuilder的parse()方法读取外部流来创建一个Document对象。
  • 通过Document对象来获得文档中的所有节点的根节点。
  • 通过根节点来解析所需要的文件内容。
 1 package LiB.XMLDemo;
2
3
4 import javax.xml.parsers.DocumentBuilder;
5 import javax.xml.parsers.DocumentBuilderFactory;
6
7 import org.w3c.dom.Document;
8 import org.w3c.dom.Element;
9 import org.w3c.dom.Node;
10 import org.w3c.dom.NodeList;
11 import org.xml.sax.InputSource;
12
13 public class DomHandler {
14 public static void GetStringFromDom(InputSource inputSource) {
15 try {
16 DocumentBuilderFactory factory = DocumentBuilderFactory
17 .newInstance();
18 DocumentBuilder builder = factory.newDocumentBuilder();
19 Document document = builder.parse(inputSource);
20 //获取根节点
21 Element rootElement = document.getDocumentElement();
22 //获取第一级子节点
23 NodeList nodeList = rootElement.getElementsByTagName("work");
24 for(int i=0 ; i<nodeList.getLength();i++)
25 {
26 //String work = rootElement.getElementsByTagName("name").item(0).getFirstChild().getNodeValue();
27
28 Element workElement = ((Element)nodeList.item(i));
29 //获取节点中的属性值
30 //String attr= workElement.getAttribute("XXX");
31 //通过节点的标签名字来获取值
32 String name = workElement.getElementsByTagName("name").item(0).getFirstChild().getNodeValue();
33 String age = workElement.getElementsByTagName("age").item(0).getFirstChild().getNodeValue();
34 System.out.println("name="+name);
35 System.out.println("age="+age);
36 }
37
38 } catch (Exception e) {
39 }
40 }
41 }

  其实是用DOM方式来解析XML文件,有一些.NET和java开发经验的同学看到上面的代码都应该非常亲切,因为这和在.NET和java中相似。

3、 二者区别

  SAX——流式解析,通过事件模型解析XML文件,对内存消耗比较小。但是只能顺序解析,也就是说如果你需要的数据在文件的末尾,那么你将需要把整个XML文件全部解析才能得到你想要的数据。

  Dom解析——符合W3C标准的一种解析方式。解析速度非常快。在几乎所有的语言中,都能使用,可以解析你所需要的数据(不管这个数据在文件中间还是文件末尾)。但是这个需要全部加载进系统内存中才能进行解析。

 三、总结

  这这个笔记中介绍了两种解析XML文档的方法。从下篇笔记开始,我将介绍如何与蓝牙、WIFI、网络传输相关的一些知识。

【源码下载】

转载于:https://www.cnblogs.com/cxcco/archive/2012/01/10/2318420.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/475322.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 1196. 最多可以买到的苹果数量(贪心)

文章目录1. 题目2. 解题1. 题目 楼下水果店正在促销&#xff0c;你打算买些苹果&#xff0c;arr[i] 表示第 i 个苹果的单位重量。 你有一个购物袋&#xff0c;最多可以装 5000 单位重量的东西&#xff0c;算一算&#xff0c;最多可以往购物袋里装入多少苹果。 示例 1&#x…

3点 刚体运动 opencv_模态法动力学分析中的刚体模态

01—概述在对汽车结构进行动力学有限元分析时&#xff0c;无论是瞬态问题还是频响问题&#xff0c;都经常使用模态叠加法。模态叠加法动力学分析是常规模态分析的自然扩展&#xff0c;它利用结构振型来缩减问题求解规模&#xff0c;从而使数值求解更为高效。模态叠加法首先计算…

简单实用的铁道部12306.cn网站自动化登录

铁道部网站登录难点分析 必须使用微软IE浏览器 铁道部网站只支持IE在线付款网站使用Https协议 客户端不允许跨域访问 技术解析 使用微软IE开发者工具栏即可破解自动化登录过程开始步骤 使用IE8及其以上的版本&#xff0c;IE7及以下版本需要另外下载微软官方的IE开发者工具栏&a…

LeetCode 1064. 不动点(二分查找)

文章目录1. 题目2. 解题2.1 暴力搜2.2 二分查找1. 题目 给定已经按升序排列、由不同整数组成的数组 A&#xff0c;返回满足 A[i] i 的最小索引 i。 如果不存在这样的 i&#xff0c;返回 -1。 示例 1&#xff1a; 输入&#xff1a;[-10,-5,0,3,7] 输出&#xff1a;3 解释&…

vue 接口节流_vue输入节流,避免实时请求接口的实例代码

在做搜索的时候&#xff0c;当搜索页面只有一个输入框、没有确定按钮的时候&#xff0c;只能在用户输入时请求服务端&#xff0c;查询数据。这样会导致频繁的发送请求&#xff0c;造成服务端压力。解决这个问题&#xff0c;可以使用vue做输入节流。1、创建一个工具类&#xff0…

如何获取JavaCard剩余空间

0x01应用场景 获取JavaCard卡内剩余空间&#xff0c;一方面是在评估一张卡的时候需要用到&#xff0c;另一方面是在应用个人化或者运行时需要用到。 例如&#xff1a;应用提供商为了保证自己的应用在卡内运行期间能够不受空间影响&#xff0c;一般会在个人化(安装应用)的时候先…

LeetCode 1474. 删除链表 M 个节点之后的 N 个节点

文章目录1. 题目2. 解题1. 题目 给定链表 head 和两个整数 m 和 n. 遍历该链表并按照如下方式删除节点: 开始时以头节点作为当前节点. 保留以当前节点开始的前 m 个节点. 删除接下来的 n 个节点. 重复步骤 2 和 3, 直到到达链表结尾. 在删除了指定结点之后, 返回修改过后的链…

mac找不到mysql_mac找不到mysql

出现问题&#xff1a;macbook安装好mysql&#xff0c;并按照各路大神的说明进行了以下配置。打开Terminal&#xff0c;输入&#xff1a;vim .bash_profile进入编辑界面&#xff0c;添加以下内容&#xff1a;export PATH$PATH:/usr/local/mysql/bin按下esc键&#xff0c;输入 :w…

一个 SQL 同时验证帐号是否存在、密码是否正确

出处&#xff1a;http://www.cnblogs.com/jacklondon/archive/2012/01/13/2321686.html近日偶尔看到一个很巧妙的 SQL 技巧&#xff0c;一个简单的 SQL 同时验证帐号是否存在、密码是否正确。之前从未曾想过这么做&#xff0c;也未曾见过别人这么做。虽是奇技淫巧&#xff0c;却…

LeetCode 1427. 字符串的左右移

文章目录1. 题目2. 解题1. 题目 给定一个包含小写英文字母的字符串 s 以及一个矩阵 shift&#xff0c;其中 shift[i] [direction, amount]&#xff1a; direction 可以为 0 &#xff08;表示左移&#xff09;或 1 &#xff08;表示右移&#xff09;。 amount 表示 s 左右移的…

修改mysql数据库字符集_修改及查看mysql数据库的字符集

Liunx下修改MySQL字符集&#xff1a;1.查找MySQL的cnf文件的位置find / -iname *.cnf -print/usr/share/mysql/my-innodb-heavy-4G.cnf/usr/share/mysql/my-large.cnf/usr/share/mysql/my-small.cnf/usr/share/mysql/my-medium.cnf/usr/share/mysql/my-huge.cnf/usr/share/texm…

生成简单的Makefile文件(Python实现)

在linux下写几个测试程序&#xff0c;还要一行行的输入g命令进行编译&#xff0c;当经常改测试代码的时候&#xff0c;那一次次的敲&#xff08;或者一次次的上线箭头选&#xff09;也感觉不爽&#xff0c;不如make来的快。用Makefile的好处就不用多说了&#xff0c;这里我写了…

LeetCode 800. 相似 RGB 颜色

文章目录1. 题目2. 解题2.1 暴力枚举2.2 独立枚举1. 题目 RGB 颜色用十六进制来表示的话&#xff0c;每个大写字母都代表了某个从 0 到 f 的 16 进制数。 RGB 颜色 “#AABBCC” 可以简写成 “#ABC” 。例如&#xff0c;"#15c" 其实是 “#1155cc” 的简写。 现在&a…

mysql 图片base64_关于图片的Base64编码

什么是Base64编码Base64编码是一种图片处理格式&#xff0c;通过特定的算法将图片编码成一长串字符串&#xff0c;在页面上显示的时候&#xff0c;可以用该字符串来代替图片的url属性。base64编码就是长得像下面这样子的代码&#xff1a;thunder://QUFodHRwOi8vd3d3LmJhaWR1LmN…

LeetCode 243. 最短单词距离

文章目录1. 题目2. 解题1. 题目 给定一个单词列表和两个单词 word1 和 word2&#xff0c;返回列表中这两个单词之间的最短距离。 示例: 假设 words ["practice", "makes", "perfect", "coding", "makes"] 输入: word1 “…

mysql load character_mysql load data Invalid utf8mb4 character string: ”

使用mysql的 load data 导入数据到 数据库中&#xff1a;LOAD DATA LOCAL INFILE /tmp/2982/20200424/user.csvINTO TABLE t_user CHARACTER SET utf8mb4 FIELDS TERMINATED BY ,LINES TERMINATED BY \r\nIGNORE 1 LINES(userName, userNo, age, homeAddr)SET province 浙江省…

LeetCode 1426. 数元素(哈希set)

文章目录1. 题目2. 解题1. 题目 给你一个整数数组 arr&#xff0c; 对于元素 x &#xff0c;只有当 x 1 也在数组 arr 里时&#xff0c;才能记为 1 个数。 如果数组 arr 里有重复的数&#xff0c;每个重复的数单独计算。 示例 1&#xff1a; 输入&#xff1a;arr [1,2,3] …

mysql 默认page大小_MySQL innodb_page_size

原标题&#xff1a;MySQL innodb_page_size墨墨导读&#xff1a;Page是MySQL Innodb存储的最基本结构&#xff0c;也是Innodb磁盘管理的最小单位&#xff0c;了解page的一些特性&#xff0c;可以更容易理解MySQL。innodb_page_size作为innodb和OS交互单位。文件系统对文件的buf…

控制台中使用cstring和string

VC 6.0 控制台&#xff1a; 1、使用string   #include <string>using namespace std; 2、使用 cstring 首先设置"在共享 DLL 中使用 MFC"&#xff0c;然后 #include <afx.h>VS2003 控制台 1、使用string using namespace std; 2、使用csting   #incl…

LeetCode 266. 回文排列(计数)

文章目录1. 题目2. 解题1. 题目 给定一个字符串&#xff0c;判断该字符串中是否可以通过重新排列组合&#xff0c;形成一个回文字符串。 示例 1&#xff1a; 输入: "code" 输出: false示例 2&#xff1a; 输入: "aab" 输出: true示例 3&#xff1a; 输入…