SAX_Parser 介绍 实例 –学习笔记 (xml 解析)
读取xml主要有两种方法
1. 标准方法是 DOM(”文档对象模型”)。 这种方法需要读取整个文件并将它存储到树结构中,因而效率不高、缓慢,并且会过度使用资源
2 . SAX , 一种替代方法是使用 Simple API for XML 或 SAX。SAX 允许正在读取文档时处理该文档,这避免了在采取操作之前需要等待存储文档的 所有内容。
解析器将事件(譬如,元素的开始或结束)发送给处理信息的事件处理程序。然后,应用程序自己可以处理数据。虽然原始文档保持不变,但 SAX 提供了操纵数据的方法,然后会将该方法导向另一个过程或文档。
- 应用程序的目的:如果必须对数据进行更改,并且作为 XML 将它输出,则在大多数情况下,使用 DOM。与使用 XSL 转换来完成的简单结构更改不一样,如果是对数据本身进行更改,则尤其应该使用 DOM。
- 数据的数量:对于大文件,SAX 是更好的选择。
- 将如何使用数据:如果实际上只使用一小部分数据,则使用 SAX 将数据抽取到应用程序中,这种方法更好些。另一方面,如果知道将需要向后引用已经处理过的信息,则 SAX 可能不是正确的选择。
- 需要速度:通常,SAX 实现比 DOM 实现快。
记住 SAX 和 DOM 不是互斥的,这一点很重要。可以使用 DOM 来创建事件的 SAX 流,可以使用 SAX 来创建 DOM 树。事实上,大多数解析器实际常常使用 SAX 来创建 DOM 树!
废话少说,看一个例子就知道改如何使用SAX来解析xml了。
package test;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
public class TestHandler extends DefaultHandler {
public TestHandler() {
// TODO Auto-generated constructor stub
}
//文档开头处理,根据实际应用而变
public void startDocument() {
System.err.println(”document begin”);
}
//具体元素的处理,qName 元素名,attrs其对于的属性
public void startElement(String uri, String localName, String qName,
Attributes attrs) {
try {
Thread.sleep(50); //too see the output clearly
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(qName.equalsIgnoreCase(”property”)){
for(int i=0; i < attrs.getLength(); i++)
{
String value= attrs.getValue(i);
System.out.print(value +”t”);
}
System.out.println();
}
//
}
public void endDocument() {
System.err.println(”document end “);
}
//Response the endElement event
public void endElement(String uri, String localName, String qName) {
System.err.println(”element end “);
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
xmlReader.setContentHandler(new TestHandler());
xmlReader.parse(new InputSource(”buildTest.xml”));
// sp.parse(new InputSource(”film.xml”),reader);
}
catch(Exception e){
e.printStackTrace();
}
}
}
//////////////////////////////////////////////////////////////////////////
通过以上例子,可以明白,用SAX解析xml,我只需继承DefaultHandler,实现其中的事件处理方法即可,具体看实际应用。
<?xml version=”1.0″?>
<project name=”Alias-i LingPipe” default=”compile” basedir=”.”>
<property name=”version”
value=”3.4.0″/>
<property name=”previous_version”
value=”3.3.0″/>
</project>
SAX 事件
以下事件是常用的;它们都在 org.xml.sax 包的 HandlerBase 类中定义。
- startDocument 表示文档开始。
- endDocument 表示文档结束。
- startElement 表示元素开始。当一对标记中的起始标记中的所有内容被处理后,解析器 激发此事件。包括了标记名和其属性。
- endElement 表示元素结束。
- characters 包含字符数据,类似于 DOM 的一个 Text 节点。
还有更多的 SAX 事件:
- ignorableWhitespace 此事件类似于我们前面所讨论的无用 DOM 节点。它与 character 事件的区别,好处是:如果您不需要空格符,您可以通过忽略这个事件来忽略所有的空格符。
- warning、error 和 fatalError 这三个事件表示了解析错误。您可根据需要来响应它们。
- setDocumentLocator 这个事件允许您存储一个 SAX 的 Locator 对象。Locator 对象可以用来找出在文档中确切发生事件的地方。
///////////////////////另外再转载一篇,太全了,当参考资料///////////////////////////////
http://zhengzb0924.blog.163.com/blog/static/3038744020075110502218/
解析xml之–SAX
SAX同DOM一样也是一个访问XML文档的接口。SAX是Simple API for XML的缩写。它不像DOM那样是W3C的推荐标准。它是由XML-DEV邮件列表的成员开发维护,由David Megginson领导(david@megginson.com)的一个Public Domain软件。SAX是一个彻底的自由软件,它的作者放弃了对它的所有权利,并且它也被许可用于任何目的(在文章最后附录了它的版权声明)。
到现在为止SAX的版本已经发展到2.0。在这个最新版本中增加了对名称空间(Namespaces)的支持,而且可以通过对features以及properties的设置来对解析器做全面的配置,这其中包括设置解析器是否对文档进行有效性验证,以及怎样来处理带有名称空间的元素名称等。SAX1中的接口已经不再使用了,这里只会讨论有关SAX2的开发。在本文中提到SAX只是指SAX 2。另外,本文的所有例子都是用java编写,SAX解析器也使用的是JAVA版本。
实现了SAX的解析器有很多,比如Apache的Xerces,Oracle的XML Parser等等。在本文中的例子程序使用的都是Xerces解析器,你可以从 http://xml.apache.org 得到它。让我们下载得到xerces.jar文件然后将其加入到classpath中去,这样我们就已经建立好环境(在xerces.jar中已经包含了SAX接口,所以不必特意再去寻找SAX类库)。
在SAX API中有两个包,org.xml.sax和org.xml.sax.helper。其中org.xml.sax中主要定义了SAX的一些基础接口,如XMLReader、ContentHandler、ErrorHandler、DTDHandler、EntityResolver等。而在org.xml.sax.helper中则是一些方便开发人员使用的帮助类,如缺省实现所有处理器接口的帮助类DefaultHandler、方便开发人员创建XMLReader的XMLReaderFactory类等等。在这两个包中还有一些应用于SAX1的接口,同时还有几个类它们只是为了便于将在SAX1上开发的应用移植到SAX2上,在这篇文章中就不涉及了。下面是我们要关注的接口和类:
Package org.xml.sax |
介绍 |
Interfaces | 接口 |
Attributes | 定义了一个属性列表接口,供访问元素的属性列表而用。 |
ContentHandler | 处理解析文档内容时产生的事件。 |
DTDHandler | 处理解析DTD时的相应事件。 |
EntityResolver | 处理外部实体。 |
ErrorHandler | 处理解析过程中所遇到的文档错误事件。 |
Locator | 为了定位解析中产生的内容事件在文档中的位置而准备的一个定位器接口。 |
XMLFilter | 提供了一个方便应用开发的过滤器接口。 |
XMLReader | 任何兼容SAX2的解析器都要实现这个接口,这个接口让应用程序可以设置或查找features和properties,注册各种事件处理器,以及开始解析文档。 |
Classes | |
InputSource | 为XML实体准备的输入源。 |
Exceptions | |
SAXException | 包装了一般的SAX错误和警告。 |
SAXNotRecognizedException | 为识别不出某些标识而抛出的异常。 |
SAXNotSupportedException | 为不支持某个操作而抛出的异常。 |
SAXParseException | 包装了一个关于XML解析的错误或者警告。 |
Package org.xml.sax.helpers |
帮助类所在的包 |
Classes | 类 |
AttributesImpl | 对Attributes接口的缺省实现 |
NamespaceSupport | 提供名称空间支持。 |
DefaultHandler | 缺省实现了四个处理器接口,方便用户开发,在开发过程中会经常用到。 |
LocatorImpl | 提供了一个对Locator接口的实现 |
XMLFilterImpl | 对过滤器接口的实现,使用过滤器进行应用程序开发时,继承这个类很方便。 |
XMLReaderFactory | 为方便创建不同的XMLReader而提供。也会经常用到。 |
SAX的设计实现与DOM是完全不同的!DOM处理XML文档是基于将XML文档解析成树状模型,放入内存进行处理。而SAX则是采用基于事件驱动的处理模式,它将XML文档转化成一系列的事件,由单独的事件处理器来决定如何处理。为了了解如何使用SAX API处理XML文档,这里先介绍一下SAX所使用的基于事件驱动的处理模式。
这种基于事件的处理模式是一种通用的程序设计模式,被广泛应用于GUI设计。在JAVA的AWT,SWING以及JAVA BEANS中就有它的身影。而SAX的基于事件驱动的处理模式就与上面三者中的非常相像。
基于事件的处理模式主要是围绕着事件源以及事件处理器(或者叫监听器)来工作的。一个可以产生事件的对象被称为事件源,而可以针对事件产生响应的对象就被叫做事件处理器。事件源和事件处理器是通过在事件源中的事件处理器注册方法连接的。这样当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就获得了处理。当然在事件源调用事件处理器中特定方法的时候,会传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据事件信息来决定自己的行为。
在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parse()方法来开始解析XML文档并根据文档内容产生事件。而事件处理器则是org.xml.sax包中的ContentHandler,DTDHandler,ErrorHandler,以及EntityResolver这四个接口。它们分别处理事件源在解析过程中产生的不同种类的事件(其中DTDHandler是为解析文档DTD时而用)。而事件源XMLReader和这四个事件处理器的连接是通过在XMLReader中的相应的事件处理器注册方法set***()来完成的。详细介绍请见下表:
处理器名称 | 所处理事件 | 注册方法 |
org.xml.sax.ContentHandler | 跟文档内容有关的所有事件:
|
XMLReader中的setContentHandler(ContentHandler handler)方法 |
org.xml.sax.ErrorHandler | 处理XML文档解析时产生的错误。如果一个应用程序没有注册一个错误处理器类,会发生不可预料的解析器行为。 | setErrorHandler(ErrorHandler handler) |
org.xml.sax.DTDHandler | 处理对文档DTD进行解析时产生的相应事件 | setDTDHandler(DTDHandler handler) |
org.xml.sax.EntityResolver | 处理外部实体 | setEntityResolver(EntityResolver resolver) |
在这四个处理器接口中,对我们最重要的是ContentHandler接口。下面让我们看一下对其中方法的说明:
方法名称 | 方法说明 |
public void setDocumentLocator (Locator locator) | 设置一个可以定位文档内容事件发生位置的定位器对象 |
public void startDocument () throws SAXException | 用于处理文档解析开始事件 |
public void endDocument () throws SAXException | 用于处理文档解析结束事件 |
public void startPrefixMapping (java.lang.String prefix, java.lang.String uri) throws SAXException | 用于处理前缀映射开始事件,从参数中可以得到前缀名称以及所指向的uri |
public void endPrefixMapping (java.lang.String prefix) throws SAXException | 用于处理前缀映射结束事件,从参数中可以得到前缀名称 |
public void startElement (java.lang.String namespaceURI,java.lang.String localName,java.lang.String qName,Attributes atts) throws SAXException | 处理元素开始事件,从参数中可以获得元素所在名称空间的uri,元素名称,属性列表等信息 |
public void endElement (java.lang.String namespaceURI, java.lang.String localName, java.lang.String qName) throws SAXException | 处理元素结束事件,从参数中可以获得元素所在名称空间的uri,元素名称等信息 |
public void characters (char[] ch, int start, int length) throws SAXException | 处理元素的字符内容,从参数中可以获得内容 |
public void ignorableWhitespace (char[] ch, int start, int length) throws SAXException | 处理元素的可忽略空格 |
public void processingInstruction (java.lang.String target, java.lang.String data) throws SAXException | 处理解析中产生的处理指令事件 |
这里再介绍一下org.xml.sax.XMLReader中的方法,然后让我们看一个具体的例子。XMLReader是所有兼容SAX2的解析器都要实现的接口,由它的方法开始解析文档,并且调用它的注册方法来注册各种事件处理器。请看下表: