在平时的学习中,一些生动简洁的示例总是能让我们更快更好地接受。
下面介绍一个关于SAX 过滤器的应用示例,希望这个示例也对大家有
所帮助
现在厨师要炒毛豆,但是毛豆中有的坏了,我们不能都放在锅里炒吧 ?
当然不能,厨师决定用坏毛豆过滤器把坏毛豆过滤掉,然后再加工毛豆。
先看一下厨房里面的材料吧 :一共有五个毛豆(其中毛豆B,和毛豆D是坏的).
GreenSoyBean.xml
<?xml version="1.0" encoding="GB2312"?>
<材料>
<毛豆 坏的 = 'no'>
A
</毛豆>
<毛豆 坏的 = 'yes'>
B
</毛豆>
<毛豆 坏的 = 'no'>
C
</毛豆>
<毛豆 坏的 = 'no'>
D
</毛豆>
<毛豆 坏的 = 'yes'>
E
</毛豆>
</材料>
坏毛豆过滤器(BadGreenSoyBeanFilter):
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLFilterImpl;
import org.xml.sax.helpers.XMLReaderFactory;
/*
* 坏毛豆过滤器,过滤掉所有坏毛豆
*/
public class BadGreenSoyBeanFilter extends XMLFilterImpl {
// 现在查看的毛豆是不是坏毛豆
private boolean currentGreenSoyBeanisBad = false;
public BadGreenSoyBeanFilter() throws SAXException {
super(XMLReaderFactory.createXMLReader());
}
public BadGreenSoyBeanFilter(XMLReader xmlReader) {
super(xmlReader);
}
// 接收文档开始的通知。
@Override
public void startDocument() throws SAXException {
System.out.println("毛豆过滤器 : 准备开始过滤毛豆 。。");
super.startDocument();
}
// 接收文档开始的通知。
@Override
public void endDocument() throws SAXException {
System.out.println("毛豆过滤器 : 毛豆过滤完毕 ");
super.endDocument();
}
// 接收元素的开始的通知。
@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
if (localName.equals("毛豆") && atts.getValue("坏的").equals("yes")){
// 现在查看的毛豆是坏毛豆
this.currentGreenSoyBeanisBad = true;
} else {
// 现在查看的毛豆不是坏毛豆,那就交给厨师了 !
super.startElement(uri, localName, qName, atts);
}
}
// 接收元素的结尾的通知。
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (localName.equals("毛豆") && currentGreenSoyBeanisBad) {
// 坏毛豆被过滤掉了,准备查看下一个毛豆了
this.currentGreenSoyBeanisBad = false;
} else {
super.endElement(uri, localName, qName);
}
}
// 接收字符数据的通知。
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
StringBuilder stringBuilder = new StringBuilder();
for (int i = start; i < start + length; i++) {
switch (ch[i]) {
case '\r':
break;
case '\t':
break;
case '\n':
break;
default:
stringBuilder.append(ch[i]);
}
}
// 如果现在查看的毛豆是坏毛豆,就把它扔掉
// 否则交给厨师 !
if (this.currentGreenSoyBeanisBad) {
System.out.println("毛豆过滤器 : 扔掉坏毛豆" + stringBuilder.toString());
} else {
super.characters(ch, start, length);
}
}
}
厨师(Chef):
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class Chef extends DefaultHandler {
//现在查看的东西是不是毛豆
private boolean isGreenSoyBean = false;
// 接收文档开始的通知。
@Override
public void startDocument() throws SAXException {
System.out.println("厨师 : 准备开始加工毛豆 。。");
}
// 接收文档开始的通知。
@Override
public void endDocument() throws SAXException {
System.out.println("厨师 : 毛豆加工完毕 ");
}
// 接收元素开始的通知。
@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
if(localName.equals("毛豆")){
this.isGreenSoyBean = true;
}
}
// 接收元素的结尾的通知。
@Override
public void endElement(String uri,String localName,String qName)
throws SAXException {
if(localName.equals("毛豆")){
this.isGreenSoyBean = false;
}
}
// 接收字符数据的通知。
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// 现在查看的毛豆是坏毛豆,把它交给厨师 !
if(isGreenSoyBean){
StringBuilder stringBuilder = new StringBuilder();
for(int i = start ; i < start + length ; i++){
switch(ch[i]){
case '\r' : break;
case '\t' : break;
case '\n' : break;
default :stringBuilder.append(ch[i]);
}
}
System.out.println("厨师 : 加工毛豆"+stringBuilder.toString());
}
}
}
开始炒毛豆了。。(先过滤掉所有坏毛豆,再加工剩下的毛豆)
// 创建一个毛豆过滤器
XMLFilter badGreenSoyBeanFilter = new BadGreenSoyBeanFilter();
// 创建一个 毛豆处理器
XMLFilterImpl GreenSoyBeanHandler = new XMLFilterImpl(){
{
// 创建一个加工毛豆的厨师
DefaultHandler chef = new Chef();
// 设置毛豆处理器的 材料加工者 为厨师
this.setContentHandler(chef);
}
};
// 指定工作顺序 :先筛选毛豆,再加工毛豆
GreenSoyBeanHandler.setParent(badGreenSoyBeanFilter);
// 开始筛选和加工毛豆 !
GreenSoyBeanHandler.parse(new InputSource(new FileInputStream("GreenSoyBean.xml")));
下面看看过滤毛豆和加工毛豆的过程吧(控制台输出)
毛豆过滤器 : 准备开始过滤毛豆 。。
厨师 : 准备开始加工毛豆 。。
厨师 : 加工毛豆A
毛豆过滤器 : 扔掉坏毛豆B
厨师 : 加工毛豆C
厨师 : 加工毛豆D
毛豆过滤器 : 扔掉坏毛豆E
毛豆过滤器 : 毛豆过滤完毕
厨师 : 毛豆加工完毕
从输出中我们可以看到,解析XML时产生的事件先由 BadGreenSoyBeanFilter 处理,
BadGreenSoyBeanFilter可以对事件进行过滤,它可以决定是否要将一个事件传给下一个事件处理者(即GreenSoyBeanHandler)。GreenSoyBeanHandler再将接收到的时间进行处理。
看似每个事件最多只被处理过两次,其实不是(只是一些处理过程什么都没做,只是把事件再传了下去)
我们就以其中一个事件(startElement)来说明一下,当解析XML产生 startElement 事件时:
(1)它首先会把事件传给 badGreenSoyBeanFilter 的 starElement() 方法,
这个方法对事件进行过滤,
(2)然后再传给 GreenSoyBeanHandler 的 starElement() 方法
而这个方法什么都不做,
(2)最后再给 GreenSoyBeanHandler.getContentHandler() 的 starElement() 方法
即 Chef 的 starElement() 方法,这个方法对事件进行处理。
本文通过一个生动的例子——使用SAX过滤器过滤坏毛豆并由厨师加工好的毛豆,介绍了SAX过滤器的工作原理及其如何与处理器配合使用。
1077

被折叠的 条评论
为什么被折叠?



