XML的解析(DOM以及SAX方式)
感谢http://blog.csdn.net/redarmy_chen/article/details/12951649(关于SAX解析)以及http://blog.csdn.net/zhangerqing/article/details/8253532(DOM解析)。首先申明本文并非个人原创,而是整合的前面两篇文章,供大家以及自己参考。
1.XML
XML是一种对独立于任何编程语言的数据进行编码的机制。主要用于数据存储,数据传输以及配置文件(Ioc)等方面。XML要求所有的标记必须成对出现,且区分大小写。举个例子:
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
可以从这个例子,得出XML的结构,简单说XML的结构即为多叉树结构。上面代码的结构图如下:

2.XML的解析技术
DOM
DOM 是 W3C 处理 XML 的标准 API,它是许多其它与 XML 处理相关的标准的基础,不仅是 Java,其它诸如 Javascript,PHP,MS .NET 等等语言都实现了该标准, 成为了应用最为广泛的 XML 处理方式。当然,为了能提供更多更加强大的功能,Java 对于 DOM 直接扩展工具类有很多,比如很多 Java 程序员耳熟能详的 JDOM,DOM4J 等等, 它们基本上属于对 DOM 接口功能的扩充,保留了很多 DOM API 的特性。其处理方式是将 XML 整个作为类似树结构的方式读入内存中以便操作及解析,因此支持应用程序对 XML 数据的内容和结构进行修改,但是同时由于其需要在处理开始时将整个 XML 文件读入到内存中去进行分析,因此其在解析大数据量的 XML 文件时会遇到类似于内存泄露以及程序崩溃的风险。例子如下:
首先造一个xml文档出来:(books.xml放在项目根路径下,不是src,可以在工程文件所在文件夹根目录下先创建txt文档,编辑books内容,然后保存为xml格式即可)
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="01" name="book1">
<title>Harry Potter</title>
<author>J K. Rowling</author>
</book>
<book id="02" name="book2">
<title>Thinking in Java</title>
<author>Bruke</author>
</book>
</books>
DOM 解析:
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList; public class DOMTest { /* build a DocumentBuilderFactory */
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance(); public static void main(String[] args) {
DOMTest parser = new DOMTest();
Document document = parser.parse("books.xml");
/* get root element */
Element rootElement = document.getDocumentElement(); /* get all the nodes whose name is book */
NodeList nodeList = rootElement.getElementsByTagName("book");
if (nodeList != null) {
for (int i = 0; i < nodeList.getLength(); i++) {
/* get every node */
Node node = nodeList.item(i);
/* get the next lever's ChildNodes */
NodeList nodeList2 = node.getChildNodes();
for (int j = 0; j < nodeList2.getLength(); j++) {
Node node2 = nodeList2.item(j);
if (node2.hasChildNodes()) {
System.out.println(node2.getNodeName() + ":"
+ node2.getFirstChild().getNodeValue());
}
}
}
}
} /* Load and parse XML file into DOM */
public Document parse(String filePath) {
Document document = null;
try {
/* DOM parser instance */
DocumentBuilder builder = builderFactory.newDocumentBuilder();
/* parse an XML file into a DOM tree */
document = builder.parse(new File(filePath));
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return document;
}
}
输出:
title:Harry Potter
author:J K. Rowling
title:Thinking in Java
author:Bruke
SAX:
SAX解析XML文件采用事件驱动的方式进行,也就是说,SAX是逐行扫描文件,遇到符合条件的设定条件后就会触发特定的事件,回调你写好的事件处理程序。使用SAX的优势在于其解析速度较快,相对于DOM而言占用内存较少。而且SAX在解析文件的过程中得到自己需要的信息后可以随时终止解析,并不一定要等文件全部解析完毕。凡事有利必有弊,其劣势在于SAX采用的是流式处理方式,当遇到某个标签的时候,它并不会记录下以前所遇到的标签,也就是说,在处理某个标签的时候,比如在startElement方法中,所能够得到的信息就是标签的名字和属性,至于标签内部的嵌套结构,上层标签、下层标签以及其兄弟节点的名称等等与其结构相关的信息都是不得而知的。实际上就是把XML文件的结构信息丢掉了,如果需要得到这些信息的话,只能你自己在程序里进行处理了。
SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器:
解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。
解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。
事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。
以SAX的ContentHandler接口为例,了解常用方法:startElement、endElement、characters等:
startElement方法说明:
void startElement(String uri,
String localName,
String qName,
Attributes atts)
throws SAXException
方法说明:
解析器在 XML 文档中的每个元素的开始调用此方法;对于每个 startElement 事件都将有相应的 endElement 事件(即使该元素为空时)。所有元素的内容都将在相应的 endElement 事件之前顺序地报告。 参数说明:
uri - 名称空间 URI,如果元素没有名称空间 URI,或者未执行名称空间处理,则为空字符串
localName - 本地名称(不带前缀),如果未执行名称空间处理,则为空字符串
qName - 限定名(带有前缀),如果限定名不可用,则为空字符串
atts - 连接到元素上的属性。如果没有属性,则它将是空 Attributes 对象。在 startElement 返回后,此对象的值是未定义的
endElement方法说明:
void endElement(String uri,
String localName,
String qName)
throws SAXException接收元素结束的通知。
SAX 解析器会在 XML 文档中每个元素的末尾调用此方法;对于每个 endElement 事件都将有相应的 startElement 事件(即使该元素为空时)。 参数:
uri - 名称空间 URI,如果元素没有名称空间 URI,或者未执行名称空间处理,则为空字符串
localName - 本地名称(不带前缀),如果未执行名称空间处理,则为空字符串
qName - 限定的 XML 名称(带前缀),如果限定名不可用,则为空字符串
characters方法:
void characters(char[] ch,
int start,
int length)
throws SAXException
接收字符数据的通知,可以通过new String(ch,start,length)构造器,创建解析出来的字符串文本.
参数:
ch - 来自 XML 文档的字符
start - 数组中的开始位置
length - 从数组中读取的字符的个数
下面我们就具体讲解sax解析的操作:
一.我们通过XMLReaderFactory、XMLReader完成,步骤如下
1.通过XMLReaderFactory创建XMLReader对象
XMLReader reader = XMLReaderFactory.createXMLReader();
2. 设置事件处理器对象
reader.setContentHandler(new MyDefaultHandler());
3.读取要解析的xml文件
FileReader fileReader =new FileReader(new File("src\\sax\\startelement\\web.xml"));
4.指定解析的xml文件
reader.parse(new InputSource(fileReader));
案例:通过案例对uri、localName、qName和attribute参数有更加深入的了解
1.首先创建要解析的web.xml文件,内容如下
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns:csdn="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<csdn:display-name></csdn:display-name>
</web-app>
<!--
uri - 名称空间 URI,如果元素没有任何名称空间 URI,或者没有正在执行名称空间处理,则为空字符串。
xml namespace-xmlns
localName - 本地名称(不带前缀),如果没有正在执行名称空间处理,则为空字符串。
qName - 限定的名称(带有前缀),如果限定的名称不可用,则为空字符串。
attributes - 附加到元素的属性。如果没有属性,则它将是空的 Attributes 对象。
-->
2.创建解析测试类及事件处理的内部类代码如下
package sax.startelement; import java.io.File;
import java.io.FileReader; import org.junit.Test;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory; public class Demo3 { @Test
public void test() throws Exception {
// 通过XMLReaderFactory创建XMLReader对象
XMLReader reader = XMLReaderFactory.createXMLReader();
// 设置事件处理器对象
reader.setContentHandler(new MyDefaultHandler());
// 读取要解析的xml文件
FileReader fileReader = new FileReader(new File(
"src\\sax\\startelement\\web.xml"));
// 指定解析的xml文件
reader.parse(new InputSource(fileReader));
} // 自定义的解析类,通过此类中的startElement了解uri,localName,qName,Attributes的含义
class MyDefaultHandler extends DefaultHandler { @Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
System.out
.println("--------------startElement开始执行--------------------------");
System.out.println("uri:::" + uri);
System.out.println("localName:::" + localName);
System.out.println("qName:::" + qName);
for (int i = 0; i < attributes.getLength(); i++) {
String value = attributes.getValue(i);// 获取属性的value值
System.out.println(attributes.getQName(i) + "-----" + value);
}
System.out
.println("------------------startElement执行完毕---------------------------");
} }
}
3.程序运行的结果如下:

二.我们通过SAXParserFactory、SAXParser、XMLReader完成,步骤如下
1.使用SAXParserFactory创建SAX解析工厂
SAXParserFactory spf = SAXParserFactory.newInstance();
2.通过SAX解析工厂得到解析器对象
SAXParser sp = spf.newSAXParser();
3.通过解析器对象得到一个XML的读取器
XMLReader xmlReader = sp.getXMLReader();
4.设置读取器的事件处理器
xmlReader.setContentHandler(new BookParserHandler());
5.解析xml文件
xmlReader.parse("book.xml");
说明:如果只是使用SAXParserFactory、SAXParser他们完成只需要如下3步骤
1.获取sax解析器的工厂对象
SAXParserFactory factory = SAXParserFactory.newInstance();
2.通过工厂对象 SAXParser创建解析器对象
SAXParser saxParser = factory.newSAXParser();
3.通过解析saxParser的parse()方法设定解析的文件和自己定义的事件处理器对象
saxParser.parse(new File("src//sax//sida.xml"), new MyDefaultHandler());
案例:解析出"作者"元素标签中的文本内容
1.需要解析的sida.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 四大名著[
<!ELEMENT 四大名著 (西游记,红楼梦)>
<!ATTLIST 西游记 id ID #IMPLIED>
]>
<四大名著>
<西游记 id="x001">
<作者>吴承恩</作者>
</西游记>
<红楼梦 id="x002">
<作者>曹雪芹</作者>
</红楼梦>
</四大名著>
2.解析测试类和事件处理器类的实现代码
package sax; import java.io.File; import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory; import org.junit.Test;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler; public class SaxTest { @Test
public void test() throws Exception {
// 1.获取sax解析器的工厂对象
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2.通过工厂对象 SAXParser创建解析器对象
SAXParser saxParser = factory.newSAXParser();
// 3.通过解析saxParser的parse()方法设定解析的文件和自己定义的事件处理器对象
saxParser.parse(new File("src//sax//sida.xml"), new MyDefaultHandler()); } // 自己定义的事件处理器
class MyDefaultHandler extends DefaultHandler { // 解析标签开始及结束的的标识符
boolean isOk = false; @Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
// 当解析作者元素开始的时候,设置isOK为true
if ("作者".equals(qName)) {
isOk = true;
}
} @Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
// 当解析的标识符为true时,打印元素的内容
if (isOk) {
System.out.println(new String(ch, start, length));
}
} @Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(uri, localName, qName);
// 当解析作者元素的结束的时候,设置isOK为false
if ("作者".equals(qName)) {
isOk = false;
}
} }
}
最后可以看到输出结果为吴承恩、曹雪芹
XML的解析(DOM以及SAX方式)的更多相关文章
- JavaEE实战——XML文档DOM、SAX、STAX解析方式详解
原 JavaEE实战--XML文档DOM.SAX.STAX解析方式详解 2016年06月22日 23:10:35 李春春_ 阅读数:3445 标签: DOMSAXSTAXJAXPXML Pull 更多 ...
- 无废话XML--XML解析(DOM和SAX)
XML处理模式 处理XML有2种方式,DOM和SAX.一般的实际开发中,这2种使用的不多,直接用dom4j来解析XML就好了,包括CRUD等操作都很方便的.这里介绍的DOM和SAX是比较底层的,具体的 ...
- XML - 十分钟了解XML结构以及DOM和SAX解析方式
引言 NOKIA 有句著名的广告语:"科技以人为本".不论什么技术都是为了满足人的生产生活须要而产生的.详细到小小的一个手机.里面蕴含的技术也是浩如烟海.是几千年来人类科技的结晶, ...
- XML文件解析DOM解析和SAX解析
解析一个XML文档有哪些内容解析有:dom和sax两种dom:把整个XML文档放入内存,适合XML随机访问,占用内存资源大sax:事件驱动型的XML解析方式,顺序读取,不用一次装载整个文件,遇到标签会 ...
- schema文件及XML文件的DOM和Sax解析
schema文件 <?xml version="1.0" encoding="UTF-8"?> <schema xmlns="htt ...
- Android解析xml文件-采用DOM,PULL,SAX三种方法解析
解析如下xml文件 <?xml version="1.0" encoding="UTF-8"?> <persons> <perso ...
- XML文件的解析—DOM、SAX
一.DOM 解析 思路:获得Document对象,遍历其中节点获得需要的内容 要点: Document : DocuemntBuilderFactory --newDocumentBuilder - ...
- xml它解析----DOM解析
DOM模型(documentobject model) •DOM解析器在解析XML文档时,会把文档中的全部元素,依照其出现的层次关系.解析成一个个Node对象(节点). •在dom中.节点之间关系例如 ...
- iOS开发中XML的DOM和SAX解析方法
一.介绍 dom是w3c指定的一套规范标准,核心是按树形结构处理数据,dom解析器读入xml文件并在内存中建立一个结构一模一样的“树”,这树各节点和xml各标记对应,通过操纵此“树”来处理xml中的文 ...
随机推荐
- Java代码操作SVN
package com.leadbank.oprPlatform.util;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import ...
- 好好写代码吧,没事别瞎B去创业!
知乎上看到这个问题 正好最近想写篇关于此的文章,于是就回答了一波. 也贴到这里来,回答如下 : 本问题简直为我量身定制,做为一个正在创业中的苦逼少年,说说我是如何从鼓吹怂恿身边人创业转换成反对创业的. ...
- MySQL系列:高可用架构之MHA
前言 从11年毕业到现在,工作也好些年头,入坑mysql也有近四年的时间,也捣鼓过像mongodb.redis.cassandra.neo4j等Nosql数据库.其实一直想写博客分享下工作上的零零碎碎 ...
- Android PopupWindows
今天了解到PopupWindows这个布局,PopupWindow这个类用来实现一个弹出框,能够使用随意布局的View作为其内容,这个弹出框是悬浮在当前activity之上的. 以下是一个实例 xml ...
- Hadoop之SequenceFile
Hadoop序列化文件SequenceFile能够用于解决大量小文件(所谓小文件:泛指小于black大小的文件)问题,SequenceFile是Hadoop API提供的一种二进制文件支持.这样的二进 ...
- (四)—性能测试工具curl-loader(linux)
curl-loader介绍 curl-loader(也被称为"omes-NIK"和"davilka")是一个开源的C语言编写的工具,模拟应用负载和成千上万的几十 ...
- OS X Yosemite升级提示升级OS10.11或更高版本问题解决方法
如图,楼主的pro久未升级,版本号已经很低.某天一时兴起,想体验最新版本的OS X.就很开心的进行软件更新: 依据iOS上的APP.系统升级经验,这是一个非常自然.毫无难度的过程,哪知道,今天一直卡在 ...
- 项目实战12.1—企业级监控工具应用实战-zabbix安装与基础操作
无监控,不运维.好了,废话不多说,下面都是干货. 警告:流量党勿入,图片太多!!! 项目实战系列,总架构图 http://www.cnblogs.com/along21/p/8000812.html ...
- 关于模式识别中的domain generalization 和 domain adaptation
今晚听了李文博士的报告"Domain Generalization and Adaptation using Low-Rank Examplar Classifiers",讲的很精 ...
- html5中将图片的绝对路径转换成文件对象
html5中将图片的绝对路径转换成文件对象 将图片的绝对路径转换成base64编码,请看这篇文章 我们先来理解基本知识点: 1. 理解HTML5中的FileList对象与file对象. 在HTML5中 ...