Android--解析XML之DOM
前言
前面已经介绍了Android平台下两种解析XML的方法,SAX和PULL,这两个均为事件驱动,以流的形式解析XML文档。现在介绍一种新的方式DOM方式解析XML。
DOM是一种用于XML文档对象模型,可用于直接访问XML文档的各个部位,在DOM中文档被模拟成树状,其中XML语法的每一组成部分都表示一个节点,DOM允许用户遍历文档树,从父节点移动到子节点和兄弟节点。并利用某节点类型特有的属性(元素具有属性,文本节点具有文本数据)。
对于DOM而言,XML文档中每一个成分都是一个节点。
DOM是这样规定的:
- 整个文档是一个文档节点。
- 每一个XML标签是一个元素节点。
- 包含在XML元素中的文本是一个文本节点。
- 每一个XML属性是一个属性节点。
DOM解析XML
DOM解析XML也是需要一个工厂类DocumentBuilderFactory,这一点和SAX、PULL类似。工厂类也是单例模式,没有提供共有的构造函数,需要使用静态的newInstance()方法获得,并且需要工厂类来获取DOM解析器实例,使用DocumentBuilderFactory.newDocumentBuilder()获得的DocumentBuilder对象。
当获得Document之后,就可以使用parse()解析XML文档,parser多个重载,可以适用于不同的输入。
下面介绍一下在DOM解析XML过程中,会碰上几个对象,Element、NodeList、Node。说也不太好说清楚,画个图解释一下更直观。
从图上可以看出,Element为一个元素,可以通过这个元素获取到该元素的属性值(Attribute),以及它的子节点的集合NodeList。而NodeList作为一个装载平级节点的集合,可以通过NodeList获得它内装载的所有平级节点,可以通过索引获取。对于Node,表示最终的节点,根据图示说的,其实Jack文本也是一个文本节点(Node),Node可以获取其节点名称、其值、其属性。所以它们三个是可以相互嵌套的,也不存在说谁一定要在谁的外侧或是内层。
示例程序
既然已经说了那么多了,现在通过一个示例程序展示一下DOM解析XML。这是一个Android应用程序,为了模拟真实的环境,通过网络读取IIS上的一个静态XML文件内容。直接上代码,注释已经写的很清楚了。
IIS上的静态XML文档内容:
<?xml version="1.0" encoding="utf-8" ?>
- <persons>
- <person id="23">
<name>Jack</name>
<age>21</age>
</person>
- <person id="20">
<name>Dick</name>
<age>23</age>
</person>
</persons>
DomService,解析网络传输来的XML文档流:
package cn.bgxt.service; import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import cn.bgxt.domain.Person; public class DomService { public DomService() {
// TODO Auto-generated constructor stub
} public static List<Person> getPersons(InputStream inputStream) throws Exception
{
List<Person> list=new ArrayList<Person>();
//获取工厂对象,以及通过DOM工厂对象获取DOMBuilder对象
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
//解析XML输入流,得到Document对象,表示一个XML文档
Document document=builder.parse(inputStream);
//获得文档中的次以及节点,persons
Element element=document.getDocumentElement();
// 获取Element下一级的person节点集合,以NodeList的形式存放。
NodeList personNodes=element.getElementsByTagName("person");
for(int i=0;i<personNodes.getLength();i++)
{
//循环获取索引为i的person节点
Element personElement=(Element) personNodes.item(i);
Person person=new Person();
//通过属性名,获取节点的属性id
person.setId(Integer.parseInt(personElement.getAttribute("id")));
//获取索引i的person节点下的子节点集合
NodeList childNodes=personElement.getChildNodes();
for(int j=0;j<childNodes.getLength();j++)
{
//循环遍历每个person下的子节点,如果判断节点类型是ELEMENT_NODE,就可以依据节点名称给予解析
if(childNodes.item(j).getNodeType()==Node.ELEMENT_NODE)
{
if("name".equals(childNodes.item(j).getNodeName()))
{
//因为文本也是一个文本节点,
//所以这里读取到name节点的时候,
//通过getFirstChild()可以直接获得name节点的下的第一个节点,就是name节点后的文本节点
//取其value值,就是文本的内容
person.setName(childNodes.item(j).getFirstChild().getNodeValue());
}
else if("age".equals(childNodes.item(j).getNodeName()))
{
person.setAge(Integer.parseInt(childNodes.item(j).getFirstChild().getNodeValue()));
}
}
}
//把解析的person对象加入的list集合中
list.add(person);
}
return list;
}
}
从IIS服务器上获取XML的方式,在另外一篇博客:HTTP协议。中已经介绍了,如果不明白可以去看看,这里就不介绍了。
Activity的布局就是一个按钮,用于点击出发解析事件,因为是Android4.0+的环境,需要无法在主线程中访问网络,需要使用到多线程的技术,并且不要网了给Android应用增加访问网络的权限。
package cn.bgxt.xmlfordom; import java.io.InputStream;
import java.util.List;
import cn.bgxt.domain.Person;
import cn.bgxt.http.HttpUtils;
import cn.bgxt.service.DomService;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button; public class MainActivity extends Activity { private Button button; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); button=(Button)findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) {
// Android 4.0+不能在主线程中访问网络
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
try {
String path="http://192.168.1.107:1231/persons.xml";
InputStream inputStream=HttpUtils.getXML(path);
List<Person> list=DomService.getPersons(inputStream);
for(Person person:list)
{
//以日志的形式打印对象内容
Log.i("DOM", person.toString());
}
} catch (Exception e) {
// TODO: handle exception
}
} });
thread.start();
} }); } }
如果解析成功,可以在LogCat中查看到日志。
总结
现在已经讲解的常用的Android应用中解析XML的方法,DOM和PULL、SAX不一样,是文档模型形式的,在解析的时候会把整个XML的内容都读取到内存中,这样对于移动设备而言,是很消耗内存的。而PULL以及SAX都是事件驱动,逐行去解析XML的内容,相对而言保证了解析速度又不会很损耗内存。所以Android应用中一般不推荐使用DOM解析XML,还是偏向于使用SAX、PULL。但是DOM也有它的优点,正因为它是把整个文档都读取到内存中了,可以指定需要查找的数据而无需遍历所有的节点,对于内容比较少的XML而言,还是很方便的。所以解析XML的方法有很多,无法绝对的说明谁好谁坏,主要还是看需求设定的环境来取舍的。
请支持原创,尊重原创,转载请注明出处。谢谢。
Android--解析XML之DOM的更多相关文章
- android解析XML总结(SAX、Pull、Dom三种方式) <转载>
android解析XML总结(SAX.Pull.Dom三种方式) http://www.cnblogs.com/JerryWang1991/archive/2012/02/24/2365507.htm ...
- Android解析XML
在Android平台上可以使用Simple API for XML(SAX) . Document Object Model(DOM)和Android附带的pull解析器解析XML文件. 下面是本例子 ...
- 解析XML:DOM,SAX,PULL
Android解析XML有三种方式:DOM(document object model).SAX(simple api XML).PULL 1.DOM DOM解析XML文件时,会将XML文件的所有内容 ...
- android解析xml文件的方式
android解析xml文件的方式 作者:东子哥 ,发布于2012-11-26,来源:博客园 在androd手机中处理xml数据时很常见的事情,通常在不同平台传输数据的时候,我们就可能使用xm ...
- JAVA解析XML之DOM方式
JAVA解析XML之DOM方式 准备工作 创建DocumentBuilderFactory对象; 创建DocumentBuilder对象; 通过DocumentBuilder对象的parse方法 ...
- Android解析xml文件-采用DOM,PULL,SAX三种方法解析
解析如下xml文件 <?xml version="1.0" encoding="UTF-8"?> <persons> <perso ...
- android解析xml文件方法之一-----DOM
Hello.xml文件 <dict num="219" id="219" name="219"> <key>hell ...
- [android]解析XML文件的方法有三种:PULL,DOM,SAM
PULL 的工作原理: XML pull提供了开始元素和结束元素.当某个元素开始时,可以调用parser.nextText从XML文档中提取所有字符数据.当解析到一个文档结束时,自动生成EndDocu ...
- android 解析XML方式(二)
上一节中,我们使用DOM方式解析xml文档,该方式比较符合我们日常思维方式,容易上手,但是它直接把文档调入内存中,比较耗内存.在这里我们可以用另外一种方式解析xml,这个就是SAX方式. SAX即是: ...
- android 解析XML方式(一)
在androd手机中处理xml数据时很常见的事情,通常在不同平台传输数据的时候,我们就可能使用xml,xml是与平台无关的特性,被广泛运用于数据通信中,那么在android中如何解析xml文件数据呢? ...
随机推荐
- Qt5对XML文件操作
转自https://blog.csdn.net/hpu11/article/details/80227093 写入xml //写xml void WriteXml() { //打开或创建文件 QFil ...
- 预装win8的笔记本用第三方分区软件分区后出现0x0000225错误的解决方法/同理win7
最近为采用EFI分区的联想电脑分区,是通过第三方软件进行的,完成后重启,发现系统报错0x0000225,提示插入安装介质修复. 应该是EFI分区导致的 http://zhidao.baidu.com/ ...
- [Java算法] -- 1. 常用排序之冒泡排序和选择排序
使用Java语言实现冒泡排序和选择排序 推荐一个数据结构可视化的网站:http://zh.visualgo.net/zh (暂时访问不了) 对排序不太熟悉的朋友,建议去上面的网站学习一下,你将会发现一 ...
- elasticsearch中 refresh 和flush区别(转)
elasticsearch中有两个比较重要的操作:refresh 和 flush refresh操作 当我们向ES发送请求的时候,我们发现es貌似可以在我们发请求的同时进行搜索.而这个实时建索引并可以 ...
- Day10 (黑客成长日记) Urllib库的使用
什么是Urllib: Urllib是python内置的HTTP请求库包括以下模块urllib.request 请求模块urllib.error 异常处理模块urllib.parse url解析模块ur ...
- Maven搭建SSH框架
工具:Eclipse(Maven管理工具)+Tomcat+Mysql. 1.新建一个Maven工程(maven-archetype-webapp). 打开File ——>new——>Mav ...
- C++标准库之string返回值研究
先说结论(不一定适用所有环境): 1) GCC默认开启了返回值优化(RVO),除非编译时指定“-fno-elide-constructors”: 2) 现代C++编译器一般都支持返回值优化: 3) s ...
- 2019年华南理工校赛(春季赛)--L--剪刀石头布(签到)
#include <iostream> using namespace std; int main(){ string a,b,c,d; a="Scissors"; b ...
- Java工具eclipse控制台console输出乱码问题
捣鼓了一下午,终于tm解决! 我的是Scanner读入,println打印乱码问题. 首先在cmd窗口运行java,是没有乱码问题的,这证明了在cmd窗口时Scanner输入的和println打印的编 ...
- python基础自学 第二天
注释 分类 单行注释 多行注释 作用 使用自己熟悉的语言,在程序中对某些代码进行标注说明,增强程序可读性 单行注释(行注释) 以 # 开头,#右边所有的东西就被当成说明文字,而不是要执行的程序,只是说 ...