学了DOC解析后我就在想老师为什么还要讲SAX解析呢?原来他们的解析方式是存在差异的,如下表所示:
DOC解析 | SAX解析 |
在内存中创建文档树,不适合处理大型XML文档 | 顺序读入文档并产生相应事件,可以处理大型的XML文档 |
可以随意访问文档的任何部分,没有次数限制 | 只能对文档按顺序解析一遍,不能任意访问 |
可以任意修改文档树,从而修改XML文档 | 只能读取XML文档,而不能修改XML文档 |
易于理解易于开发 | 开发上比较复杂,需要自己来实现事件处理器 |
已经在DOM基础之上创建好了文档树 | 对开发人员而言更灵活,可以用SAX创建自己的XML对象模型 |
详细对比:
如上图所示:
前两步的方式是一样的,只不过是代码不同而已,都是先创建解析器对象工厂,然后创建解析器对象
唯一不同的是第三步DOM是直接DOM树解析(然后再通过子节点解析XML),而SAX必须要通过创建事件处理器来解析,所以SAX解析总的来说比较复杂,事件处理器代码如下:
package cjl.sax; import java.util.ArrayList; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * sax事件处理器 * * @author kowloon * */ public class MyDefaultHandler extends DefaultHandler { ArrayList<Student> slist; String strValue; Student stu; @Override public void startDocument() throws SAXException { slist = new ArrayList<Student>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("stu")) { // 创建学生对象 stu = new Student(); // 获得该节点的属性 String num = attributes.getValue("num"); stu.num = Integer.parseInt(num); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals("name")) { stu.name = strValue; } if (qName.equals("sex")) { stu.sex = strValue; } if (qName.equals("cla")) { stu.cla = strValue; } if (qName.equals("stu")) { slist.add(stu); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { strValue = new String(ch, start, length); System.out.println("解析文本:" + strValue); } @Override public void endDocument() throws SAXException { System.out.println("解析完成-----------------"); // 遍历队列,取出学生对象 for (Student s : slist) { System.out.println(s.toString()); } } }
所以建议小的XML文档还是用DOC解析,因为DOC是解析整篇文档,易于修改
大的文档还是用SAX解析,因为SAX是读一点扔一点,易于读取,再说大的XML文档
DOC也不好解析占内存,解析速度极慢。切记大的文档不要用DOC去解析。