SAX解析XML文件采用事件驱动的方式进行,也就是说,SAX是逐行扫描文件,遇到符合条件的设定条件后就会触发特定的事件,回调你写好的事件处理程序。使用SAX的优势在于其解析速度较快,相对于DOM而言占用内存较少。而且SAX在解析文件的过程中得到自己需要的信息后可以随时终止解析,并不一定要等文件全部解析完毕。凡事有利必有弊,其劣势在于SAX采用的是流式处理方式,当遇到某个标签的时候,它并不会记录下以前所遇到的标签,也就是说,在处理某个标签的时候,比如在startElement方法中,所能够得到的信息就是标签的名字和属性,至于标签内部的嵌套结构,上层标签、下层标签以及其兄弟节点的名称等等与其结构相关的信息都是不得而知的。实际上就是把XML文件的结构信息丢掉了,如果需要得到这些信息的话,只能你自己在程序里进行处理了。所以相对DOM而言,SAX处理XML文档没有DOM方便,SAX处理的过程相对DOM而言也比较复杂。
SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器: 解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。 解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。 事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。
备注说明:SAX API中主要有四种处理事件的接口,它们分别是ContentHandler,DTDHandler,EntityResolver和ErrorHandler
这里使用最多的就是ContentHandler,仔细阅读API文档,了解常用方法:startElement、endElement、characters等
1.startElement方法说明
[java]
voidstartElement(Stringuri,StringlocalName,StringqName,Attributesatts)
throwsSAXException
方法说明:
解析器在XML文档中的每个元素的开始调用此方法;对于每个startElement事件都将有相应的endElement事件(即使该元素为空时)。所有元素的内容都将在相应的endElement事件之前顺序地报告。
参数说明:
uri-名称空间URI,如果元素没有名称空间URI,或者未执行名称空间处理,则为空字符串
localName-本地名称(不带前缀),如果未执行名称空间处理,则为空字符串
qName-限定名(带有前缀),如果限定名不可用,则为空字符串(标签名)
atts-连接到元素上的属性。如果没有属性,则它将是空Attributes对象。在startElement返回后,此对象的值是未定义的(标签名属性)
2.endElement方法说明
[java]
voidendElement(Stringuri,StringqName)
throwsSAXException接收元素结束的通知。
SAX解析器会在XML文档中每个元素的末尾调用此方法;对于每个endElement事件都将有相应的startElement事件(即使该元素为空时)。
参数:
uri-名称空间URI,如果元素没有名称空间URI,或者未执行名称空间处理,则为空字符串
localName-本地名称(不带前缀),如果未执行名称空间处理,则为空字符串
qName-限定的XML名称(带前缀),如果限定名不可用,则为空字符串
3.characters方法
[java]
voidcharacters(char[]ch,intstart,intlength)
throwsSAXException
接收字符数据的通知,可以通过newString(ch,start,length)构造器,创建解析出来的字符串文本.
参数:
ch-来自XML文档的字符
start-数组中的开始位置
length-从数组中读取的字符的个数
说明:xml中每个标签的文本内容是在characters方法里处理的。
比如在如下:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPE四大名著[
<!ELEMENT四大名著(西游记,红楼梦)>
<!ATTLIST西游记idID#IMPLIED>
]>
<四大名著>
<西游记id="x001">
<作者>吴承恩</作者>
</西游记>
<红楼梦id="x002">
<作者>曹雪芹</作者>
</红楼梦>
</四大名著>
在<西游记 id="x001"><作者>吴承恩</作者></西游记>里
吴承恩这个文本就是在其中<西游记></西游记>和<作者></作者>是标签(qname)
id="x001"是属性(atts)和值
其它方法请参考api数据
下面我们就具体讲解sax解析的操作.
一.我们通过XMLReaderFactory、XMLReader完成,步骤如下
[java]
1.通过XMLReaderFactory创建XMLReader对象
XMLReaderreader=XMLReaderFactory.createXMLReader();
2.设置事件处理器对象
reader.setContentHandler(newMyDefaultHandler());
3.读取要解析的xml文件
FileReaderfileReader=newFileReader(newFile("srcsaxstartelementweb.xml"));
4.指定解析的xml文件
reader.parse(newInputSource(fileReader));
案例:通过案例对uri、localName、qName和attribute参数有更加深入的了解
1.首先创建要解析的web.xml文件,内容如下
[html]
<?xmlversion="1.0"encoding="UTF-8"?>
<web-appversion="2.5"
xmlns:csdn="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<csdn:display-name></csdn:display-name>
</web-app>
<!--
uri-名称空间URI,如果元素没有任何名称空间URI,或者没有正在执行名称空间处理,则为空字符串。
xmlnamespace-xmlns
localName-本地名称(不带前缀),如果没有正在执行名称空间处理,则为空字符串。
qName-限定的名称(带有前缀),如果限定的名称不可用,则为空字符串。
attributes-附加到元素的属性。如果没有属性,则它将是空的Attributes对象。
-->
2.创建解析测试类及事件处理的内部类代码如下
[java]
packagesax.startelement;
importjava.io.File;
importjava.io.FileReader;
importorg.junit.Test;
importorg.xml.sax.Attributes;
importorg.xml.sax.InputSource;
importorg.xml.sax.SAXException;
importorg.xml.sax.XMLReader;
importorg.xml.sax.helpers.DefaultHandler;
importorg.xml.sax.helpers.XMLReaderFactory;
publicclassDemo3{
@Test
publicvoidtest()throwsException{
//通过XMLReaderFactory创建XMLReader对象
XMLReaderreader=XMLReaderFactory.createXMLReader();
//设置事件处理器对象
reader.setContentHandler(newMyDefaultHandler());
//读取要解析的xml文件
FileReaderfileReader=newFileReader(newFile(
"srcsaxstartelementweb.xml"));
//指定解析的xml文件
reader.parse(newInputSource(fileReader));
}
//自定义的解析类,通过此类中的startElement了解uri,localName,qName,Attributes的含义
classMyDefaultHandlerextendsDefaultHandler{
@Override
publicvoidstartElement(Stringuri,Attributesattributes)throwsSAXException{
super.startElement(uri,attributes);
System.out
.println("--------------startElement开始执行--------------------------");
System.out.println("uri:::"+uri);
System.out.println("localName:::"+localName);
System.out.println("qName:::"+qName);
for(inti=0;i<attributes.getLength();i++){
Stringvalue=attributes.getValue(i);//获取属性的value值
System.out.println(attributes.getQName(i)+"-----"+value);
}
System.out.println("------------------startElement执行完毕---------------------------");
}
}
}
3.程序运行的结果如下:
通过运行结果,希望你对uri,qName有更加深入的了解.
二.我们通过SAXParserFactory、SAXParser完成,步骤如下(建议使用)说明:如果只是使用SAXParserFactory、SAXParser他们完成只需要如下3步骤
1.获取sax解析器的工厂对象 SAXParserFactory factory = SAXParserFactory.newInstance(); 2.通过工厂对象 SAXParser创建解析器对象 SAXParser saxParser = factory.newSAXParser(); 3.通过解析saxParser的parse()方法设定解析的文件和自己定义的事件处理器对象 saxParser.parse(new File("src//sax//sida.xml"),new MyDefaultHandler());
案例:解析出"作者"元素标签中的文本内容
1.需要解析的sida.xml文件
[html]
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPE四大名著[
<!ELEMENT四大名著(西游记,红楼梦)>
<!ATTLIST西游记idID#IMPLIED>
]>
<四大名著>
<西游记id="x001">
<作者>吴承恩</作者>
</西游记>
<红楼梦id="x002">
<作者>曹雪芹</作者>
</红楼梦>
</四大名著>
2.解析测试类和事件处理器类的实现代码
[java]
packagesax;
importjava.io.File;
importjavax.xml.parsers.SAXParser;
importjavax.xml.parsers.SAXParserFactory;
importorg.junit.Test;
importorg.xml.sax.Attributes;
importorg.xml.sax.SAXException;
importorg.xml.sax.helpers.DefaultHandler;
publicclassSaxTest{
@Test
publicvoidtest()throwsException{
//1.获取sax解析器的工厂对象
SAXParserFactoryfactory=SAXParserFactory.newInstance();
//2.通过工厂对象SAXParser创建解析器对象
SAXParsersaxParser=factory.newSAXParser();
//3.通过解析saxParser的parse()方法设定解析的文件和自己定义的事件处理器对象
saxParser.parse(newFile("src//sax//sida.xml"),newMyDefaultHandler());
}
//自己定义的事件处理器
classMyDefaultHandlerextendsDefaultHandler{
//解析标签开始及结束的的标识符
booleanisOk=false;
@Override
publicvoidstartElement(Stringuri,attributes);
//当解析作者元素开始的时候,设置isOK为true
if("作者".equals(qName)){
isOk=true;
}
}
@Override
publicvoidcharacters(char[]ch,intlength)
throwsSAXException{
//TODOAuto-generatedmethodstub
super.characters(ch,length);
//当解析的标识符为true时,打印元素的内容
if(isOk){
System.out.println(newString(ch,length));
}
}
@Override
publicvoidendElement(Stringuri,StringqName)
throwsSAXException{
super.endElement(uri,qName);
//当解析作者元素的结束的时候,设置isOK为false
if("作者".equals(qName)){
isOk=false;
}
}
}
}
3.程序运行结果如下:
原文地址:http://blog.csdn.net/redarmy_chen/article/details/12951649 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|