SAX实例

SAX(Simple API for XML)由XML-DEV邮件列表成员开发,目前版本2.0.x,民间标准.http://www.saxproject.org/ 
SAX是一种基于事件驱动的API。利用SAX解析XML文档牵涉到两个部分:解析器和事件处理器。 
解析器负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件;而事件处理器则负责对事件作出相应,对传递的XML数据进行处理。 

SAX特点:操作XML时不同全部读取到内存中。 

SAX的处理机制: 

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://orz.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" quality="high" flashvars="clipboard=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22gb2312%22%3F%3E%0A%3Cstudent%3E%0A%20%20%20%3Cname%3E%E5%BC%A0%E4%B8%89%3C%2Fname%3E%0A%3C%2Fstudent%3E%0A"></embed>
  1. <?xml version="1.0" encoding="gb2312"?>  
  2. <student>  
  3.    <name>张三</name>  
  4. </student>  

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://orz.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" quality="high" flashvars="clipboard=%E6%96%87%E6%A1%A3%E5%BC%80%E5%A7%8B%0A%20%20%E5%85%83%E7%B4%A0%E5%BC%80%E5%A7%8B(%3Cstudent%3E)%0A%20%20%20%20%E5%AD%97%E7%AC%A6%E7%A9%BA%E7%99%BD(%22%3E%22%E5%88%B0%22%3C%22%E4%B9%8B%E9%97%B4%E7%9A%84%E7%A9%BA%E7%99%BD)%0A%20%20%20%20%20%20%20%E5%85%83%E7%B4%A0%E5%BC%80%E5%A7%8B(%3Cname%3E)%0A%20%20%20%20%20%20%20%20%20%20%E5%AD%97%E7%AC%A6%E6%95%B0%E6%8D%AE(%E5%BC%A0%E4%B8%89)%0A%20%20%20%20%20%20%20%E5%85%83%E7%B4%A0%E7%BB%93%E6%9D%9F(%3C%2Fname%3E)%0A%20%20%20%20%E5%AD%97%E7%AC%A6%E7%A9%BA%E7%99%BD(%22%3E%22%E5%88%B0%22%3C%2F%22%E4%B9%8B%E9%97%B4%E7%9A%84%E7%A9%BA%E7%99%BD)%0A%20%20%E5%85%83%E7%B4%A0%E7%BB%93%E6%9D%9F(%3C%2Fstudent%3E)%0A%E6%96%87%E6%A1%A3%E7%BB%93%E6%9D%9F%0A"></embed>
  1. 文档开始  
  2.   元素开始(<student>)  
  3.     字符空白(">""<"之间的空白)  
  4.        元素开始(<name>)  
  5.           字符数据(张三)  
  6.        元素结束(</name>)  
  7.     字符空白(">""</"之间的空白)  
  8.   元素结束(</student>)  
  9. 文档结束  

SAX解析器接口和事件处理器接口在org.xml.sax包中定义。 
XMLReader是SAX2.0解析器必须实现的接口。该接口允许应用程序设置和查询解析器的功能和特性,注册处理文档的事件处理器,以及启动文档的解析。 

解析器提供商负责提供实现XMLReader接口的解析器类,我们只需编写事件处理器程序。 
SAX API中的ContnetHandle接口是一个主要的处理器接口。如果应用程序要获得基本的解析事件就必须实现该接口,并使用XMLReader对象的setContentHandler()向解析器注册一个ContentHandler()实例。解析器使用这个实例来报告与文档相关的基本事件,例如,元素开始和结束,以及字符数据等。在这个接口中,事件的顺序是非常重要的,它反映了文档自身信息的顺序。例如,元素的所有内容(字符数据,处理指令,子元素)都依次在startElement事件和对应的endElement事件之间出现。 

void setDocumentLocator(Locator locator) 
该方法接收一个用于获取文档分析时产生的SAX事件定位信息的对象。该方法将在解析器报告任何其他文档事件之前被调用。作为参数传递给这个方法的定位器对象,允许应用程序测定任何与文档相关的事件的结束位置。通常,应用程序会使用这个信息来报告它自身的错误(例如,与应用程序的商业规则不匹配的字符内容)。 

void startDocument() throws SAXException 
该方法接收文档开始的通知。SAX解析器将在任何其它事件回调方法被调用之前调用该方法(除了setDocumentLocator方法),并只调用一次。 

void endDocument() throws SAXException 
该方法接收文档结束的通知。SAX解析器只调用这个方法一次,而且它是在解析过程中最后一次被调用的方法。 

void startPrefixMapping(String prefix,String uri)throws SAXException 
void endPrefixMapping(String prefix)throws SAXException 
startPrefixMapping()在一个前缀-URI名称空间映射范围的开始时被调用。而endPrefixMapping()在前缀-URI映射范围结束时被调用。例如:下面的XML文档 
<students xmlns:stu="http://www.iteye.com/students"> 
   ..... 
</students> 
SAX解析器在分析到<students>元素时,就会调用startPrefixMapping(),将stu传递给prefix参数,将http://www.iteye.com/students传递给uri参数,然后产生<students>元素的startElement事件。在产生<students>元素的endElement事件后,解析器将调用endPrefixMapping(),将stu传递给prefix参数。 

void startElement(String uri,String localName,String qName,Attribute atts)throws SAXException 
该方法接收元素开始的通知。解析器在xml文档的每一个元素开始时调用这个方法。每一个startElement事件都有一个对应的endElement事件(即使是空元素),在endElement事件之前,元素的所有内容都被依次报告。 
这个事件允许每个元素最多有三个名称部分:1.名称空间URI;2.本地名;3.限定名;是否有这几部分,取决于http://xml.org/sax/features/namespaces和http://xml.org/sax/features/namespace-prefixes属性的值. 
a.当namespaces属性为true时,名称空间URI和本地名是必须的。当namespaces属性是false,那么二者是可选的(但如果指定了其中一个名称,那么另一个也必须指定) 
b.当namespace-prefixes属性为true,那么限定名必需的,否则是可选的,缺省值为false. 
注意:属性列表将只包含具有确切值(直接指定或缺省值)的属性,#IMPLIED属性将被忽略。只有当http://xml.org/sax/features/namespace-prefixes属性为true(缺省值为false,解析器对true值的支持是可选的),属性列表才会包括用于名称空间声明的属性(xmlns*属性) 

void endElement(String uri,String localName,String qName) throws SAXException 
该方法接收元素结束的通知。解析器在XML文档的每一个元素结束时调用这个方法。 

void characters(char[] ch,int start,int length)throws SAXException 
该方法接收字符数据的通知。解析器调用这个方法来报告字符数据块。SAX解析器会把所有连续的字符数据放在一个单独的块中返回,或者把它们分成几个数据块。不过,在任何一个单独的所有字符都必须来自同一个外部实体,以便Locator提供有用的信息(Locator要提供文档中事件结束的位置信息)。应用程序不要试图读取ch数组中指定范围以外的的数据。注意:有些解析器使用ignorableWhitespace()来报告元素内容中的空白,而不是用characters()(进行有效性验证的解析器就是如此)。 

void processingInstruction(String target,String data)throws SAXException 
该方法接收处理指令的通知。解析器每遇到一个处理指令就调用该方法一次。注意:处理指令可以在XML文档的根元素(文档元素)之前或之后出现。 

void skippedEntity(String name)throws SAXException 
该方法接收跳过的实体的通知。解析器每跳过一个实体就会调用该方法。非验证的解析器如果没有看到实体声明的话(例如实体在外部的DTD子集中的声明),可以跳过实体。所有的处理器是否跳过外部的实体取决于http://xml.org/sax/features/external-general-entities和http://xml.org/sax/features/exteral-parameter-entities属性(property)的值。 

配置SAX解析器有两种方法:功能和特性。 
功能包括打开和关闭某个功能。例如验证。 
特性包括设置解析器所使用的特定项的值,例如设置SAX词法分析器实例。 
1.功能(feature)是通过XMLReader接口中的setFeature()来设置的,例如要打开验证功能可调用setFeature(): xmlReader.setFeature("http://xml.org/sax/feature/validation",true); 

注意:在SAX中每一个功能都是由一个特定的URI来标识,当前的标准功能的URI都以http://xml.org/sax/features/作为前缀,下面列出常用功能的URI: 
-http://xml.org/sax/features/namespaces 
如果namespace为true,则解析器执行名称空间处理。在事件处理器的相应方法中,所有元素和属性的名称空间URI和未限定的本地名称可以使用。任何SAX2.0兼容的解析器都支持将namespaces的默认值设成true。 
-http://xml.org/sax/features/namespace=prefixes 
如果namespace-prefixes设为true时,则解析器对名称空间前缀的解析提供支持。在事件处理器的相应方法中,XML限定名(带前缀的名称)和属性(包括xmlns*属性)将可以使用。任何SAX2.0兼容的解析器都支持将namespace-prefixes的默认值设为false。 
-http://xml.org/sax/features/external-general-entities 
设置解析器是否处理外部的一般实体。如果对解析器启用了验证功能。则external-general-entities将总是true。 
-http://xml.org/sax/features/external-parameter-entities 
设置解析器是否处理外部的参数实体。如果对解析器启用了验证功能。则external-general-entities将总是true。 
-http://xml.org/sax/features/validation 
设置解析器是否验证文档。如果为true,则所有的外部实体都将被处理。 

2.特性(property)是通过XMLReader接口中的setProperty()来设置的。特性和功能的设置是类似的,区别是特性以对象作为参数,而功能以布尔值作为参数。例如要设置词法分析器实例 ,可调用setProperty(): xmlReader.setProperty("http://xml.org/sax/properties/lexical-handle",new MyLexicalHandler()); 

SAX解析器工厂:javax.xml.parsers.SAXParserFactory 
如果使用Apache的Xerces解析器,可配置如下: 
javax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl 

SAX实例一: 
SAXPrinter.java输出跟students.xml一样的数据。 
Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://orz.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" quality="high" flashvars="clipboard=import%20java.io.File%3B%0Aimport%20java.io.IOException%3B%0Aimport%20javax.xml.parsers.ParserConfigurationException%3B%0Aimport%20javax.xml.parsers.SAXParser%3B%0Aimport%20javax.xml.parsers.SAXParserFactory%3B%0Aimport%20org.xml.sax.Attributes%3B%0Aimport%20org.xml.sax.SAXException%3B%0Aimport%20org.xml.sax.helpers.DefaultHandler%3B%0A%0A%2F%2F%E9%87%8D%E5%86%99%E4%BA%86DefaultHandler%E7%9A%845%E4%B8%AA%E6%96%B9%E6%B3%95%0Apublic%20class%20SAXPrinter%20extends%20DefaultHandler%7B%0A%0A%09%40Override%0A%09%2F%2F%E6%96%87%E6%A1%A3%E5%BC%80%E5%A7%8B%0A%09public%20void%20startDocument()%20throws%20SAXException%20%7B%0A%09%09%2F%2F%E8%BE%93%E5%87%BA%E5%8F%8C%E5%BC%95%E5%8F%B7%E5%8F%AF%E4%BB%A5%E7%94%A8%E5%8F%8D%E6%96%9C%E6%9D%A0%E4%B9%9F%E5%8F%AF%E8%BE%93%E5%87%BA%E5%8D%95%E5%BC%95%E5%8F%B7%0A%09%09System.out.println(%22%3C%3Fxml%20version%3D%5C%221.0%5C%22%20encoding%3D'gb2312'%3F%3E%22)%3B%0A%09%7D%0A%09%0A%09%40Override%0A%09%2F%2F%E5%A4%84%E7%90%86%E6%8C%87%E4%BB%A4%0A%09public%20void%20processingInstruction(String%20target%2C%20String%20data)%20throws%20SAXException%20%7B%0A%09%09System.out.println(%22%3C%3F%22%2Btarget%2B%22%20%22%2Bdata%2B%22%3F%3E%22)%3B%0A%09%7D%0A%09%0A%09%40Override%0A%09%2F%2F%E5%85%83%E7%B4%A0%E5%BC%80%E5%A7%8B%0A%09public%20void%20startElement(String%20uri%2C%20String%20localName%2C%20String%20qName%2C%20Attributes%20attrs)%20throws%20SAXException%20%7B%0A%09%09System.out.print(%22%3C%22%2BqName)%3B%0A%09%09int%20len%20%3D%20attrs.getLength()%3B%0A%09%09for(int%20i%3D0%3Bi%3Clen%3Bi%2B%2B)%7B%0A%09%09%09System.out.print(%22%20%22)%3B%0A%09%09%09System.out.print(attrs.getQName(i))%3B%0A%09%09%09System.out.print(%22%3D%5C%22%22)%3B%0A%09%09%09System.out.print(attrs.getValue(i))%3B%0A%09%09%09System.out.print(%22%5C%22%22)%3B%0A%09%09%7D%0A%09%09System.out.print(%22%3E%22)%3B%0A%09%7D%0A%09%0A%09%40Override%0A%09%2F%2F%E5%A4%84%E7%90%86%E5%AD%97%E7%AC%A6(%E7%94%B1%E7%A9%BA%E7%99%BD%E7%BB%84%E6%88%90%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%9C%8B%E6%88%90%E6%A0%BC%E5%BC%8F)%0A%09public%20void%20characters(char%5B%5D%20ch%2C%20int%20start%2C%20int%20length)%20throws%20SAXException%20%7B%0A%09%09System.out.print(new%20String(ch%2Cstart%2Clength))%3B%0A%09%7D%0A%0A%0A%09%40Override%0A%09%2F%2F%E5%85%83%E7%B4%A0%E7%BB%93%E6%9D%9F%0A%09public%20void%20endElement(String%20uri%2C%20String%20localName%2C%20String%20qName)%20throws%20SAXException%20%7B%0A%09%09System.out.print(%22%3C%2F%22%2BqName%2B%22%3E%22)%3B%0A%09%7D%0A%0A%09public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%09%09SAXParserFactory%20spf%20%3D%20SAXParserFactory.newInstance()%3B%0A%09%09try%20%7B%0A%09%09%09SAXParser%20sp%20%3D%20spf.newSAXParser()%3B%0A%09%09%09sp.parse(new%20File(%22students.xml%22)%2Cnew%20SAXPrinter())%3B%0A%09%09%7D%20catch%20(ParserConfigurationException%20e)%20%7B%0A%09%09%09%2F%2F%20TODO%20%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%20catch%20%E5%9D%97%0A%09%09%09e.printStackTrace()%3B%0A%09%09%7D%20catch%20(SAXException%20e)%20%7B%0A%09%09%09%2F%2F%20TODO%20%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%20catch%20%E5%9D%97%0A%09%09%09e.printStackTrace()%3B%0A%09%09%7D%20catch%20(IOException%20e)%20%7B%0A%09%09%09%2F%2F%20TODO%20%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%20catch%20%E5%9D%97%0A%09%09%09e.printStackTrace()%3B%0A%09%09%7D%0A%09%7D%0A%0A%7D%0A"></embed>
  1. import java.io.File;  
  2. import java.io.IOException;  
  3. import javax.xml.parsers.ParserConfigurationException;  
  4. import javax.xml.parsers.SAXParser;  
  5. import javax.xml.parsers.SAXParserFactory;  
  6. import org.xml.sax.Attributes;  
  7. import org.xml.sax.SAXException;  
  8. import org.xml.sax.helpers.DefaultHandler;  
  9.   
  10. //重写了DefaultHandler的5个方法  
  11. public class SAXPrinter extends DefaultHandler{  
  12.   
  13.     @Override  
  14.     //文档开始  
  15.     public void startDocument() throws SAXException {  
  16.         //输出双引号可以用反斜杠也可输出单引号  
  17.         System.out.println("<?xml version=\"1.0\" encoding='gb2312'?>");  
  18.     }  
  19.       
  20.     @Override  
  21.     //处理指令  
  22.     public void processingInstruction(String target, String data) throws SAXException {  
  23.         System.out.println("<?"+target+" "+data+"?>");  
  24.     }  
  25.       
  26.     @Override  
  27.     //元素开始  
  28.     public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {  
  29.         System.out.print("<"+qName);  
  30.         int len = attrs.getLength();  
  31.         for(int i=0;i<len;i++){  
  32.             System.out.print(" ");  
  33.             System.out.print(attrs.getQName(i));  
  34.             System.out.print("=\"");  
  35.             System.out.print(attrs.getValue(i));  
  36.             System.out.print("\"");  
  37.         }  
  38.         System.out.print(">");  
  39.     }  
  40.       
  41.     @Override  
  42.     //处理字符(由空白组成的数据,可以看成格式)  
  43.     public void characters(char[] ch, int start, int length) throws SAXException {  
  44.         System.out.print(new String(ch,start,length));  
  45.     }  
  46.   
  47.   
  48.     @Override  
  49.     //元素结束  
  50.     public void endElement(String uri, String localName, String qName) throws SAXException {  
  51.         System.out.print("</"+qName+">");  
  52.     }  
  53.   
  54.     public static void main(String[] args) {  
  55.         SAXParserFactory spf = SAXParserFactory.newInstance();  
  56.         try {  
  57.             SAXParser sp = spf.newSAXParser();  
  58.             sp.parse(new File("students.xml"),new SAXPrinter());  
  59.         } catch (ParserConfigurationException e) {  
  60.             // TODO 自动生成 catch 块  
  61.             e.printStackTrace();  
  62.         } catch (SAXException e) {  
  63.             // TODO 自动生成 catch 块  
  64.             e.printStackTrace();  
  65.         } catch (IOException e) {  
  66.             // TODO 自动生成 catch 块  
  67.             e.printStackTrace();  
  68.         }  
  69.     }  
  70.   
  71. }  

SAX实例二: 
ErrorProcessor.java演示错误处理器的使用 
如果SAX应用程序需要实现定制的错误处理,那么它必须实现这个接口,并调用XMLReader对象的setErrorHandler()向解析器注册一个实例。之后解析器将通过这个接口报告所有的错误和 
警告。 
students2.xml 
Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://orz.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" quality="high" flashvars="clipboard=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22gb2312%22%3F%3E%0A%0A%3C%3Fxml-stylesheet%20type%3D%22text%2Fxsl%22%20href%3D%22student.xsl%22%3F%3E%0A%0A%3C!DOCTYPE%20students%5B%0A%3C!ELEMENT%20students%20(student%2B)%3E%0A%3C!ELEMENT%20student%20(name%2Cage%2Cscore)%3E%0A%3C!ELEMENT%20name%20(%23PCDATA)%3E%0A%3C!ELEMENT%20age%20(%23PCDATA)%3E%0A%3C!ELEMENT%20score%20(%23PCDATA)%3E%0A%3C!ATTLIST%20student%20sn%20CDATA%20%23REQUIRED%3E%0A%5D%3E%0A%0A%3Cstudents%3E%0A%20%20%3Cstudent%20sn%3D%2201%22%3E%0A%20%20%20%20%20%3Cname%3E%E5%BC%A0%E4%B8%89%3C%2Fname%3E%0A%20%20%20%20%20%3Cage%3E11%3C%2Fage%3E%0A%20%20%3C%2Fstudent%3E%0A%20%20%3Cstudent%20sn%3D%2202%22%3E%0A%20%20%20%20%20%3Cname%3E%E6%9D%8E%E5%9B%9B%3C%2Fname%3E%0A%20%20%20%20%20%3Cage%3E14%3C%2Fage%3E%0A%20%20%3C%2Fstudent%3E%0A%3C%2Fstudents%3E%0A"></embed>
  1. <?xml version="1.0" encoding="gb2312"?>  
  2.   
  3. <?xml-stylesheet type="text/xsl" href="student.xsl"?>  
  4.   
  5. <!DOCTYPE students[  
  6. <!ELEMENT students (student+)>  
  7. <!ELEMENT student (name,age,score)>  
  8. <!ELEMENT name (#PCDATA)>  
  9. <!ELEMENT age (#PCDATA)>  
  10. <!ELEMENT score (#PCDATA)>  
  11. <!ATTLIST student sn CDATA #REQUIRED>  
  12. ]>  
  13.   
  14. <students>  
  15.   <student sn="01">  
  16.      <name>张三</name>  
  17.      <age>11</age>  
  18.   </student>  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值