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中的文 ...
随机推荐
- 使用nginx代理跨域,使用nginx代理bing的每日一图
前言 自从搞清楚了跨域原理后一直自鸣得意,感觉跨域没啥问题了.而事实上对关于跨域的几个header的理解也有限,但那又如何,我能做到跨域就行了.今天想把博客背景图改成bing的每日一图,发现遇到跨域问 ...
- javascript设计模式——组合模式
前面的话 在程序设计中,有一些和“事物是由相似的子事物构成”类似的思想.组合模式就是用小的子对象来构建更大的对象,而这些小的子对象本身也许是由更小的“孙对象”构成的.本文将详细介绍组合模式 宏命令 宏 ...
- Spring Cloud Zuul
新建Spring Boot工程,命名为zuul 1.pom.xml添加依赖 <?xml version="1.0" encoding="UTF-8"?&g ...
- NOIP2016提高组初赛(1)
一.选择题 6.后缀表达式,使用二叉树来求解,正常情况下的表达式a*(b+c)- d为中序遍历的二叉树. 即 若转换为后缀表达式(左右根)则为abc+*d- 14.代数字进去,多试几遍: 三.问题求解 ...
- JAVA IO分析二:字节数组流、基本数据&对象类型的数据流、打印流
上一节,我们分析了常见的节点流(FileInputStream/FileOutputStream FileReader/FileWrite)和常见的处理流(BufferedInputStream/B ...
- netty详解之reactor模型
假设在办理各种证件时分为填表,审核,制作3个过程,每个过程用时10分钟,这样一个工作人员需要30分钟办理一个证件.那么有没有办法提供效率,减少等待时间呢.可以让一个专门的工作人员,每个顾客到来时就负责 ...
- 工作中git 操作汇总
1. git branch -l 查看本地branch 2. git reset --hard 回滚全部修改 3. git status 查看本地修改 4. git pull 更新代码 5. gi ...
- C++ Primer高速入门之三:几种常见的控制语句
语句总是顺序运行的:第一条语句运行完了接着是第二条,第三条等等.这是最简单的情况,为了更好的控制语句的运行.程序设计语言提供了多种控制结构支持更为复杂的语句运行.我们就来看看C++ 提供的控制方式. ...
- 使用milang出错:LookupError: unknown encoding: idna
今天同事安装了milang,结果发现例如以下出错: Traceback (most recent call last): File "F:\vmid.py", line 11, i ...
- 【java】抓取页面内容,提取链接(此方法可以http get无需账号密码的请求)
package 网络编程; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileOutpu ...