`
步行者
  • 浏览: 167409 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

SAX解析XML 之 坏毛豆过滤器

    博客分类:
  • XML
阅读更多

在平时的学习中,一些生动简洁的示例总是能让我们更快更好地接受。

下面介绍一个关于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() 方法,这个方法对事件进行处理。


2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics