stax 介绍

目前,主流的XML解析API有SAX和DOM。SAX是基于事件的XML解析API,每次解析时都会从头到尾读取整个文档,然后在解析过程中触发一些事件并调用相应的回调方法进行处理。而DOM是基于树状模型的XML解析API,只需一次读取文档并解析生成文档的树状模型存放在内存里,以后可以对树模型中的节点进行随机访问。

      SAX对于只要解析一次的XML文档显得很高效,且节省存储空间,但是如果要对文档的节点进行随机访问时,则会很低效,需要每次对文档进行一次解析。 DOM对文档的节点进行随机访问很方便,但是因为需要把整个文档的树状模型存放在内存里,所以对内存要求较高,不适用于存储受限的场合(如嵌入式设备)。另外,SAX是一种push式的XML解析API,它从XML文档中读到数据,然后将这些数据push给用户程序。

      除了SAX和DOM以外,最近又涌现出了一种新的XML解析API,StAX(the Streaming API for XML),它是一种新一代的pull式的XML解析API。StAX与SAX类似的地方是它也是从头到尾读取整个文档并进行解析,但是不同的是StAX读取文档的方式是每次只读取一部分,等用户程序要求时才读取下一部分,文档的读取过程是用户程序可以控制的,所以是一种pull的方式。

      下面是一段例程,通过例程我们就可以更好地理解StAX的工作方式了。这段例程用于解析一段XHTML并把其中的各级标题(h1、h2、h3……)的内容给解析出来。

import javax.xml.stream.*;
import java.net.URL;
import java.io.*;

public class XHTMLOutliner {

  public static void main(String[] args) {

    if (args.length == 0) {
      System.err.println("Usage: java XHTMLOutliner url" );
      return;
    }
    String input = args[0];

    try {
      URL u = new URL(input);
      InputStream in = u.openStream();
      XMLInputFactory factory = XMLInputFactory.newInstance();
      XMLStreamReader parser = factory.createXMLStreamReader(in);
      
      int inHeader = 0;
      for (int event = parser.next();
       event != XMLStreamConstants.END_DOCUMENT;
       event = parser.next()) {
        switch (event) {
          case XMLStreamConstants.START_ELEMENT:
            if (isHeader(parser.getLocalName())) {
              inHeader++;
            }
            break;
          case XMLStreamConstants.END_ELEMENT:
            if (isHeader(parser.getLocalName())) {
              inHeader--;
              if (inHeader == 0) System.out.println();
            }
            break;
          case XMLStreamConstants.CHARACTERS:
            if (inHeader > 0)  System.out.print(parser.getText());
            break;
          case XMLStreamConstants.CDATA:
            if (inHeader > 0)  System.out.print(parser.getText());
            break;
        } // end switch
      } // end while
      parser.close();
    }
    catch (XMLStreamException ex) {
       System.out.println(ex);
    }
    catch (IOException ex) {
      System.out.println("IOException while parsing " + input);
    }

  }

   /**
    * Determine if this is an XHTML heading element or not
    * @param  name tag name
    * @return boolean true if this is h1, h2, h3, h4, h5, or h6;
    *                 false otherwise
    */
    private static boolean isHeader(String name) {
      if (name.equals("h1")) return true;
      if (name.equals("h2")) return true;
      if (name.equals("h3")) return true;
      if (name.equals("h4")) return true;
      if (name.equals("h5")) return true;
      if (name.equals("h6")) return true;
      return false;
    }

}

      由此可见,StAX的工作方式和iterator模式很相似,用户程序主动调用next方法读入一段数据,用户程序判断这段数据是属于哪种类型(START_DOCUMENT、END_DOCUMENT、START_ELEMENT、END_ELEMENT、CDATA和CHARACTERS 等)的,然后相应的做出处理。

      如果用户希望检查XML文档的合法性,可以设置工厂的javax.xml.stream.isValidating属性为真,这样得到的XMLStreamReader 对象在读取XML文档时就会验证其合法性。
            factory.setProperty("javax.xml.stream.isValidating", Boolean.TRUE);

      但是,StAX解析发现文档非法时并不会抛出异常,而是通过一个XMLReporter接口来报告这种错误。下面这段代码就是常见了一个匿名类的实例,并将其注册作为StAX报告错误的接口。

factory.setXMLReporter(new XMLReporter() {
  public void report(String message, String errorType,
    Object relatedInformation, Location location) {
      System.err.println("Problem in " + location.getLocationURI());
      System.err.println("at line " + location.getLineNumber()
        + ", column " + location.getColumnNumber());
      System.err.println(message);
  }
});

      StAX提供了一个特殊的方法require来测试当前文档读取的位置是否满足要求。例如下面这段代码就是要求当前文档读取的位置是一个head开始标记。这个方法很像assert,如果满足条件程序就能继续下去,否则,抛出XMLStreamException,程序将无法继续下去。
      parser.require(XMLStreamConstants.START_ELEMENT,
               "http://www.w3.org/1999/xhtml",
               "head");

      StAX还可以生成并输出XML文档。下面是一个例程向data.xml文件中输出一个简单的XML文档。

OutputStream out = new FileOutputStream("data.xml");
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = factory.createXMLStreamWriter(out);

writer.writeStartDocument("ISO-8859-1", "1.0");
writer.writeStartElement("greeting");
writer.writeAttribute("id", "g1");
writer.writeCharacters("Hello StAX");
writer.writeEndDocument();

writer.flush();
writer.close();
out.close();
stax源码下载
http://stax.codehaus.org/Download

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值