在上一篇随笔中分析了xml以及它的两种验证方式。我们有了xml,但是里面的内容要怎么才能得到呢?如果得不到的话,那么还是没用的,解析xml的方式主要有DOMSAX,其中DOM是W3C官方的解析方式,而SAX是民间(非官方)的,两种解析方式是很不一样的。下面通过例子来分析两种解析方式的区别。

下面是要解析的xml文档

 <?xml version="1.0" encoding="utf-8"?>
<学生名册>
<!--http://www.cnblogs.com/zhi-hao/-->
<学生 学号="A1">
<姓名>CIACs</姓名>
<性别>男</性别>
<年龄>22</年龄>
</学生>
<学生 学号="A2">
<姓名>zhihao</姓名>
<性别>男</性别>
<年龄>23</年龄>
</学生>
</学生名册>

DOM(Document Object Model)文档对象模式,从名字上就可以知道,DOM应该是基于文档对象来解析的。在DOM解析方式中主要用到了以下四个接口

1、Document接口,该接口是对xml文档进行操作的入口,要想操作xml,必须获得文档的入口。

2、Node接口,存储xml文档的节点的

3、NodeList接口

4、NameNodeMap接口,存储的是xml中的属性。

DOM中的基本对象有Document,Node,NodeList,Element和Attr。有了这些就可以解析xml了

 package xmlTest;

 import java.io.File;

 import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
*
* @author CIACs
* 2014-09-22
*/ public class DOM { public static void main(String[] args) throws Exception {
//获得解析工厂实例
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//通过工厂获得DocumentBulider
DocumentBuilder db = dbf.newDocumentBuilder();
//获得文档对象的入口
Document doc = db.parse(new File("student.xml"));
//获得根元素
Element root = doc.getDocumentElement();
//开始解析
parseElement(root);
}
private static void parseElement(Element element)
{
String tagName = element.getNodeName();
System.out.print("<"+tagName);
//获得元素属性
NamedNodeMap map = element.getAttributes();
if(null != map)
{
for(int i = 0;i < map.getLength();i++)
{
Attr attr = (Attr)map.item(i);
String attrName = attr.getName();
String attrValue = attr.getValue();
System.out.print(" "+attrName + "=\""+attrValue+"\"");
}
}
System.out.print(">"); //获得元素的孩子节点
NodeList child = element.getChildNodes(); for(int i = 0;i < child.getLength();i++)
{
Node node = child.item(i);
//判断节点类型 short nodeType = node.getNodeType(); if(nodeType == Node.ELEMENT_NODE)
{
parseElement((Element)node);
}
else
if(nodeType == Node.TEXT_NODE)
{
System.out.print(node.getTextContent());
}
else
if(nodeType == Node.COMMENT_NODE)
{
System.out.print("<!--"+node.getTextContent()+"-->");
}
}
System.out.print("</"+tagName+">");
}
}

DOM

输出结果:

当然你可以直接输出内容,不用控制格式。

SAX(Simple APIs for XML)面向xml的简单APIs。SAX解析xml的一般步骤如下

1、创建SAXParserFactory对象; SAXParserFactory spf = SAXParserFactory.newInstance();

2、使用上面创建的工厂对象创建SAXParser解析对象;SAXParser sp = spf.newSAXParser();

3、创建SAXHandler处理器,而这个SAXHandler类要继承DefaultHandler,自己重新编写其中的方法,主要有 public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException{ } 这个方法是在读取xml数据的节点元素开始时触发,需要实现这个方法进行标记元素的名字的操作; public void characters(char[] ch, int start, int length)throws SAXException{ } 这个方法可以处理节点之间的数据;  public void endElement(String uri, String ocalName, String qName)throws SAXException { } 这个方法在处理节点元素终止时触发,可添加代码来将节点数据进行存储。

下面是解析xml的代码

 package xmlTest;

 import java.io.File;
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; /**
*
* @author CIACs
* 2014-09-22
*/ public class Sax {
public static void main(String []args)
{
try
{
//获得sax解析工厂实例
SAXParserFactory spf = SAXParserFactory.newInstance();
//获得sax解析器
SAXParser sp = spf.newSAXParser();
//获得SAXHandler,该类是继承自DefaultHandler的
SAXHandler handler = new SAXHandler();
//开始解析xml文档
sp.parse(new File("student.xml"), handler); }
catch(Exception e)
{
e.printStackTrace();
}
} } class SAXHandler extends DefaultHandler
{
private String currentElement;
private String currentValue;
private String attrName;
private String attrValue;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currentElement = qName;
for(int i = 0;i < attributes.getLength();i++)
{
attrName = attributes.getQName(i);
attrValue = attributes.getValue(i);
System.out.println("属性: "+ attrName + "=" + attrValue);
} }
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
currentValue = new String(ch,start,length);
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException { if(currentElement.equals(qName))
{
System.out.println(currentElement + "=" + currentValue);
}
}
}

Sax

输出结果:

这里我也是直接输出xml的内容,并没有写到硬盘,在实际应用时你可以把内容存在Map中。

总结:

  通过上面的两个解析实例,我们可以看出DOM解析XML时,首先将xml文档整个加载到内存中,然后就可以随机访问内存中的文档对象树(dom解析器是把xml解析成树形结构的)。SAX是基于事件的而且是顺序的,就是读到某个标签时就会调用相应的方法,一旦经过了某个元素之后,我们就没办法再去访问了。DOM由于要把整个xml加载到内存中,所以当xml很大时,内存就可能会溢出,而SAX不用事先把xml文档加载到内存中,占用内存小,相对而言SAX是面向xml的简单APIs,在开发上比较复杂,要开发者去实现事件处理器,但会更灵活,而DOM会更易于理解和开发。对于大型的xml文档,我们通常会使用SAX的方式去解析。

DOM&SAX解析XML的更多相关文章

  1. Dom,pull,Sax解析XML

    本篇随笔将详细讲解如何在Android当中解析服务器端传过来的XML数据,这里将会介绍解析xml数据格式的三种方式,分别是DOM.SAX以及PULL. 一.DOM解析XML 我们首先来看看DOM(Do ...

  2. Android之SAX解析XML

    一.SAX解析方法介绍 SAX(Simple API for XML)是一个解析速度快并且占用内存少的XML解析器,非常适合用于Android等移动设备. SAX解析器是一种基于事件的解析器,事件驱动 ...

  3. JAVA使用SAX解析XML文件

    在我的另一篇文章(http://www.cnblogs.com/anivia/p/5849712.html)中,通过一个例子介绍了使用DOM来解析XML文件,那么本篇文章通过相同的XML文件介绍如何使 ...

  4. SAX解析xml浅析

    SAX解析XML文件采用事件驱动的方式进行,也就是说,SAX是逐行扫描文件,遇到符合条件的设定条件后就会触发特定的事件,回调你写好的事件处理程序.使用SAX的优势在于其解析速度较快,占用内存较少(相对 ...

  5. JavaWeb学习日记----SAX解析XML

    1.SAX解析XML文档的方式: 与DOM方式解析不同,DOM方式解析是根据XML的层级结构在内存中分配一个树形结构,把xml的标签,属性和文本都封装成对象.优点是可以很方便实现增删改操作.缺点是,如 ...

  6. 用DOM方式解析XML

    一.用DOM方式解析XML 此例子节点结构如下: 1.获取book节点属性 (1).如果不知道节点的属性,通过 NamedNodeMap attrs = book.getAttributes(); 来 ...

  7. Python:使用基于事件驱动的SAX解析XML

    SAX的特点: 是基于事件的 API 在一个比 DOM 低的级别上操作 为您提供比 DOM 更多的控制 几乎总是比 DOM 更有效率 但不幸的是,需要比 DOM 更多的工作 基于对象和基于事件的接口 ...

  8. python 之模块之 xml.dom.minidom解析xml

    # -*- coding: cp936 -*- #python 27 #xiaodeng #python 之模块之 xml.dom.minidom解析xml #http://www.cnblogs.c ...

  9. 安卓SAX解析XML文件

    XML文件经常使用的解析方式有DOM解析,SAX解析. 一.Sax SAX(simpleAPIforXML)是一种XML解析的替代方法. 相比于DOM.SAX是一种速度更快,更有效的方法. 它逐行扫描 ...

随机推荐

  1. [经典] atoi && itoa

    atoi原型:int atoi(const char *nptr) atoi,需要考虑的内容: 1. 第一个字符为"-"时为负,系数为-1:为"+"时为正,系数 ...

  2. 3 weekend110的shuffle机制 + mr程序的组件全貌

    前面,讲到了hadoop的序列化机制,mr程序开发,自定义排序,自定义分组. 有多少个reduce的并发任务数可以控制,但有多少个map的并发任务数还没 缓存,分组,排序,转发,这些都是mr的shuf ...

  3. SQL语句的增删改查

    一.增:有2种方法 1.使用insert插入单行数据: 语法:insert [into] <表名> [列名] values <列值> 例:insert into Strdent ...

  4. wDatePicker使用说明文档

    版权声明:本文为博主原创文章,未经博主允许不得转载. http://www.my97.net/dp/demo/ 4.5更新的内容 [重构]对WdatePicker.js做了较大规模的调整 [改进]自动 ...

  5. Navicat远程连接MySQL数据库

    1.打开Navicat,在界面的“主机名和IP地址”处输入IP地址,一般是192.168.1.1 2.输入相应的用户名和密码,点击连接测试,确认是否已经连接,之后就可以点击确定了 3.找到相应的数据库 ...

  6. LINUX下解决netstat查看TIME_WAIT状态过多问题

     来源:多3度热爱 的BLOG   查看连接某服务端口最多的的IP地址 netstat -nat |awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c ...

  7. 在地图上添加POI

    使用Tangram的Marker, 可以在地图上做各种标记, 效果图: Tangram是通过Marker在地图上添加标记的,Marker分Point, Polyline和Polygon三种, 分别对应 ...

  8. (转)在javascript中关于submit和button提交表单区别

      原文来自:http://www.jb51.net/article/42236.htm   submit是button的一个特例,也是button的一种,它把提交这个动作自动集成了,submit和b ...

  9. [TypeScript] Using Lodash in TypeScript with Typings and SystemJS

    One of the most confusing parts of getting started with TypeScript is figuring out how to use all th ...

  10. Oracle 设置archivelog错误解决方案

    在Oracle 数据库的实际应用中,开启archivelog模式是必不可少的,但是在设置archivelog的过程中,可能因为不小心出现错误,导致数据库无法启动,本案例就是一种情况. 误操作现象: 设 ...