java xml解析 学习笔记(2)——SAX

来源:互联网 发布:java培训育知同创 编辑:程序博客网 时间:2024/05/16 10:34



     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 blocke.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 stubif(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();}}


运行结果:


0 0