StAX杂谈

对于XML的解析,不外乎两种机制:
- 基于Tree的API,需要一次性读入整个文档到内存中,但是读入之后任何节点都可以随时访问。例如:DOM,JDOM,DOM4j
- 基于Event的API,顺序解析并监听XML Tree的任何变动,实时的响应,内存开销较小。例如:SAX,XNI

Java API for XML Processing (JAXP),就提供了两种方法来处理 XML:文档对象模型(DOM)方法是用标准的对象模型表示 XML 文档;Simple API for XML (SAX) 方法使用应用程序提供的事件处理程序来处理 XML。
StAX 与其他方法的区别就在于应用程序能够把 XML 作为一个事件流来处理。将 XML 作为一组事件来处理的想法并不新颖(事实上 SAX 已经提出来了),但不同之处在于 StAX 允许应用程序代码把这些事件逐个拉出来,而不用提供在解析器方便时从解析器中接收事件的处理程序。

StAX被设计为这两者的一个折中。在StAX中,程序的切入点是表示XML文档中一个位置的光标。应用程序在需要时向前移动光标,从解析器拉出信息。与基于事件的API(如SAX)将“数据推送”给应用程序不同的是,SAX需要应用程序维持时间状态,以保持文档内的位置信息。
StAX有两种API,一种是cursor-based,一种是iterator-based,这两种API的官方文档:http://java.sun.com/webservices/docs/1.6/tutorial/doc/SJSXP3.html#wp102139
- cursor-based的 API 允许应用程序把 XML 作为一个标记(或事件)流来处理;应用程序可以检查解析器的状态,获得解析的上一个标记的信息,然后再处理下一个标记,依此类推。这是一种低层 API,尽管效率高,但是没有提供底层 XML 结构的抽象。
- iterator-based的 API 允许应用程序把 XML 作为一系列事件对象来处理,每个对象和应用程序交换 XML 结构的一部分。应用程序只需要确定解析事件的类型,将其转换成对应的具体类型,然后利用其方法获得属于该事件的信息。

SAX和StAX的另外一点区别是: SAX只能读xml文件. StAX不但能读xml文件,而且还能写xml文件. StAX 定义了一种序列化器 API,Java 标准 XML 处理支持中一直缺少的一种特性。和解析一样,也包含两种风格的流式 API:处理标记的底层 XMLStreamWriter 和处理事件对象的高层 XMLEventWriter。XMLStreamWriter 提供了写入单个 XML 记号(比如开始和关闭标记或者元素属性)的方法,不检查这些标记是否格式良好。另一方面,XMLEventWriter 允许应用程序向输出中添加完整的 XML 事件。第 3 部分将详细讨论 StAX 序列化器 API。

StAX最好的开源实现是Woodstox(http://woodstox.codehaus.org/),它完整地支持StAX API。Resin3.1也内置了StAX的实现,但是并没有支持所以的StAX API。以下是一个简单的使用例子:
public interface XMLStreamReader { 
  public int next() throws XMLStreamException; 
  public boolean hasNext() throws XMLStreamException; 
  public String getText(); 
  public String getLocalName(); 
  public String getNamespaceURI(); 
  // ...
}

public interface XMLStreamWriter { 
  public void writeStartElement(String localName) throws XMLStreamException;
  public void writeEndElement() throws XMLStreamException; 
  public void writeCharacters(String text) throws XMLStreamException; 
  // ...
}

XMLInputFactory f = XMLInputFactory.newInstance(); 
XMLStreamReader r = f.createXMLStreamReader(... ); 

//or if want to use iterator-based API
//XMLEventReader r = f.createXMLEventReader (...);
while (r.hasNext()) { 
    r.next(); 
}

StAX 所采用的基于拉的方法和其他方法相比有一些突出的优点。首先,不管使用哪种 API 风格,都是应用程序调用读取器(解析器)而不是相反。通过保留解析过程的控制权,可以简化调用代码来准确地处理它预期的内容。或者发生意外时停止解析。此外,由于该方法不基于处理程序回调,应用程序不需要像使用 SAX 那样模拟解析器的状态。

StAX 仍然保留了 SAX 相对于 DOM 的优点。通过把重心从结果对象模型转移到解析流本身,从理论上说应用程序能够处理无限的 XML 流,因为事件固有的临时性,不会在内存中累积起来。对于那些使用 XML 作为消息传递协议而非表示文档内容的那些应用程序尤其重要,比如 Web 服务或即时消息应用程序。比方说,如果只是将其转换成特定于应用程序的对象模型然后就将其丢弃,那么为 Web 服务路由器 servlet 提供一个 DOM 就没有多少用处。使用 StAX 直接转化成应用程序模型效率更高。对于 Extensible Messaging and Presence Protocol(XMPP)客户机,根本不能使用 DOM,因为 XMPP 客户机/服务器流是随着用户输入的消息实时生成。等待流的关闭标签(以便最终建立 DOM)就意味着等待整个会话结束。通过把 XML 作为一系列的事件来处理,应用程序能够以最合适的方式响应每个事件(比如显示收到的即时消息等等)。

由于其双向性,StAX 也支持链式处理,特别是在事件层上。接收事件(无论什么来源)的能力被封装在 XMLEventConsumer(XMLEventWriter 的扩展)接口中。因此,可以模块化地编写应用程序从 XMLEventReader(也是一个普通的迭代器,可以按迭代器处理)读取和处理 XML 事件、然后传递给事件消费者(如果需要可以进一步扩展处理链)。在第 2 部分将看到,也可使用应用程序提供的筛选器(实现了 EventFilter 接口的类)来定制 XMLEventReader 或者使用 EventReaderDelegate 修饰已有的 XMLEventReader。

总而言之,和 DOM 以及 SAX 相比,StAX 使应用程序更贴近底层的 XML。使用 StAX,应用程序不仅可以建立需要的对象模型(而不需要处理标准 DOM),而且可以随时这样做,而不必等到解析器回调。

原文链接:http://www.ibm.com/developerworks/cn/xml/x-stax1.html

你可能感兴趣的:(xml,String,api,文档,interface,XMPP)