ch7SAX解析XML文档.ppt_第1页
ch7SAX解析XML文档.ppt_第2页
ch7SAX解析XML文档.ppt_第3页
ch7SAX解析XML文档.ppt_第4页
ch7SAX解析XML文档.ppt_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第七章 SAX解析XML文档,学 习 目 标 掌握SAX的概念和特点 理解SAX的工作机制 了解SAX的常用接口 熟练掌握SAX解析XML文档的步骤 熟练掌握解析器和事件处理器的创建和使用 掌握SAX和DOM共同构建XML文档,基于DOM的解析器的核心是在内存中建立和XML 文档相对应的树状结构。XML文件的标记、标记中 的文本数据和实体等都是内存中的树状结构的某个节 点相对应。 优点:可以方便地操作内存中的树状节点 缺点:如果XML文件较大,或者只需要解析XML文档的一部分数据,就会占用大量的内存空间,SAX简介,SAX没有官方的标准机构,它不属于任何标准组织或团体,也不属于任何公司或个人,而是供任何人使用的一种计算机技术。 SAX是XML事实上的标准,所有的XML解析器都支持它,已经被Java,C#等语言编写实现 SAX是一种基于事件的API,SAX概述,SAX是Simple API for XML,简易应用程序编 写接口。解析的核心是事件处理机制,具有占用 内存少,效率高等特点。 SAX是一种高效的解析器,在对那些要处理 大量数据的应用程序,这种特性尤为重要。它允 许在读取文档时处理它,而不必等到整个文档都 被存储之后才采用该操作。,SAX在概念上与DOM完全不同。它采用事件 机制的方式来解析XML文档。使用SAX解析器对 XML文档进行解析时,会触发一系列事件,这些 事件将被相应的事件监听器监听,从而触发相应 的事件处理方法,应用程序通过这些事件处理方 法实现对XML文档的访问。,大多数的SAX都会实现以下几种类型的事件 在文档的开始和结束时触发文档处理事件 在文档内每一个XML元素都在接受解析的前后触发元素事件。任何元数据通常都是由单独的事件交付。这是我们最关心的事件。通常,SAX解析器会向应用程序提供包含元素信息的事件参数,在最低程度上也会提供元素的名字。 在处理文档的DTD或Schema时产生DTD或Schema事件 错误事件用来通知主机应用程序解析错误,SAX解析器在解析开始的时候就开始发送事 件,当解析器开始处理文档开始,元素开始和文 本时,负责在文档中触发一个事件,而程序员则 实现这些事件监听器,这些监听器负责处理这些 事件事件中包含了XML元素的内容。,SAX解析器根本不创建任何对象,它只是在遇到XML文档的各种标签 时触发对应的事件,并将XML元素的内容封装成事件传出去。而程序 员则负责提供事件监听器来监听这些事件,并通过事件获取XML文档 信息。,SAX监听器【重点掌握】,SAX解析事件一共有4种,因此需要分别设置4 种监听器。 ContentHandler:监听XML文档内容处理事件的监听器 DTDHander:监听DTD处理事件的监听器 EntityResolver:监听实体处理事件的监听器 ErrorHandler:监听解析错误的监听器,在ContentHandler接口中定义了如下方法: void characters(char ch,int start,int length):SAX解析器处理字符数据时触发该方法 void endDocument(): SAX解析器处理文档结束时触发该方法 void endElement(String uri,String localName,String qName): SAX解析器处理元素结束时触发该方法 void endPrefixMapping(String prefix):SAX解析器处理元素里命名空间属性(即xmlns:prefix属性)结束时触发该方法,void ignorableWhitesapce(char ch,int start,int length):SAX解析器处理元素内容中可忽略的空白时触发该方法 void skippedEntity(String name):SAX解析器跳过实体时触发该方法 void startDocument(): SAX解析器开始处理文档时触发该方法 void startElement(String uri,String localName,String qName,Attributes atts): SAX解析器开始处理元素时触发该方法 void startPrefixMapping(String prefix,String uri):SAX解析器开始处理元素里命名空间属性(即xmlns:prefix属性)时触发该方法,SAX解析器【重点掌握】,JAXP为SAX解析器提供了如下2组API: XMLReader 和XMLReaderFactory XMLReaderFactory工厂类createXMLReader()静态方法用于创建XMLReader。这两个类位于org.xml.sax包下。 SAXParser 和SAXParserFactory SAXParserFactory工厂类的newSAXParser()实例方法用于创建SAXParser。这两个类位于javax.xml.parsers包下。,XMLReader定义了以下两种用于解析XML文档 的方法: void parse(InputSource input):解析InputSource输入源中的XML文档 void parse(String systemId):解析系统URI所代表的XML文档,SAXParser定义了以下几种用于解析XML文档的方法: void parse(File f,DefaultHandler dh):使用指定的dh作为监听器监听SAX解析事件,解析f文件所代表的XML文档 void parse(InputSource is,DefaultHandler dh):使用指定的dh作为监听器监听SAX解析事件,解析is输入源的XML文档 void parse(InputStream is, DefaultHandler dh):使用指定的dh作为监听器监听SAX解析事件,解析is输入流的XML文档 void parse(String uri, DefaultHandler dh):使用指定的dh作为监听器监听SAX解析事件,解析系统URI所代表的XML文档,提问:为何XMLReader在调用时不需要传入SAX解析时间的监听器呢?SAX解析不是总是基于事件机制的吗?,回答:的确是这样。因此使用XMLReader解析XML文档 时一样需要制定监听器来监听事件。只不过XMLReader 不通过parse()方法临时指定监听器。通过自己本身的 setContentHandler(ContentHandler handler), setDTDHandler(DTDHandler handler), setEntityResolverHandler(EntityResolver resolver), setErrorHandler(ErrorHandle handler), 4个方法来设置监听器。也就是说,在调用XMLReader 的parse()方法来解析XML文档之前,应先调用上面4个方 法设置监听SAX解析事件的监听器。,如果使用XMLReader去解析XML文档,程序员需要分 别为上面四个监听器提供实现类,然后调用XMLReader 的setXXXHandler()方法来注册监听器,这是一件麻烦的 事情。 幸好JAXP提供了一个DefaultHandler类来解决这个问 题,这个类实现了四个监听器接口,并为这些接口中所 包含的方法提供了空实现。它通常用于被继承,我们只 需要重写我们所关心的监听方法,而无须为每个方法都 提供实现。,答: XMLReader是SAX规范定义的解析器接口,ContentHander、 DTDHandler、EntityResolver和ErrorHandler也是SAX规范定义的监 听器器接口。他们通常结合在一起用。 SAXParse是JAXP对XMLReader的进一步包装,使用SAXParse 可以进步一简化SAX解析编程,而DefaultHandler则是上面四种监听 器的实现类,用于简化监听器编程。 所以,我们通常选择SAXParse+ DefaultHandler来解析XML文档。 除非开发者非常喜欢原生的SAX解析,或者考虑到某些原生的特性 才会选用XMLReader,提问:XMLReader和SAXParser到底是什么关系?我们到底应该用哪个呢?,SAX对象的创建及调用【重点掌握】,使用javax.xml.parsers包中SAXParserFactory类调用方法newInstance 实例化一个解析器工厂对象.代码如下: Factory对象调用newnewSAXParser ()方法,创建一个SAXParser对象,也可以称为SAX解析器 解析器创建完成后,就调用parse()方法解析XML文件.,SAXParserFactory factory=SAXParserFactory.newInstance();,DocumentBuilder builder=factory.newDocumentBuilder();,Public void parse(File f,DefaultHandler dh)throws SAXEception,IOException,SAX解析XML文档, 黄胜霞 前台接待 ,发现XML文件,触发文件开始事件,监听器调用startDocument()方法处理 发现“员工名单”的开始标记,触发开始标记事件,监听器调用startElement()方法处理 发现和之间的空白符号,触发文本事件,监听器调用characters方法处理,发现“员工”的开始标记,触发开始标记事件,监听器调用startElement()方法处理 发现和之间的空白符号,触发文本事件,监听器调用characters方法处理 发现“姓名”的开始标记,触发开始标记事件,监听器调用startElement()方法处理 发现标记的文本内容,触发文本事件,监听器调用characters方法处理 发现“姓名”标记的结束标记,触发结束标记事件,监听器调用endElement()方法处理 17 发现XML文件结束,触发文件结束事件,调用endDocument()方法,SAX应用,利用SAX解析XML文档,涉及两个部分:解析 器和事件监听器。 解析器负责读取XML文档中“行走”,每当遇到文档开始、元素开始、文本、元素结束和文档结束时,都将负责向外发送事件。 程序员则负责提供事件监听器来监听这些事情,并通过事件获取XML文档信息。,可以这样理解SAX的解析过程:SAX解析器就 像一个电子探测器,它在XML文档中一路走过 来,每经过一个元素开始、元素结束、处理指令 开始、处理指令结束都将向外发送一个事 件,给元素的内容就包含在该事件中,而程序则 负责接收该事件,并将其内容解析出来。,基于事件委托处理模式,Source:事件源 Xlistener:事件处理者(监听器),处理文件开始和结束,当SAX解析器解析XML文档时,解析到不同的 标记时会触发不同的事件。当解析到文档开始和 文档结束时,就会分别出发startDocument()和 endDocument()方法。 如果要实现处理“文件开始”和“文件结束”事件, 需要在程序的类中重写这两个继承的方法。,class MyHandler extends DefaultHandler File file; long starttime,endtime; public MyHandler(File f)file=f; public void startDocument() starttime=System.currentTimeMillis(); System.out.println(“文件所在的路径是“+file.getAbsolutePath(); System.out.println(“文件名为“+file.getName(); System.out.println(“开始解析XML文件-“); public void endDocument() System.out.println(“解析XML文件结束-“); endtime=System.currentTimeMillis(); System.out.println(“文件解析共花费“+(endtime-starttime)+“秒“); ,监听器编程部分:继承DefaultHandler监听器,并重写其部分方法,构造函数,程序员自己开发的监听器为MyHandler,它必须继承 JAXP提供的DefaultHandler监听器接口,并重写其 部分方法,重写文档开始方法的内 容。当文档开始事件触 发的时候,就调用这个 方法对其进行处理,重写文档结束方法的内 容。当文档结束事件触 发的时候,就调用这个 方法对其进行处理,SAX解析器部分,处理开始和结束标记【重点掌握】,解析器在解析XML文档时,如果发现开始标记和结 束标记就会触发相应的事件。,public void startElement(String uri,String localName,String qName, Attributes atts) throws SAXException,uri参数表示命名空间URI,如果元素没有任何命名空间URI,或者没有正在执行的命名空间处理,则为空字符串。 localName参数表示本地名称(不带前缀),如果没有正在执行的命名空间处理,则为空字符串 qName参数表示限定的名称(带前缀)或标记名称(如果没有命名空间前缀),如果限定的名称不可用,则为空字符串 attributes参数表示这个参数可以获得相应的标记的属性名称和属性的值,class MyHandler extends DefaultHandler int count=0;String str=null; public void startElement(String uri,String localName,String qName,Attributes atts) count+; if(uri.length()0) str=uri; System.out.println(str); System.out.print(“); public void endElement(String uri,String localName,String qName) System.out.println(“); public void endDocument() System.out.println(“解析文件结束一共有“+count+“标记“); System.out.println(“文件使用的命名空间是“+str); ,处理文本数据,XML文件中标记的内容是文本数据,当SAX解析器解析这 些数据时,会报告“文本数据”事件给事件处理器,事件处 理器在获取事件信息后,就会调用下面的方法,对解析 的数据做出处理。,public void characters(char ch,int start,int length)throws SAXEception,ch 参数中存放SAX解析器解析的文本数据 Start是数组ch中存放字符的起始位置 Length是存放的字符个数,练习一, 修改文稿 看书 跑步 ,打印XML文档的根元素 打印所有节点的属性和内容, 刘海松 2000 刘红霞 879 李张利 3200 陈凡灵 1680 ,要求: 如何获取普通员工月收入合计? 如何获取经理月收入合计? 如何获取所有员工月收入合计?,处理空白,在XML文件中,标记之间的缩进区域都是为了使XML文件 看起来更加美观.但是解析器却把它们作为文本数据来处理. 在处理文本事件时,会调用characters()方法来处理.会一并 处理文本之间的空白字符,这样会延长整个程序的执行时间. 这个时候,可以重写下面的方法,public void ignorableWhitespace(char ch,int start,int length) throws SAXEception,处理命名空间,命名空间的声明在一个标记的开始标记中,当解 析器在一个标记的开始标记发现一个命名空间声 明时,就会报告一个“命名空间开始”事件给事件处 理器.解析器报告的事件顺序是:“命名空间开始”、 “开始标记”、“文本数据”、“文本数据”、“结束标 记”和“命名空间结束”事件。,public void startPrefixMapping(String prefix,String uri)throws SAXEception,SAX与DOM接口比较,DOM和SAX采用两种截然不同的方式来解析 XML文档。 DOM解析方式需要一次性将整份XML文档装入内存,关键之处在于文档到对象之间的转换。从实际使用角度来看,DOM模型的作用其实就是定义了XML文档(Document)和Object(各种Node节点)之间的映射关系,从而允许用户通过内存中的树(一系列Node对象的集合)获取对应的XML文档里的信息。,SAX解析的关键之处在于事件驱动,SAX解析器处理XML文档时,会自动对外发送一系列的事件,这些事件将会由程序员提供的监听器所监听。因此实现SAX解析的重要工作在于实现事件监听器,监听SAX解析器在处理XML文档时所发出的额一系列事件。,SAX与DOM接口比较,结论,通常认为:对于解析大的XML文档,使用SAX 更有优势;而对于解析下的XML文档,特别是那 些需要重复读取的文档,则使用DOM更有优势

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论