sax dom pull 解析xml
来源:互联网 发布:sql语法范例大全 编辑:程序博客网 时间:2024/04/30 07:59
一 sax 解析:注意空格。
1. Java Sax解析是按照xml文件的顺序一步一步的来解析,在解析xml文件之前,我们要先了解xml文件的节点的种类,一种是ElementNode,一种是TextNode。如下面的这段book.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <books>
- <book id="12">
- <name>thinking in java</name>
- <price>85.5</price>
- </book>
- <book id="15">
- <name>Spring in Action</name>
- <price>39.0</price>
- </book>
- </books>
其中,像<books>、<book>这种节点就属于ElementNode,而thinking in java、85.5这种就属于TextNode。
下面结合一张图来详细讲解Sax解析。
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。具体见代码:SaxParseService.java
- import java.io.InputStream;
- import java.util.ArrayList;
- import java.util.List;
- import javax.xml.parsers.SAXParser;
- import javax.xml.parsers.SAXParserFactory;
- import org.xml.sax.Attributes;
- import org.xml.sax.SAXException;
- import org.xml.sax.helpers.DefaultHandler;
- import com.xtlh.cn.entity.Book;
- public class SaxParseService extends DefaultHandler{
- private List<Book> books = null;
- private Book book = null;
- private String preTag = null;//作用是记录解析时的上一个节点名称
- public List<Book> getBooks(InputStream xmlStream) throws Exception{
- SAXParserFactory factory = SAXParserFactory.newInstance();
- SAXParser parser = factory.newSAXParser();
- SaxParseService handler = new SaxParseService();
- parser.parse(xmlStream, handler);
- return handler.getBooks();
- }
- public List<Book> getBooks(){
- return books;
- }
- @Override
- public void startDocument() throws SAXException {
- books = new ArrayList<Book>();
- }
- @Override
- public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
- if("book".equals(qName)){
- book = new Book();
- book.setId(Integer.parseInt(attributes.getValue(0)));
- }
- preTag = qName;//将正在解析的节点名称赋给preTag
- }
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- if("book".equals(qName)){
- books.add(book);
- book = null;
- }
- preTag = null;/**当解析结束时置为空。这里很重要,例如,当图中画3的位置结束后,会调用这个方法
- ,如果这里不把preTag置为null,根据startElement(....)方法,preTag的值还是book,当文档顺序读到图
- 中标记4的位置时,会执行characters(char[] ch, int start, int length)这个方法,而characters(....)方
- 法判断preTag!=null,会执行if判断的代码,这样就会把空值赋值给book,这不是我们想要的。*/
- }
- @Override
- public void characters(char[] ch, int start, int length) throws SAXException {
- if(preTag!=null){
- String content = new String(ch,start,length);
- if("name".equals(preTag)){
- book.setName(content);
- }else if("price".equals(preTag)){
- book.setPrice(Float.parseFloat(content));
- }
- }
- }
- }
Book.java如下:主要是用来组装数据
- 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 setName(String name) {
- this.name = name;
- }
- public float getPrice() {
- return price;
- }
- public void setPrice(float price) {
- this.price = price;
- }
- @Override
- public String toString(){
- return this.id+":"+this.name+":"+this.price;
- }
- }
测试是用的单元测试,测试代码如下:ParseTest
- import java.io.InputStream;
- import java.util.List;
- import junit.framework.TestCase;
- import com.xtlh.cn.demo.DomParseService;
- import com.xtlh.cn.demo.SaxParseService;
- import com.xtlh.cn.entity.Book;
- public class ParseTest extends TestCase{
- public void testSAX() throws Throwable{
- SaxParseService sax = new SaxParseService();
- InputStream input = this.getClass().getClassLoader().getResourceAsStream("book.xml");
- List<Book> books = sax.getBooks(input);
- for(Book book : books){
- System.out.println(book.toString());
- }
- }
- }
在用Sax解析的时候最需要重视的一点就是不要把那些<节点>之间的空白忽略就好!
二 JAVA使用DOM解析XML: 注意空格,空格也属于子节点。
首先来了解点Java DOM 的 API:
1.解析器工厂类:DocumentBuilderFactory
创建的方法:DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2.解析器:DocumentBuilder
创建方法:通过解析器工厂类来获得 DocumentBuilder db = dbf.newDocumentBuilder();
3.文档树模型Document
创建方法:a.通过xml文档 Document doc = db.parse("bean.xml"); b.将需要解析的xml文档转化为输入流InputStream is = new FileInputStream("bean.xml");
Document doc = db.parse(is);
Document对象代表了一个XML文档的模型树,所有的其他Node都以一定的顺序包含在Document对象之内,排列成一个树状结构,以后对XML文档的所有操作都与解析器无关,
直接在这个Document对象上进行操作即可;
包含的方法:
4.节点列表类NodeList
NodeList代表了一个包含一个或者多个Node的列表,根据操作可以将其简化的看做为数组
5.节点类Node
Node对象是DOM中最基本的对象,代表了文档树中的抽象节点。但在实际使用中很少会直接使用Node对象,而是使用Node对象的子对象Element,Attr,Text等
6.元素类Element
是Node类最主要的子对象,在元素中可以包含属性,因而Element中有存取其属性的方法
7.属性类Attr
代表某个元素的属性,虽然Attr继承自Node接口,但因为Attr是包含在Element中的,但并不能将其看做是Element的子对象,因为Attr并不是DOM树的一部分
基本的知识就到此结束,更加具体的大家可以参阅JDK API文档
代码:
1.使用DOM来遍历XML文档中的全部内容并且插入元素:
school.xml文档:
DomDemo.java
运行后结果:
然后到目录下查看生成的xml文件:
打开查看内容:
上面添加元素后输出的文件与之前的文件不是同一个文件,如果需要输出到原文件中,那么只要将路径改为原文间路径即可:src/xidian/sl/dom/school.xml
2.创建XML过程与插入过程相似,就是Document需要创建
运行结果:
DOM的操作应该还是非常简单明了的,掌握了没哦
三 pull 解析xml:
XmlPull和Sax类似,是基于流(stream)操作文件,然后根据节点事件回调开发者编写的处理程序。因为是基于流的处理,因此Xmlpull和 Sax都比较节约内存资源,不会象Dom那样要把所有节点以对橡树的形式展现在内存中。 但Xmlpull比Sax更简明,而且不需要扫描完整个流。
下面来看一个pull解析xml的例子:
student.xml:
- <?xml version="1.0" encoding="utf-8"?>
- <root>
- <student id="1" group="1">
- <name>张三</name>
- <sex>男</sex>
- <age>18</age>
- <email>zhangsan@163.com</email>
- <birthday>1987-06-08</birthday>
- <memo>好学生</memo>
- </student>
- <student id="2" group="2">
- <name>李四</name>
- <sex>女</sex>
- <age>18</age>
- <email>lisi@163.com</email>
- <birthday>1987-06-08</birthday>
- <memo>好学生</memo>
- </student>
- <student id="3" group="3">
- <name>小王</name>
- <sex>男</sex>
- <age>18</age>
- <email>xiaowang@163.com</email>
- <birthday>1987-06-08</birthday>
- <memo>好学生</memo>
- </student>
- <student id="4" group="4">
- <name>小张</name>
- <sex>男</sex>
- <age>18</age>
- <email>xiaozhang@163.com</email>
- <birthday>1987-06-08</birthday>
- <memo>好学生</memo>
- </student>
- <student id="5" group="5">
- <name>小明</name>
- <sex>男</sex>
- <age>18</age>
- <email>xiaoming@163.com</email>
- <birthday>1987-06-08</birthday>
- <memo>好学生</memo>
- </student>
- </root>
- public class Student {
- private int id;
- private int group;
- private String name;
- private String sex;
- private int age;
- private String email;
- private String memo;
- private String birthday;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public int getGroup() {
- return group;
- }
- public void setGroup(int group) {
- this.group = group;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getSex() {
- return sex;
- }
- public void setSex(String sex) {
- this.sex = sex;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getEmail() {
- return email;
- }
- public void setEmail(String email) {
- this.email = email;
- }
- public String getMemo() {
- return memo;
- }
- public void setMemo(String memo) {
- this.memo = memo;
- }
- public String getBirthday() {
- return birthday;
- }
- public void setBirthday(String birthday) {
- this.birthday = birthday;
- }
- }
主要的解析和现实类:
- import java.io.InputStream;
- import java.util.ArrayList;
- import java.util.List;
- import org.xmlpull.v1.XmlPullParser;
- import org.xmlpull.v1.XmlPullParserFactory;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.view.ViewGroup.LayoutParams;
- import android.widget.LinearLayout;
- import android.widget.TextView;
- public class PullActivity extends Activity implements Runnable{
- private TextView pullTextView ;
- private LinearLayout layout;
- private Handler handler=new Handler(){
- public void handleMessage(android.os.Message msg) {
- List<Student> lists=(List<Student>) msg.obj;
- for(int i=0;i<lists.size();i++){
- Student student=lists.get(i);
- StringBuffer sb=new StringBuffer();
- sb.append(student.getId()+" ").append(student.getName()+" ")
- .append(student.getAge()+" ").append(student.getSex()+" ").append(student.getBirthday()+" ")
- .append(student.getEmail()+" ").append(student.getGroup()+" ");
- TextView txt=new TextView(getApplicationContext());
- txt.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- txt.setText(sb.toString());
- layout.addView(txt);
- }
- };
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- setContentView(R.layout.pull);
- pullTextView=(TextView) this.findViewById(R.id.pullTextView);
- layout=(LinearLayout) this.findViewById(R.id.layout);
- new Thread(this).start();
- }
- //pull解析xml
- public List<Student> pullParseXml(){
- List<Student> lists=null;
- Student student=null;
- try {
- XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
- //获取XmlPullParser实例
- XmlPullParser pullParser=factory.newPullParser();
- InputStream in=this.getClass().getClassLoader().getResourceAsStream("student.xml");
- pullParser.setInput(in, "UTF-8");
- //开始
- int eventType=pullParser.getEventType();
- while(eventType!=XmlPullParser.END_DOCUMENT){
- String nodeName=pullParser.getName();
- switch (eventType) {
- //文档开始
- case XmlPullParser.START_DOCUMENT:
- lists=new ArrayList<Student>();
- break;
- //开始节点
- case XmlPullParser.START_TAG:
- if("student".equals(nodeName)){
- student=new Student();
- student.setId(Integer.parseInt(pullParser.getAttributeValue(0)));
- student.setGroup(Integer.parseInt(pullParser.getAttributeValue(1)));
- }else if("name".equals(nodeName)){
- student.setName(pullParser.nextText());
- }else if("sex".equals(nodeName)){
- student.setSex(pullParser.nextText());
- }else if("age".equals(nodeName)){
- student.setAge(Integer.parseInt(pullParser.nextText()));
- }else if("email".equals(nodeName)){
- student.setEmail(pullParser.nextText());
- }else if("birthday".equals(nodeName)){
- student.setBirthday(pullParser.nextText());
- }else if("memo".equals(nodeName)){
- student.setMemo(pullParser.nextText());
- }
- break;
- //结束节点
- case XmlPullParser.END_TAG:
- if("student".equals(nodeName)){
- lists.add(student);
- student=null;
- }
- break;
- default:
- break;
- }
- // 手动的触发下一个事件
- eventType=pullParser.next();
- }
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return lists;
- }
- @Override
- public void run() {
- // TODO Auto-generated method stub
- List<Student> lists=pullParseXml();
- Message msg=handler.obtainMessage();
- msg.obj=lists;
- handler.sendMessage(msg);
- }
- }
注意xml中的<?xml version="1.0" encoding="utf-8"?> 这句话要顶格显示,不要留空隙,附则错了很难调试的。
解析后效果:
四 三者不同点
对于Android的移动设备而言,因为设备的资源比较宝贵,内存是有限的,所以我们需要选择适合的技术来解析XML,这样有利于提高访问的速度。
DOM在处理XML文件时,将XML文件解析成树状结构并放入内存中进行处理。当XML文件较小时,我们可以选DOM,因为它简单、直观,可以生产,修改xml
SAX则是以事件作为解析XML文件的模式,它将XML文件转化成一系列的事件,由不同的事件处理器来决定如何处理。XML文件较大时,选择SAX技术是比较合理的。虽然代码量有些大,但是它不需要将所有的XML文件加载到内存中。这样对于有限的Android内存更有效,而且Android提供了一种传统的SAX使用方法以及一个便捷的SAX包装器。 使用Android.util.Xml类,从示例中可以看出,会比使用 SAX来得简单,没有修改,生产xml
XML pull解析并未像SAX解析那样监听元素的结束,而是在开始处完成了大部分处理。这有利于提早读取XML文件,可以极大的减少解析时间,这种优化对于连接速度较漫的移动设备而言尤为重要。对于XML文档较大但只需要文档的一部分时,XML Pull解析器则是更为有效的方法,可以生成xml
SAX
优点:①无需将整个文档加载到内存,因而内存消耗少
②推模型允许注册多个ContentHandler
缺点:①没有内置的文档导航支持
②不能够随机访问XML文档
③不支持在原地修改XML
④不支持名字空间作用域
最适合于:只从XML读取数据的应用程(不可用于操作或修改XML文档)
DOM
优点:①易于使用
②丰富的API集合,可用于轻松地导航
③整棵树加载到内存,允许对XML文档进行随机访问
缺点:①整个XML文档必须一次解析完
②将整棵树加载到内存成本较高
③一般的DOM节点对于必须为所有节点创建对象的对象类型绑定不太理想
最适合于:需要修改XML文档的应用程序或XSLT应用程序(不可用于只读XML的应用程序)
- sax、dom、pull解析xml
- SAX、DOM、PULL解析XML
- Dom Sax Pull解析xml
- sax、dom、pull解析xml
- sax、dom、pull解析xml
- sax dom pull 解析xml
- 解析XML:DOM、SAX、PULL
- DOM、SAX、Pull解析XML
- pull,sax,dom解析XML
- 解析XML:DOM,SAX,PULL
- DOM、SAX、Pull解析XML
- xml解析:Sax,Dom,pull解析
- 解析XML(SAX、DOM、PULL、dom4j)
- Android SAX,DOM,PULL解析XML文档
- android sax dom pull 解析 xml
- Dom sax pull解析xml的差异
- Android中XML解析DOM/SAX/PULL
- Android系列--DOM、SAX、Pull解析XML
- Sencha Touch 2入门:创建一个实用的天气应用程序之一
- Java NIO系列教程(十) Java NIO DatagramChannel
- Quick-Cocos2d-X 3.3 笔记(草稿)
- 浅谈sql中的in与not in,exists与not exists的区别
- 面向对象与面向过程
- sax dom pull 解析xml
- aChartEngine图表显示(饼图、柱状图、折线图)
- 背包九讲的读书笔记
- Sencha Touch 2入门:创建一个实用的天气应用程序之二
- 新注册BandwagonHost搬瓦工账户无法看到验证码解决方法
- Android硬件传感器专题[2]——测试手机中有哪些传感器
- 耦合与内聚
- HTML用来显示计算机代码的标签 pre 预定义格式标签
- svd矩阵奇异值分解