students.xml

<?xml version="1.0" encoding="UTF-8"?>
<students><student id="1"><name>张珊</name><age>22</age></student><student id="2"><name>王航</name><age>25</age></student><student id="3"><name>刘沙</name><age>26</age></student><student id="4"><name>张海</name><age>24</age></student>
</students>

Person.java

package xmldom;public class Person {int id;String name;int age;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 int getAge() {return age;}public void setAge(int age) {this.age = age;}}

一,DOM方式解析XML就是先把XML文档都读到内存中,然后在用户DOMAPI来访问树形结构,获取数据

解析的思路是:

1,将xml文件加载进来

2,获取文档的根节点

3,获取文档根节点中的所有子节点的列表

4,获取子节点列表中需要多去的节点信息

首先创建一个DocumentBuilderFactory实例,然后通过该实例来加载XML文档(Document)文档加载完毕以后,进行节点获取,先找到根节点,在找到子节点。

package xmldom;import java.io.File;
import java.io.IOException;
import java.util.ArrayList;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.NodeList;
import org.xml.sax.SAXException;public class Main {/*** @param args*/public static void main(String[] args) {ArrayList<Person> studentslist=new ArrayList<Person>();DocumentBuilderFactory factory=null;//DOM解析器工厂DocumentBuilder builder=null;//DOM解析器Document document=null;//文档对象try {//1,实例化DOM解析器工厂,工厂的作用是创建具体的解析器factory=DocumentBuilderFactory.newInstance();//2,通过工厂获得DOM解析器builder=factory.newDocumentBuilder();//3,通过DOM解析器获得文档对象,可以解析File,InputStream等document=builder.parse(new File("students.xml"));//把这个文档放在项目的根路径下,与src目录平行,就可以使用相对路径来引用了//4,获取文档的根节点Element root=document.getDocumentElement();//5,由根节点获取子节点列表NodeList nodelist=root.getElementsByTagName("student");//遍历每个子节点Person person=null;for(int i=0;i<nodelist.getLength();i++){person=new Person();// 获得元素,将节点强制转换为元素。此时element就是一个具体的元素Element studentelement=(Element) nodelist.item(i);                       String id=studentelement.getAttribute("id");//元素获得属性值person.setId(Integer.valueOf(id));//获取子元素:子元素name只有一个节点.所以是item(0)Element Name=(Element) studentelement.getElementsByTagName("name").item(0);person.setName(Name.getFirstChild().getNodeValue());//获得子元素的值,一定要加getFirstChild//获取子元素:子元素name只有一个节点.所以是item(0)Element Age=(Element) studentelement.getElementsByTagName("age").item(0);person.setAge(new Integer(Age.getFirstChild().getNodeValue()));//获得子元素的值,一定要加getFirstChildstudentslist.add(person);}                              } catch (ParserConfigurationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}for(int i=0;i<studentslist.size();i++){System.out.println("ID:"+studentslist.get(i).getId()+" 姓名:"+studentslist.get(i).getName()+" 年龄:"+studentslist.get(i).getAge());                }}}

结果:

ID:1 姓名:张珊 年龄:22
ID:2 姓名:王航 年龄:25
ID:3 姓名:刘沙 年龄:26
ID:4 姓名:张海 年龄:24

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对象上进行操作即可;

Document的方法:

4.节点列表类NodeList
NodeList代表了一个包含一个或者多个Node的列表,根据操作可以将其简化的看做为数组


5.节点类Node
Node对象是DOM中最基本的对象,代表了文档树中的抽象节点。但在实际使用中很少会直接使用Node对象,而是使用Node对象的子对象Element,Attr,Text等
6.元素类Element
是Node类最主要的子对象,在元素中可以包含属性,因而Element中有存取其属性的方法

二,使用SAX解析XML

SAX是Simple API for XML的缩写,比DOM速度更快,更有效,占用内存更小。他是逐行扫描,边扫描边解析,流式处理,是基于事件驱动的,就是不用完全解析整个文档,在按内容顺序解析文档过程中,SAX会判断当前读到的字符是否符合XML文件语法的某部分,如果符合,就会触发事件,就是调用一些回调方法

使用SAX解析XML的几个步骤:

1,创建SAXParserFactory对象

2,调用SAXParserFactory的newSAXParser方法创建一个SAXParser对象

3,实例化一个继承DefaultHandler的自定义对象

4,SAXParser对象的parser方法按自定义Handler规则解析xml文档

MyHandler.java

package saxxml;import java.util.ArrayList;import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;public class MyHandler extends DefaultHandler {ArrayList<Person> students;//要返回的对象集合StringBuilder sb;Person student;//当遇到文档开头的时候,即开始解析XML根元素时调用该方法,调用这个方法,可以做一些预处理@Overridepublic void startDocument() throws SAXException {System.out.println("--startDocument--");students=new ArrayList<Person>();//实例化对象sb=new StringBuilder();}//当读到开始标签的时,调用这个方法。即开始解析每个元素时都会调用该方法,uri表示命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签名,attributes可以得到所有属性,一般读到的标签名在qName@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {       System.out.println("--startElement--"+qName);//如果读到的开始标签是student,就实例化对象,设置idif(qName.equals("student")){student=new Person();student.setId(new Integer(attributes.getValue("id")));   }sb.setLength(0);//每次读到开始标签将字符长度设置为0,以便重新开始读取元素内的字符节点}/*这个方法处理xml文件读到的内容,第一个参数存放文件的内容,注意是xml文件的全部内容早已经在ch中,只是每次调用此函数时start和length会变化,* 后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)可以获取内容*/@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {     System.out.println("--characters()--"+new String(ch,start,length)+"start="+start+" length="+length);sb.append(new String(ch,start,length));//将读取到数字符数组追加到builder中}//遇到结束标签的时候,调用这个方法@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {System.out.println("--endElement--"+qName);if(qName.equalsIgnoreCase("name")){student.setName(sb.toString());}else if(qName.equalsIgnoreCase("age")){student.setAge(new Integer(sb.toString()));}else if(qName.equalsIgnoreCase("student")){students.add(student);}}//文档结束的时候,调用这个方法,可以做一些善后工作@Overridepublic void endDocument() throws SAXException {     System.out.println("--endDocument--");}     //返回对象集合public ArrayList<Person> getList(){return students;}}

Main.java

package saxxml;import java.io.File;
import java.io.IOException;
import java.util.ArrayList;import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;import org.xml.sax.SAXException;public class Main {public static void main(String[] args) {// TODO Auto-generated method stubtry {//1,创建一个SAXParserFactory对象SAXParserFactory factory=SAXParserFactory.newInstance();//2,调用SAXParserFactory中的newSAXParser方法创建一个SAXParser对象SAXParser parser=factory.newSAXParser();MyHandler myhandler=new MyHandler();//3,SAXParser对象使用自定义的Handler规则解析xml文件或xml文件流parser.parse(new File("students.xml"), myhandler);//遍历返回的对象集合ArrayList<Person> list=myhandler.getList();for(int i=0;i<list.size();i++){System.out.println("ID:"+list.get(i).getId()+" 姓名:"+list.get(i).getName()+" 年龄:"+list.get(i).getAge());}} catch (SAXException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ParserConfigurationException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

输出:

--startDocument--
--startElement--students
--characters()--start=13 length=5//前面的空格是回车符\t.换行符\n,空格,的输出
--startElement--student
--characters()--start=35 length=9
--startElement--name
--characters()--张珊start=50 length=2
--endElement--name
--characters()--start=60 length=9
--startElement--age
--characters()--22start=74 length=2
--endElement--age
--characters()--start=83 length=5
--endElement--student
--characters()--start=99 length=5
--startElement--student
--characters()--start=121 length=9
--startElement--name
--characters()--王航start=136 length=2
--endElement--name
--characters()--start=146 length=9
--startElement--age
--characters()--25start=160 length=2
--endElement--age
--characters()--start=169 length=5
--endElement--student
--characters()--start=185 length=5
--startElement--student
--characters()--start=207 length=9
--startElement--name
--characters()--刘沙start=222 length=2
--endElement--name
--characters()--start=232 length=9
--startElement--age
--characters()--26start=246 length=2
--endElement--age
--characters()--start=255 length=5
--endElement--student
--characters()--start=271 length=5
--startElement--student
--characters()--start=293 length=9
--startElement--name
--characters()--张海start=308 length=2
--endElement--name
--characters()--start=318 length=9
--startElement--age
--characters()--24start=332 length=2
--endElement--age
--characters()--start=341 length=5
--endElement--student
--characters()--
start=357 length=1
--endElement--students
--endDocument--
ID:1 姓名:张珊 年龄:22
ID:2 姓名:王航 年龄:25
ID:3 姓名:刘沙 年龄:26
ID:4 姓名:张海 年龄:24

分析:用SAX解析XML采用的是从上而下的基于事件驱动的解析方式,在解析过程中会视情况自动调用startDocument()、startElement()、characters()、endElement()、endDocument()等相关的方法。

由编译执行的结果来看:
1,startDocument()方法只会在文档开始解析的时候被调用,每次解析只会调用一次。,

2,startElement()方法每次在开始解析一个元素,即遇到元素标签开始的时候都会调用。
3,characters()方法也是在每次解析到元素标签携带的内容时都会调用,即在startElement调用后,调用characters时读到的内容值,在endElement调用后,调用characters时读到的回车符,换行符和空格。即使该元素标签的内容为空或换行。而且如果元素内嵌套元素,在父元素结束标签前, characters()方法会再次被调用,此处需要注意。

4,endElement()方法每次在结束解析一个元素,即遇到元素标签结束的时候都会调用。

5,endDocument() startDocument()方法只会在文档解析结束的时候被调用,每次解析只会调用一次。
其实参数char[] ch中早已经加载了文档,每次调用的时候改变的是start,length

[
,
, <, s, t, u, d, e, n, t, s, >,
,
,  ,  ,  ,  , <, s, t, u, d, e, n, t,  , i, d, =, ", 1, ", >,
,
,  ,  ,  ,  ,  ,  ,  ,  , <, n, a, m, e, >, 张, 珊, <, /, n, a, m, e, >,
,
,  ,  ,  ,  ,  ,  ,  ,  , <, a, g, e, >, 2, 2, <, /, a, g, e, >,
,
,  ,  ,  ,  , <, /, s, t, u, d, e, n, t, >,
,
,  ,  ,  ,  , <, s, t, u, d, e, n, t,  , i, d, =, ", 2, ", >,
,
,  ,  ,  ,  ,  ,  ,  ,  , <, n, a, m, e, >, 王, 航, <, /, n, a, m, e, >,
,
,  ,  ,  ,  ,  ,  ,  ,  , <, a, g, e, >, 2, 5, <, /, a, g, e, >,
,
,  ,  ,  ,  , <, /, s, t, u, d, e, n, t, >,
,
,  ,  ,  ,  , <, s, t, u, d, e, n, t,  , i, d, =, ", 3, ", >,
,
,  ,  ,  ,  ,  ,  ,  ,  , <, n, a, m, e, >, 刘, 沙, <, /, n, a, m, e, >,
,
,  ,  ,  ,  ,  ,  ,  ,  , <, a, g, e, >, 2, 6, <, /, a, g, e, >,
,
,  ,  ,  ,  , <, /, s, t, u, d, e, n, t, >,
,
,  ,  ,  ,  , <, s, t, u, d, e, n, t,  , i, d, =, ", 4, ", >,
,
,  ,  ,  ,  ,  ,  ,  ,  , <, n, a, m, e, >, 张, 海, <, /, n, a, m, e, >,
,
,  ,  ,  ,  ,  ,  ,  ,  , <, a, g, e, >, 2, 4, <, /, a, g, e, >,
,
,  ,  ,  ,  , <, /, s, t, u, d, e, n, t, >,
,
, <, /, s, t, u, d, e, n, t, s, >, 

解析XML方式-DOM,SAX相关推荐

  1. java sax xml文件解析_java解析xml文件-DOM/SAX

    java解析xml文件的两种方式 1:DOM 原理:把整个文档加载到内存,转化成dom树,之后应用程序可以随机的访问dom树的任何数据,灵活 快,但消耗内存 一个简单的xml 使用java解析 //b ...

  2. SAX解析xml (遍历DOM树各节点)

    本文参考 http://yangjunfeng.iteye.com/blog/401377 1. books.xml 1 <?xml version="1.0" encodi ...

  3. pythonxml解析拿到控件坐标_Python解析xml中dom元素的方法

    本文实例讲述了Python解析xml中dom元素的方法.共享给大家供大家参考.详细实现方法如下: 复制代码 代码如下: from xml.dom import minidom try: xmlfile ...

  4. android解析XML总结(SAX、Pull、Dom三种方式)

    在android开发中,经常用到去解析xml文件,常见的解析xml的方式有一下三种:SAX.Pull.Dom解析方式. 今天解析的xml示例(channels.xml)如下: 1 <?xml v ...

  5. Android之解析XML总结(SAX、Pull、Dom三种方式)

    常见的解析xml的方式有一下三种:SAX.Pull.Dom解析方式.最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull),今天对android解析xml的这三种方式进行一 ...

  6. 安卓XML解析的几种方式(DOM,SAX,PULL..)

    在android开发中,经常用到去解析xml文件,常见的解析xml的方式有一下三种:SAX.Pull.Dom解析方式.最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull) ...

  7. 10. 解析XML文件(SAX/DOM/ElementTre)

    XML的全称是eXtensible Markup Language, 意为可扩展的标记语言, 是一种用于标记电子文件使其具有结构性的标记语言.以XML结构存储数据的文件就是XML文件,它被设计用来传输 ...

  8. XML文件解析-DOM4J方式和SAX方式

    最近遇到的工作内容都是和xml内容解析相关的. 1图片数据以base64编码的方式保存在xml的一个标签中,xml文件通过接口的方式发送给我,然后我去解析出图片数据,对图片进行进一步处理. 2.xml ...

  9. 解析XML报文--------DOM、JDOM、SAX

    例: <?xml version="1.0" encoding="UTF-8"?> <bookstore><book id=&qu ...

最新文章

  1. 【PAT (Advanced Level) Practice】1120 Friend Numbers (20 分)
  2. c++对象长度之内存对齐(2)
  3. VC/MFC列表CListCtrl类的LVCOLUMN和LVITEM详解
  4. Tree Xor(未完全搞定)
  5. Pandas选择行列的十大技能
  6. 从19本书中选取五本,并且要求这五本互相不相邻,一共有多少种方法?
  7. iphone NSTimer
  8. Delphi 集合和字符串互转
  9. RN开发系列<4>--FlatList SectionList (iOS中的tableView)
  10. 【优化求解】基于NSGA2算法求解多目标优化问题matlab源码
  11. Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class redacted.BasicEnt
  12. 6-23 sdust-Java-可实现多种排序的Book类 (20 分)
  13. 【如何学习Kotlin 开发?《Kotin 移动和服务器端应用开发》告诉你】
  14. 小志营销:自媒体营销,平民化网络营销新玩法
  15. Linux字体库问题(PDF转图片中文字缺失)
  16. 最近Oracle Cloud甲骨文上线了免费云套餐.
  17. [VOT12](2017CVPR) CSR-DCF: Discriminative Correlation Filter Tracker with Channel and Spatial
  18. python中如何控制随机的概率_Python3根据基础概率随机生成选项
  19. unity小游戏实践(一) 俄罗斯方块
  20. “调节阀”发脾气了你怎么办?

热门文章

  1. 为什么我的vc6.0建立工程时显示不能访问类查文件类信息,类查看信息不可用
  2. 资源在另一个编辑器中打开的错误处理办法
  3. ST17H26 tea加密java版本
  4. 死锁产生的4个必要条件,如何检测,解除死锁
  5. mysql主从复制 drbd_MySql主从复制简单案例实现
  6. (chap2 TCP/IP基础知识) TCP/IP协议分层模型-应用层
  7. 【Pygame小游戏】《坦克大战》,那些童年的游戏你还记得几个呢?
  8. 绕过TracerPid检测
  9. C++日志系统log4cxx使用总结
  10. linux两个网段默认网关_Linux下配置多网卡多网关