SAX处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。一般来说,SAX还比它的替代者DOM快许多。
选择DOM还是选择SAX? 对于需要自己编写代码来处理XML文档的开发人员来说, 选择DOM还是SAX解析模型是一个非常重要的设计决策。 DOM采用建立树形结构的方式访问XML文档,而SAX采用的事件模型。
DOM解析器把XML文档转化为一个包含其内容的树,并可以对树进行遍历。用DOM解析模型的优点是编程容易,开发人员只需要调用建树的指令,然后利用navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然而由于使用DOM解析器的时候需要处理整个XML文档,所以对性能和内存的要求比较高,尤其是遇到很大的XML文件的时候。由于它的遍历能力,DOM解析器常用于XML文档需要频繁的改变的服务中。
SAX解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag.特别是当开发人员只需要处理文档中所包含的部分数据时,SAX这种扩展能力得到了更好的体现。但用SAX解析器的时候编码工作会比较困难,而且很难同时访问同一个文档中的多处不同数据.
下面给出两个例子来简单的介绍下sax方式解析xml文件的方法:
xml文件:first.xml,放于src目录下
<?xml version="1.0" encoding="UTF-8"?> <xml-body> <result> <value> <no> 鲁B1234 </no> <addr> 山东省青岛市 </addr> </value> <value> <no> 鲁A1234 </no> <addr> 山东省济南市 </addr> </value> </result> </xml-body>
例一:(使用boolean标记解析)
package Test; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class MyXmlReader_sax extends DefaultHandler { boolean isOkTag; public static void main(String args[]) { long lasting = System.currentTimeMillis(); try { SAXParserFactory sf = SAXParserFactory.newInstance(); //1、创建SAXParserFactory 工厂 SAXParser sp = sf.newSAXParser(); //2、创建SAXParser MyXmlReader_sax reader = new MyXmlReader_sax(); sp.parse(new InputSource("src/first.xml"), reader); //3、解析XML文档,并回调处理器的相应事件 } catch (Exception e) { e.printStackTrace(); } System.out.println("运行时间:" + (System.currentTimeMillis() - lasting) + "毫秒"); } /* * 接收元素开始的通知。 * 参数意义如下: * uri :元素的命名空间 * localName :元素的本地名称(不带前缀) * qName :元素的限定名(带前缀) * atts :元素的属性集合 */ public void startElement(String uri,String localName,String qName,Attributes attrs) { //5、开始标记 //tags.push(qName); if(qName.equals("value")) { System.out.println("=============value start============"); } if(qName.equals("no")) { isOkTag = true; System.out.print("车牌号:"); }else if(qName.equals("addr")){ isOkTag = true; System.out.println("地址:"); } } /* * 接收字符数据的通知。 */ public void characters(char ch[], int start, int length) throws SAXException { // if(isOkTag) { System.out.println(new String(ch, start, length)); } } /* * 接收文档的结尾的通知。 * 参数意义如下: * uri :元素的命名空间 * localName :元素的本地名称(不带前缀) * qName :元素的限定名(带前缀) * */ public void endElement(String uri, String localName, String qName) throws SAXException { isOkTag = false; if(qName.equals("value")) { System.out.println("=============value end============"); } } }
运行结果:
例二:(使用栈解析)
package Test; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class MyXmlReader_sax2 extends DefaultHandler { //获取栈实例 java.util.Stack tags = new java.util.Stack(); public MyXmlReader_sax2() { super(); } //解析xml文件 public void getXML() { SAXParserFactory factory = SAXParserFactory.newInstance(); try { SAXParser parser = factory.newSAXParser(); MyXmlReader_sax2 parX = new MyXmlReader_sax2(); parser.parse("src/first.xml", parX); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } // 重写方法characters(...); public void characters(char ch[], int start, int length) throws SAXException { //获取栈顶元素 String tag = (String) tags.peek(); // 比较栈顶元素 String text = new String(ch, start, length); if(tag.equals("value")){ System.out.println("<value>"); tags.pop(); //出栈 } if (tag.equals("no")) { System.out.println(" <no>" + text); tags.pop(); } else if (tag.equals("addr")) { System.out.println(" <addr>" + text); tags.pop(); } } // 重写方法startElement(...); public void startElement(String uri, String localName, String qName, Attributes attrs) { tags.push(qName);// 把项压入栈顶(入栈) // System.out.println(qName); } //重写方法endElement(...); public void endElement(String uri, String localName, String qName) throws SAXException { // TODO Auto-generated method stub if(qName.equals("value")){ System.out.println("</value>"); }else if(qName.equals("no")){ System.out.println("</no>"); }else if(qName.equals("addr")){ System.out.println("</addr>"); } } public static void main(String[] args) { new MyXmlReader_sax2().getXML(); } }
运行结果: