在之前的一篇文章中介绍了XML文档的格式规范,语义约束,命名空间等基本内容。我们知道XML文档的一个主要作用就是作为数据传输的工具,那么就涉及到应用程序对XML文档内容的解析。由于XML文档本身具备结构化格式,所以不推荐将其当作普通文件,使用I/O流解析。一般情况下,XML使用DOM模型和SAX两种解析机制。
在解析XML文件的过程中,有几个经常出现的名词概念,笔者发现有的文章博客中或并列或单独的介绍,给读者一种混淆的错觉。如DOM模型,SAX,JAXP,Dom4j,JDom等,这里可以给这几个名词做个区别和划分:
- DOM模型和SAX是XML文档内容底层解析的两种基本方法。
- JAXP、Dom4j、JDom是应用程序如Java读取XML文档的方法或接口,其底层实现方法最终还是封装的DOM或这SAX解析机制,只不过在解析性能或功能侧重上有多区别。
下面重点介绍本篇的重点角色DOM和SAX解析机制。
1. DOM解析
Document Object Model,即文档对象模型,W3C推荐的处理XML文档的规范;
DOM为解析XML文档定义了一组标准接口,DOM解析器负责读入整个文档,然后将该文档解析成树状结构存入内存,这样就将XML文档映射为一组父子、兄弟相关联的节点对象集合。一般情况,解析器将提供相应接口,实现DOM树各个元素节点信息访问。
2. SAX解析
Simple API for XML, 是XML解析的事实规范,基于事件驱动处理的方式来解析XML文档;SAX在解析XML文档的时候会依次触发文档开始,元素开始,元素结束,文档结束等事件,应用程序监听SAX解析过程中所触发的事件来获取XML文档中的内容。
关于SAX的解析方式,主要是两方面的内容,事件触发与事件监听。SAX解析器在按顺序依次解析文档时,触发到文档或者节点的开始标签和结束标签时,就会向监听器发送”事件“,监听器通过监听到的”事件“来获取当前节点的详细信息。
所以,在实际的开发过程中,程序员关心最多的还是如何实现上面的监听器,在监听器中获取XML文档的内容。如下图展示SAX解析XML文档的整个流程。
SAX解析器不创建任何对象,只是依次遇到标签时触发对应的事件,并将元素内的内容封装成事件传出去,到监听器中。监听器获取XML文档中的内容。
SAX解析器
JAXP为SAX提供两组解析器API,XMLReader和XMLParser,其中前者时Java提供的原生的XML解析器,后者时对前者的再封装。其提供的接口基本区别不大,都是parse()接口,只是开发的方法和参数设置略有不同。
XMLReader:
- void parse(InputSource is):解析InputSource输入源中的资源;
- void parse(String systemId):解析url地址资源,xml文件于磁盘上的位置。
XMLParser:
- void parse(InputSource is,DefaultHandler df):解析InputSource输入源中的资源,指定监听器DefaultHandler;
- void parse(String systemId,DefaultHandler df):解析url地址资源,xml文件于磁盘上的位置,指定监听器DefaultHandler。
- void parse(File f,DefaultHandler df):解析File对象,指定监听器DefaultHandler。
SAX监听器
一般情况JAXP提供了四种监控器,如下表:
Name | Description |
---|---|
ContentHandler | 监听XML文档的内容处理事件; |
DTDHandler | 监听DTD处理事件; |
EntityResolver | 监听实体处理事件; |
ErrorHandler | 监听解析出错的事件; |
上面的四种监听器,只是大类,各自内部有自己的实现方法,开发中根据具体的需求,重写继承的监听器中的方法。
3. SAX和DOM之间的区别
table below describes the differences of DOM & SAX parsers.
DOM | SAX | |
---|---|---|
速度 | 一次性装入整个XML文档内容,并将其加载为Dom树,速度较慢 | 顺序解析XML文档,无需一次性装入XML文档至内存,速度较快 |
重复访问 | XML文档解析成Dom树之后,存入内容,可以重复访问,方便高效 | 顺序解析XML文档,不入内存,若要重复访问,需再次解析,不方便重复访问 |
内存要求 | 内存占用较高 | 内存占用较低 |
读取与修改 | 可以读取节点内容,也可以修改节点内容 | 一般只能读取节点内容,不能修改 |
解析思路 | 采用面向对象的思想解析,整个XML文档解析成DOM树之后,以面向对象的方式来操作元素 | 采用事件驱动机制,SAX解析器只负责触发事件,程序负责监听所有事件,并通过事件获取XML文档中的信息 |
(摘自李刚《疯狂XML讲义》)
4.DOM树的对象类型
DOM树形容XML文档的结构化特征,可以抽象为对象,DOM树中每一个节点都是一个对象。DOM中所有的节点都是一个Node对象。根据结合XML格式,DOM树的Node字对象有如下种类:
Node子接口 | 对应节点 | 描述 |
---|---|---|
Element | 元素 | 代表XML文档中开始标签、结束标签及其中间部分所组成的整体;元素之间具有父子,兄弟关联关系 |
Document | 文档对象 | 代表整个XML文档本身,Document对象中包含一个root节点 |
Attr | 属性 | 代表XML元素的属性 |
DocumentType | 文档类型 | |
CharacterData | 字符数据 | 代表各种字符数据 |
Comment | 注释 | 代表注释所包含的字符 |
CDataSession | CDATA片段 | XML文档中,放在CDATA标签中的字符对象 |
Notation | 符号 | 代表DTD语义约束中声明的符号 |
Text | 文本数据 | 代表XML文档中的文本数据 |
ProcessingInstruction | 处理指令 | XML中的指令数据 |
总结
上面是对DOM和SAX解析机制的理论介绍;通过对上述基本内容的认识,可以理解XML文档底层解析的方法和流程。
在Java语言中,jdk提供了JAXP接口,能够实现支持DOM和SAX解析机制的实现方法。后面的文章会一一叙述。