《SAX解析XML文档.ppt》由会员分享,可在线阅读,更多相关《SAX解析XML文档.ppt(42页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、SAX解析XML文档学 习 目 标q掌握SAX的概念和特点q理解SAX的工作机制q了解SAX的常用接口q熟练掌握SAX解析XML文档的步骤q熟练掌握解析器和事件处理器的创建和使用q掌握SAX和DOM共同构建XML文档基于DOM的解析器的核心是在内存中建立和在内存中建立和XML文档相对应的树状结构文档相对应的树状结构。XML文件的标记、标记中的文本数据和实体等都是内存中的树状结构的某个节点相对应。v优点:可以方便地操作内存中的树状节点v缺点:如果XML文件较大,或者只需要解析XML文档的一部分数据,就会占用大量的内存空间SAX简介vSAX没有官方的标准机构,它不属于任何标准组织或团体,也不属于任
2、何公司或个人,而是供任何人使用的一种计算机技术。vSAX是XML事实上的标准,所有的XML解析器都支持它,已经被Java,C#等语言编写实现vSAX是一种基于事件的APISAX概述 SAX是Simple API for XML,简易应用程序编写接口。解析的核心是事件处理机制解析的核心是事件处理机制,具有占用内存少,效率高等特点。 SAX是一种高效的解析器,在对那些要处理大量数据的应用程序,这种特性尤为重要。它允许在读取文档时处理它,而不必等到整个文档都被存储之后才采用该操作。SAX的工作机制【重点掌握】 SAX在概念上与DOM完全不同。它采用事件事件机制的方式机制的方式来解析XML文档。使用S
3、AX解析器对XML文档进行解析时,会触发一系列事件,这些事件将被相应的事件监听器监听,从而触发相应的事件处理方法,应用程序通过这些事件处理方法实现对XML文档的访问。Java事件处理图事件事件事件源事件源事件监听器事件监听器外部动作外部动作1.将事件监听器注将事件监听器注 册到事件源册到事件源2触发事件触发事件源上事件源上事件3.生成事件生成事件对象对象4.触发事件监听器事触发事件监听器事件被作为参数传入事件被作为参数传入事件处理器件处理器事件处理器事件处理器事件处理器事件处理器.5.调用事件处理器调用事件处理器做响应做响应SAX解析解析器调用处器调用处理器方法理器方法DTD(可选)(可选)X
4、ML源源startDocumentstartElmentcharatersendElmentendDocumentEtc.输出输出SAX解析器根本不创建任何对象,它只是在遇到XML文档的各种标签时触发对应的事件,并将XML元素的内容封装成事件传出去。而程序员则负责提供事件监听器来监听这些事件,并通过事件获取XML文档信息。 SAX解析器在解析开始的时候就开始发送事件,当解析器开始处理文档开始,元素开始和文本时,负责在文档中触发一个事件,而程序员则而程序员则实现这些事件监听器,这些监听器负责处理这些实现这些事件监听器,这些监听器负责处理这些事件事件事件中包含了XML元素的内容。可以这样理解SAX
5、的解析过程:SAX解析器就像一个电子探测器,它在XML文档中一路走过来,每经过一个元素开始、元素结束、处理指令开始、处理指令结束.都将向外发送一个事件,给元素的内容就包含在该事件中,而程序则负责接收该事件,并将其内容解析出来。SAX监听器【重点掌握】SAX解析事件一共有4种,因此需要分别设置4种监听器。ContentHandler:监听XML文档内容处理事件的监听器DTDHander:监听DTD处理事件的监听器EntityResolver:监听实体处理事件的监听器ErrorHandler:监听解析错误的监听器在ContentHandler接口中定义了如下方法:void characters(c
6、har 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解
7、析器处理元素内容中可忽略的空白时触发该方法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解
8、析XML文档 黄胜霞 前台接待 发现XML文件,触发文件开始事件,监听器调用startDocument()方法处理发现“员工名单”的开始标记,触发开始标记事件,监听器调用startElement()方法处理发现和之间的空白符号,触发文本事件,监听器调用characters方法处理发现“员工”的开始标记,触发开始标记事件,监听器调用startElement()方法处理发现和之间的空白符号,触发文本事件,监听器调用characters方法处理发现“姓名”的开始标记,触发开始标记事件,监听器调用startElement()方法处理发现标记的文本内容,触发文本事件,监听器调用characters方法处
9、理发现“姓名”标记的结束标记,触发结束标记事件,监听器调用endElement()方法处理17 发现XML文件结束,触发文件结束事件,调用endDocument()方法SAX解析器【重点掌握】JAVA为SAX解析器提供了如下2组API:XMLReader 和XMLReaderFactory XMLReaderFactory工厂类createXMLReader()静态方法用于创建XMLReader。这两个类位于org.xml.sax包下。SAXParser 和SAXParserFactory SAXParserFactory工厂类的newSAXParser()实例方法用于创建SAXParser。
10、这两个类位于javax.xml.parsers包下。XMLReader定义了以下两种用于解析XML文档的方法:void parse(InputSource input):解析InputSource输入源中的XML文档void parse(String systemId):解析系统URI所代表的XML文档SAXParser定义了以下几种用于解析XML文档的方法:void parse( dh):使用指定的dh作为监听器监听SAX解析事件,解析f文件所代表的XML文档void parse(InputSource is,DefaultHandler dh):使用指定的dh作为监听器监听SAX解析事件,
11、解析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()方法临时指
12、定监听器。通过自己本身的setContentHandler(ContentHandler handler), setDTDHandler(DTDHandler handler),setEntityResolverHandler(EntityResolver resolver),setErrorHandler(ErrorHandle handler),4个方法来设置监听器。也就是说,在调用XMLReader的parse()方法来解析XML文档之前,应先调用上面4个方法设置监听SAX解析事件的监听器。如果使用XMLReader去解析XML文档,程序员需要分别为上面四个监听器提供实现类,然后调用XM
13、LReader的setXXXHandler()方法来注册监听器,这是一件麻烦的事情。幸好JAVA提供了一个DefaultHandler类来解决这个问题,这个类实现了四个监听器接口,并为这些接口中所包含的方法提供了空实现。它通常用于被继承,我们只需要重写我们所关心的监听方法,而无须为每个方法都提供实现。SAX应用利用SAX解析XML文档,涉及两个部分:解析解析器和事件监听器器和事件监听器。解析器负责读取XML文档中“行走”,每当遇到文档开始、元素开始、文本、元素结束和文档结束时,都将负责向外发送事件。程序员则负责提供事件监听器来监听这些事情,并通过事件获取XML文档信息。SAX解析器的创建及调用
14、【重点掌握】使用javax.xml.parsers包中SAXParserFactory类调用方法newInstance实例化一个解析器工厂对象.代码如下:Factory对象调用newSAXParser ()方法,创建一个SAXParser对象,也可以称为SAX解析器解析器创建完成后,就调用parse()方法解析XML文件.SAXParserFactory factory=SAXParserFactory.newInstance();SAXParser saxParser=factory.newSAXParser();Public void parse( dh)throws SAXEceptio
15、n,IOException处理文件开始和结束当SAX解析器解析XML文档时,解析到不同的标记时会触发不同的事件。当解析到文档开始和文档结束时,就会分别出发startDocument()和endDocument()方法。如果要实现处理“文件开始”和“文件结束”事件,需要在程序的类中重写这两个继承的方法。class MyHandler extends DefaultHandler;long starttime,endtime;public MyHandler(File f)file=f;public void startDocument()starttime=System.currentTimeM
16、illis();System.out.println(文件所在的路径是文件所在的路径是+();System.out.println(文件名为文件名为+();System.out.println(开始解析开始解析XML文件文件-);public void endDocument()System.out.println(解析解析XML文件结束文件结束-);endtime=System.currentTimeMillis();System.out.println(文件解析共花费文件解析共花费+(endtime-starttime)+秒秒);监听器编程部分:继承监听器编程部分:继承DefaultHan
17、dler监听器,并重写其部分方法监听器,并重写其部分方法构造函数构造函数程序员自己开发的监听器为程序员自己开发的监听器为MyHandler,它必须继承它必须继承JAXP提供的提供的DefaultHandler监听器接口,并重写其监听器接口,并重写其部分方法部分方法重写文档开始方法的内重写文档开始方法的内容。当文档开始事件触容。当文档开始事件触发的时候,就调用这个发的时候,就调用这个方法对其进行处理方法对其进行处理重写文档结束方法的内重写文档结束方法的内容。当文档结束事件触容。当文档结束事件触发的时候,就调用这个发的时候,就调用这个方法对其进行处理方法对其进行处理SAX解析器部分解析器部分SAX
18、ParserFactory factory=SAXParserFactory.newInstance();SAXParser saxParser=factory.newSAXParser(); File(Example2.xml);MyHandler handler=new MyHandler(file);saxParser.parse();调用实现调用实现DefaultHandler监听器接口类的构造函数监听器接口类的构造函数将将XML文档和监听器作为参数传入到解析器中文档和监听器作为参数传入到解析器中处理开始和结束标记【重点掌握】解析器在解析XML文档时,如果发现开始标记和结束标记就会触发
19、相应的事件。public void startElement(String uri,String localName,String qName,Attributes atts) throws SAXExceptionq uri参数表示命名空间URI,如果元素没有任何命名空间URI,或者没有正在执行的命名空间处理,则为空字符串。q localName参数表示本地名称(不带前缀),如果没有正在执行的命名空间处理,则为空字符串q qName参数表示限定的名称(带前缀)或标记名称(如果没有命名空间前缀),如果限定的名称不可用,则为空字符串q attributes参数表示这个参数可以获得相应的标记的属性
20、名称和属性的值class MyHandler extends DefaultHandlerint 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(+qName+ ); for(int k=0;k); public void endElement(String uri,Strin
21、g 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
22、 SAXEceptionq ch 参数中存放SAX解析器解析的文本数据qStart是数组ch中存放字符的起始位置qLength是存放的字符个数处理空白在XML文件中,标记之间的缩进区域都是为了使XML文件看起来更加美观.但是解析器却把它们作为文本数据来处理.在处理文本事件时,会调用characters()方法来处理.会一并处理文本之间的空白字符,这样会延长整个程序的执行时间.这个时候,可以重写下面的方法public void ignorableWhitespace(char ch,int start,int length)throws SAXEception处理命名空间命名空间的声明在一个标记
23、的开始标记中,当解析器在一个标记的开始标记发现一个命名空间声明时,就会报告一个“命名空间开始”事件给事件处理器.解析器报告的事件顺序是:“命名空间开始”、“开始标记”、“文本数据”、“文本数据”、“结束标记”和“命名空间结束”事件。public void startPrefixMapping(String prefix,String uri)throws SAXEception使用DTD验证XML的有效性如果使用SAXParser和SAXParserFactory这组API进行解析,则直接调用SAXParserFactory实例的setValidating(true)方法即可。代码如下:/启用
24、DTD校验XML文档的有效性factory.setValidating(true); SAX和命名空间使用SAX解析方式时,命名空间的信息一样通过ContentHandler监听器获得,该监听器里包含的startElement,endElement,StartPerfixMapping和endPrefixMapping 4 个方法用于获取命名空间相关信息。希望SAX解析器能够获取XML文档的命名空间,需要两部:启用SAX解析器的命名空间支持通过以上四个方法获取当XML文档中某个元素具有xmlns:prefix属性时,StartPerfixMapping和endPrefixMapping 两个方
25、法会被监听器所出发,StartPerfixMapping方法会在处理元素方法之前(startElement方法被触发)之前被触发。而endPrefixMapping方法将在处理元素结束之后(endElement方法被触发之后)被触发。使用XML Schema验证XML文档不管是使用DOM方式还是SAX方式来解析XML文档,可以通过XML Schema来验证XML文档的有效性。如果使用DOM方式解析XML文档,可以通过DocumentBuilderFactory对象的setSchema(Schema schema)方法启用XML Schema验证XML的有效性。如果使用SAX方式解析XML文档,
26、可以通过SAXParserFactory对象的setSchema(Schema schema)方法启用XML Schema验证XML的有效性Schema对象Schema对象就代表一份XML Schema文档。通常采用工厂类SchemaFactory来获取Schema对象。newInstance(String schemaLanguage)方法获取SchemaFactory 对象。schemaLauage参数支持的常量值对应的字符串对应的语言XMLConstants.W3C_XML_SCHEMA_NS_URIW3C XML Schema 1.0 XMLConstants.RELAXNG_NS_U
27、RI RELAX NG 1.0 使用XML Schema验证XML文档创建创建SchemaFactory对象对象SchemaFactory schemaFactory = SchemaFactory.newInstance(String schemaLanguage);通过通过SchemaFactory对象创建对象创建Schema对象对象Schema schema = schemaFactory.newSchema(File schema);如果传入的Schema文档本身是无效的,那么该方法会抛出SAXParseException.创建创建DOM或或SAX解析器的工厂类对象解析器的工厂类对象启
28、动解析器其工厂类对象的对命名空间的支持启动解析器其工厂类对象的对命名空间的支持解析器利用已有的解析器利用已有的shema验证验证xml文档文档基于DOM和SAX解析机制都需要启动解析器工厂的命名空间的支持,这是必须的DOM解析和SAX解析Schema有效性相同的是,为了保证程序能自己处理验证过程中发生的验证错误,同样需要指定ErrorHandler监听器使用XML Schema验证XML文档如果只需要利用Schema验证XML文档的有效性,其实无需解析XML文档,只要简单利用Validator接口即可,该接口提供了一个validate(Source source) 方法用于验证指定XML文档。
29、SAX与DOM接口比较DOM和SAX采用两种截然不同的方式来解析XML文档。DOM解析方式需要一次性将整份XML文档装入内存,关键之处在于文档到对象之间的转换。从实际使用角度来看,DOM模型的作用其实就是定义了XML文档(Document)和Object(各种Node节点)之间的映射关系,从而允许用户通过内存中的树(一系列Node对象的集合)获取对应的XML文档里的信息。SAX解析的关键之处在于事件驱动,SAX解析器处理XML文档时,会自动对外发送一系列的事件,这些事件将会由程序员提供的监听器所监听。因此实现SAX解析的重要工作在于实现事件监听器,监听SAX解析器在处理XML文档时所发出的一系
30、列事件。DOMSAX速度需要一次性装入整份XML文档,并将XML文档转换为DOM树,因此速度比较慢顺序解析XML文档,无须一次装入整份XML文档,因此速度很快重复访问将XML文档转换成DOM树之后,整个解析阶段DOM常驻内存,非常适合重复访问,效率很好顺序解析XML文档,不保存已访问的数据,因此不适合重复访问。如果需要重复访问数据,则需要再次解析XML文档内存要求整个解析阶段DOM树常驻内存,对内存的要求高,内存占用率大不保存已访问数据,对内存几乎没有要求,内存占用率低修改既可读取节点内容,也可修改节点内容可读取节点内容,无法可修改节点内容复杂度完全采用面向对象的编程思维进行解析,整份XML文
31、档转换为DOM树之后,以面向对象的方式来操作各Node对象即可采用事件机制思维进行编程,SAX解析器只负责触发事件,程序负责监听所有事件,并通过事件获取XML文档中的信息SAX与DOM接口比较结论通常认为:对于解析大的XML文档,使用SAX更有优势;而对于解析下的XML文档,特别是那些需要重复读取的文档,则使用DOM更有优势。我们一般采用DOM创建XML文档,SAX访问文档中的数据。但是如果要对数据进行修改的话,只能采用DOM。浏览器对DOM的支持由于Dom已经成为一种应用非常广泛的XML解析API,因此各种主流浏览器都内置了DOM解析器用于解析XML文档。在浏览器中借助与JavaScript来解析XML文档,它本身没有解析能力主要是借助浏览器内置的DOM解析器才能解析XML文档。IE的DOM解析器通过ActiveX空间来实现 。创建解析器创建解析器 Var doc = new ActiveXObject(Microsoft.XMLDOM);设置关闭异步方式设置关闭异步方式 doc.async = false;装载装载XML文档,并转换为文档,并转换为DOM Document对象对象 doc.load();
限制150内