夜光序言:
人总是需要一些仪式的,仪式给人庄重感和宿命感,给人信心。
没有人会理解她这种莫名其妙的执念——想象中那样平等的相识是多么的重要。
正文:
SAX
SAX概述
1 SAX解析原理
首先我们想一下,DOM解析器是不是需要把XML文档遍历一次,然后把每次读取到的数据转换成节点对象(到底哪一种节点对象,这要看解析时遇到了什么东西)保存起来,最后生成一个Document对象返回。也就是说,当你调用了builder.parse(“a.xml”)后,这个方法就会把XML文档中的数据转换成节点对象保存起来,然后生成一个Document对象。这个解析XML文档的过程在parse()方法调用结束后也就结束了。我们的工作是在解析之后,开始对Document对象进行操作。
但是SAX不同,当SAX解析器的parse()方法调用结束后,不会给我们一个Document对象,而是什么都不给。SAX不会把XML数据保存到内存中,如果我们的解析工作是在SAX解析器的parse()方法调用结束后开始,那么就已经晚了~~凉凉献给自己~~
这说明我们必须在SAX解析XML文档的同时完成我们的工作。
SAX解析器在解析XML文档的过程中,读取到XML文档的一个部分后,会调用ContentHandler(内部处理器)中的方法。例如当SAX解析到一个元素的开始标签时,它会调用ContentHandler的startElement()方法;在解析到一个元素的结束标签时会调用ContentHandler的endElement()方法。
ContentHandler是一个接口,我们的工作是编写该接口的实现类,然后创建实现类的对象,在SAX解析器开始解析之前,把我们写的内容处理类对象交给SAX解析器,这样在解析过程中,我们的内容处理中的方法就会被调用了。
2 获取SAX解析器
与DOM相同,你应该通过JAXP获取SAX解析器,而不是直接使用特定厂商的SAX解析器。JAXP查找特定厂商的SAX解析器实现的方式与查找DOM解析器实现的方式完全相同~~
SAXParserFactory factory = SAXParserFactory.newInstance(); javax.xml.parsers.SAXParser parser = factory.newSAXParser(); parser.parse("src/students.xml", new MyContentHandler()); |
上面代码中,MyContentHandler就是我们自己需要编写的ContentHandler的实现类对象。
3 内容处理器
org.xml.sax.ContentHandler中的方法:不用背诵,看看即可,洒脱一笑
- void setDocumentLocator(Locator locator):与定位相关,例如获取行数、实体、标识等信息,我们可以忽略他的存在;
- void startDocument() throws SAXException:文档开始解析之前被调用;
- void endDocument() throws SAXException:文档解析结束之后被调用;
- void startPrefixMapping(String prefix,String uri)throws SAXException:与名称空间相关,忽略;
- void endPrefixMapping(String prefix) throws SAXException:与名称空间相关,忽略;
- void startElement(String uri,String local,String qName,Attributes atts)throws SAXException:开始解析一个元素时被调用,其中uri、local这两个参数与名称空间相关,可以忽略。qName表示当前元素的名称,atts表示当前元素的属性集合;
- void endElement(String uri,String localName,String qName)throws SAXException:一个元素解析结束后会被调用;
- void characters(char[] ch,int start,int length)throws SAXException:解析到文本数据时会被调用,ch表示当前XML文档所有内容对应的字符数组,不只是当前文本元素的内容。start表示当前文本数据在整个XML文档中的开始下载位置,length是当前文本数据的长度;
- void ignorableWhitespace(char[] ch,int start,int length)throws SAXException:解析到空白文本数据时会被调用,可以忽略!
- void processingInstruction(String target,String data)throws SAXException:解析到处理指令时会被调用,可以忽略!
- void skippedEntity(String name)throws SAXException:解析到实体时会被调用,可以忽略!
org.xml.sax.helpers.DefualtHandler对ContentHandler做了空实现,所以我们可以自定义内容处理器时可以继承DefaultHandler类。
SAX应用
- 测试SAX
public class SAXTest { @Test public void testSAX() throws ParserConfigurationException, SAXException, IOException { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse("src/students.xml", new MyContentHandler()); } private static class MyContentHandler extends DefaultHandler { @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 { System.out.println(qName + "元素解析开始"); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.println(qName + "元素解析结束"); } @Override public void characters(char[] ch, int start, int length) throws SAXException { String s = new String(ch, start, length); if(s.trim().isEmpty()) { return; } System.out.println("文本内容:" + s); } @Override public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
} @Override public void processingInstruction(String target, String data) throws SAXException { System.out.println("处理指令"); } } } |
2 使用SAX打印XML文档
public class SAXTest2 { @Test public void testSAX() throws ParserConfigurationException, SAXException, IOException { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse("src/students.xml", new MyContentHandler()); } private static class MyContentHandler extends DefaultHandler { @Override public void startDocument() throws SAXException { System.out.println("<?xml version='1.0' encoding='utf-8'?>"); }
@Override public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { StringBuilder sb = new StringBuilder(); sb.append("<").append(qName); for(int i = 0; i < atts.getLength(); i++) { sb.append(" "); sb.append(atts.getQName(i)); sb.append("="); sb.append("'"); sb.append(atts.getValue(i)); sb.append("'"); } sb.append(">"); System.out.print(sb); }
@Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.print("</" + qName + ">"); }
@Override public void characters(char[] ch, int start, int length) throws SAXException { System.out.print(new String(ch, start, length)); } } } |