在j2ee1.4标准教材里看到一个很有趣的例子,从任意数据结构生成XML解析器产生SAX事件.数据结构可以是文本文件,PDF格式文档等.关键是自己解析这些数据源.另外一个有意思的地方是观察者模式的应用.所以就粗糙的改了一下并完整到可以测试运行.观察者模式简略UML图:
具体实现 被观察者对象ParseXMLSubject类:
package test;
import java.io.*;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.*;
public class ParseXMLSubject implements XMLReader {
ContentHandler handler;
String nsu = "";
Attributes atts = new AttributesImpl();
String rootElement = "addressbook";
String indent = "\n ";
public ParseXMLSubject(){
}
public ContentHandler getContentHandler() {
return handler;
}
public void parse(InputSource input) throws IOException, SAXException {
try {
// Get an efficient reader for the file
java.io.Reader r = input.getCharacterStream();
BufferedReader br = new BufferedReader(r);
// Read the file and display it's contents.
String line = br.readLine();
while (null != (line = br.readLine())) {
if (line.startsWith("email:")) {
break;
}
}
if (handler == null) {
throw new SAXException("No content handler");
}
// Note:
// We're ignoring setDocumentLocator(), as well
handler.startDocument();
handler.startElement(nsu, rootElement, rootElement, atts);
output("email", line);
line = br.readLine();
output("html", line);
line = br.readLine();
output("firstname", line);
line = br.readLine();
output("lastname", line);
line = br.readLine();
output("work", line);
line = br.readLine();
output("home", line);
line = br.readLine();
output("fax", line);
line = br.readLine();
output("pager", line);
line = br.readLine();
output("cell", line);
handler.ignorableWhitespace("\n".toCharArray(), 0, // start index
1 // length
);
handler.endElement(nsu, rootElement, rootElement);
handler.endDocument();
} catch (Exception e) {
e.printStackTrace();
}
}
public void parse(String systemId) throws IOException, SAXException {
}
public DTDHandler getDTDHandler() {
return null;
}
public EntityResolver getEntityResolver() {
return null;
}
public ErrorHandler getErrorHandler() {
return null;
}
public boolean getFeature(String name) throws SAXNotRecognizedException,
SAXNotSupportedException {
return false;
}
public Object getProperty(String name) throws SAXNotRecognizedException,
SAXNotSupportedException {
return null;
}
public void setContentHandler(ContentHandler handler) {
this.handler = handler;
}
public void setDTDHandler(DTDHandler handler) {
}
public void setEntityResolver(EntityResolver resolver) {
}
public void setErrorHandler(ErrorHandler handler) {
}
public void setFeature(String name, boolean value) throws
SAXNotRecognizedException, SAXNotSupportedException {
}
public void setProperty(String name, Object value) throws
SAXNotRecognizedException, SAXNotSupportedException {
}
void output(String name, String line) throws SAXException {
int tmp = name.length();
int startIndex=tmp+1;
int textLength = line.length() - startIndex;
String characters = line.substring(startIndex,line.length()-1);
handler.ignorableWhitespace(indent.toCharArray(), 0, // start index
indent.length());
handler.startElement(nsu, name, name /*"qName"*/, atts);
handler.characters(characters.toCharArray(), startIndex, textLength);
handler.endElement(nsu, name, name);
}
}
具体观察者对象: ConcreateObserver类
package test;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.*;
public class ConcreateObserver extends DefaultHandler {
public ConcreateObserver() {
}
public void startElement(String uri,
String localName,
String qName,
Attributes attributes)
throws SAXException{
System.out.println("startElement: "+localName);
}
public void characters(char[] ch,
int start,
int length)
throws SAXException{
System.out.println("characters: ");
System.out.print(ch);
System.out.println();
}
}
测试类:TestMain
package test;
import java.io.*;
import org.xml.sax.InputSource;
public class TestMain {
public TestMain() {
}
public static void main(String[] args) throws Exception {
TestMain testmain = new TestMain();
FileReader in = new FileReader(new File("d:\\AddressBookReaderLog01.txt"));
ConcreateObserver observer=new ConcreateObserver();
ParseXMLSubject parse = new ParseXMLSubject();
parse.setContentHandler(observer);
parse.parse(new InputSource(in));
}
}
测试文本文档:AddressBookReaderLog01.txt
AddressBookReader01 ../samples/PersonalAddressBook.ldif
nickname: Fred
email: fred@barneys.house
html: TRUE
firstname: Fred
lastname: Flintstone
work: 999-Quarry
home: 999-BedrockLane
fax: 888-Squawk
pager: 777-pager
cell: 555-cell
另外一个也比较也有意思的地方就是具体观察者类从DefaultHandler 继承,该类是缺省适配器模式的应用.
欢迎加入QQ群:30406099