﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-&lt;b&gt;BeanSoft's Java Blog&lt;/b&gt;-随笔分类-Java EE</title><link>http://www.blogjava.net/beansoft/category/17555.html</link><description>&lt;a href="http://www.beansoft.biz/?p=132"&gt;《MyEclipse 6 Java 开发中文教程》完整版书籍代码及配套超高清讲解视频免费下载&lt;/a&gt;</description><language>zh-cn</language><lastBuildDate>Sat, 12 Feb 2011 12:36:48 GMT</lastBuildDate><pubDate>Sat, 12 Feb 2011 12:36:48 GMT</pubDate><ttl>60</ttl><item><title>使用 StAX 解析 XML，第 1 部分: Streaming API for XML (StAX) 简介[转]</title><link>http://www.blogjava.net/beansoft/archive/2010/09/09/331566.html</link><dc:creator>BeanSoft</dc:creator><author>BeanSoft</author><pubDate>Thu, 09 Sep 2010 11:23:00 GMT</pubDate><guid>http://www.blogjava.net/beansoft/archive/2010/09/09/331566.html</guid><description><![CDATA[<p>来源: <a href="http://www.ibm.com/developerworks/cn/xml/x-stax1.html">http://www.ibm.com/developerworks/cn/xml/x-stax1.html</a></p> <h3>使用 StAX 解析 XML，第 1 部分: Streaming API for XML (StAX) 简介</h3> <p><em>探究其基于指针的 API，它把 XML 作为标记（或事件）流拉出</em></p><span class="Apple-style-span" style="word-spacing: 0px; font: medium 微软雅黑; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span class="Apple-style-span" style="font-size: 12px; line-height: 19px; font-family: verdana, nsimsun, sans-serif"> <p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">级别： 中级</p> <p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/cn/xml/x-stax1.html#author">Peter Nehrer</a><span class="Apple-converted-space">&nbsp;</span>(<a style="color: rgb(92,129,167)" href="mailto:pnehrer@ecliptical.ca?subject=Streaming%20API%20for%20XML%20(StAX)%20%E7%AE%80%E4%BB%8B&amp;cc=dwxed@us.ibm.com">pnehrer@ecliptical.ca</a>), 自由撰稿人, 独立咨询顾问<br></p> <p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">2007 年 3 月 02 日</p> <blockquote>Streaming API for XML (StAX) 是用 Java™ 语言处理 XML 的最新标准。作为一种面向流的方法，无论从性能还是可用性上都优于其他方法，如 DOM 和 SAX。本系列分为 3 部分，本文是第 1 部分，简要介绍了 StAX 及其处理 XML 的基于指针的 API。</blockquote> <p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><a name="N1004C"><span class="atitle" style="font-weight: bold; font-size: 18px; font-family: arial, sans-serif">StAX 概述</span></a></p> <p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">从一开始，Java API for XML Processing (JAXP) 就提供了两种方法来处理 XML：文档对象模型（DOM）方法是用标准的对象模型表示 XML 文档；Simple API for XML (SAX) 方法使用应用程序提供的事件处理程序来处理 XML。JSR-173 提出了一种面向流的新方法：Streaming API for XML (StAX)。其最终版本于 2004 年 3 月发布，并成为了 JAXP 1.4（将包含在即将发布的 Java 6 中）的一部分。</p> <p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">如其名称所暗示的那样，StAX 把重点放在<i>流</i>上。实际上，StAX 与其他方法的区别就在于应用程序能够把 XML 作为一个事件流来处理。将 XML 作为一组事件来处理的想法并不新颖（事实上 SAX 已经提出来了），但不同之处在于 StAX 允许应用程序代码把这些事件逐个拉出来，而不用提供在解析器方便时从解析器中接收事件的处理程序。</p> <p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">StAX 实际上包括两套处理 XML 的 API，分别提供了不同程度的抽象。基于指针的 API 允许应用程序把 XML 作为一个标记（或事件）流来处理；应用程序可以检查解析器的状态，获得解析的上一个标记的信息，然后再处理下一个标记，依此类推。这是一种低层 API，尽管效率高，但是没有提供底层 XML 结构的抽象。较为高级的基于迭代器的 API 允许应用程序把 XML 作为一系列事件对象来处理，每个对象和应用程序交换 XML 结构的一部分。应用程序只需要确定解析事件的类型，将其转换成对应的具体类型，然后利用其方法获得属于该事件的信息。</p><br> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td style="line-height: 19px"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0"></td></tr></tbody></table> <table class="no-print" cellspacing="0" cellpadding="0" align="right"> <tbody> <tr align="right"> <td style="line-height: 19px"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td style="line-height: 19px" valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0"><br></td> <td style="line-height: 19px" valign="top" align="right"><a class="fbox" style="font-size: 12px; color: rgb(92,129,167); line-height: 13px; font-family: verdana, nsimsun, arial, sans-serif; text-decoration: none" href="http://www.ibm.com/developerworks/cn/xml/x-stax1.html#main"><b>回页首</b></a></td></tr></tbody></table></td></tr></tbody></table><br><br> <p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><a name="N1005E"><span class="atitle" style="font-weight: bold; font-size: 18px; font-family: arial, sans-serif">基本原理</span></a></p> <p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">为了使用这两类 API，应用程序首先必须获得一个具体的<span class="Apple-converted-space">&nbsp;</span><code>XMLInputFactory</code>。根据传统的 JAXP 风格，要用到抽象工厂模式；<code>XMLInputFactory</code><span class="Apple-converted-space">&nbsp;</span>类提供了静态的<span class="Apple-converted-space">&nbsp;</span><code>newInstance</code><span class="Apple-converted-space">&nbsp;</span>方法，它负责定位和实例化具体的工厂。配置该实例可设置定制或者预先定义好的属性（其名称在类 XMLInputFactory 中定义）。最后，为了使用基于指针的 API，应用程序还要通过调用某个<span class="Apple-converted-space">&nbsp;</span><code>createXMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>方法获得一个<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamReader</code>。如果要使用基于事件迭代器的 API，应用程序就要调用<span class="Apple-converted-space">&nbsp;</span><code>createXMLEventReader</code><span class="Apple-converted-space">&nbsp;</span>方法获得一个<span class="Apple-converted-space">&nbsp;</span><code>XMLEventReader</code>（如清单 1 所示）。</p><br><a name="N10087"><b>清单 1. 获取和配置默认的<span class="Apple-converted-space">&nbsp;</span><code>XMLInputFactory</code><span class="Apple-converted-space">&nbsp;</span></b></a><br> <table cellspacing="0" cellpadding="0" width="100" border="0"> <tbody> <tr> <td class="code-outline" style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 5px; padding-bottom: 5px; border-left: rgb(204,204,204) 1px solid; line-height: 19px; padding-top: 5px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><pre class="displaycode" style="margin-top: 0px; font-size: 11px; margin-bottom: 0px; font-family: 'Andale Mono', 'Lucida Console', monaco, fixed, monospace">                
// get the default factory instance
XMLInputFactory factory = XMLInputFactory.newInstance();
// configure it to create readers that coalesce adjacent character sections
factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
XMLStreamReader r = factory.createXMLStreamReader(input);
// ...
</pre></td></tr></tbody></table><br>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>XMLEventReader</code><span class="Apple-converted-space">&nbsp;</span>都允许应用程序迭代底层的 XML 流。两种方法的差别在于如何公开解析后的 XML InfoSet 信息片段。<code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>就像一个指针，指在刚刚解析过的 XML 标记的后面，并提供了方法获得更多关于该标记的信息。这种方法节约内存，因为不用创建新的对象。但是，业务应用程序开发人员可能会发现<span class="Apple-converted-space">&nbsp;</span><code>XMLEventReader</code><span class="Apple-converted-space">&nbsp;</span>更直观一些，因为它实际上就是一个标准的 Java 迭代器，将 XML 变成了事件对象流。每个事件对象都封装了它所表示的特定 XML 结构固有的信息。本系列的第二部分将详细讨论这种基于事件迭代器的 API。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">使用哪种风格的 API 取决于具体情况。和基于指针的 API 相比，基于事件迭代器的 API 具有更多的面向对象特征。因此更便于应用于模块化的体系结构，因为当前的解析器状态反映在事件对象中，应用程序组件在处理事件的时候不需要访问解析器/读取器。此外，还可以使用<code>XMLInputFactory</code><span class="Apple-converted-space">&nbsp;</span>的<span class="Apple-converted-space">&nbsp;</span><code>createXMLEventReader(XMLStreamReader)</code><span class="Apple-converted-space">&nbsp;</span>方法从<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>创建<span class="Apple-converted-space">&nbsp;</span><code>XMLEventReader</code>。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">StAX 还定义了一种序列化器 API，Java 标准 XML 处理支持中一直缺少的一种特性。和解析一样，也包含两种风格的流式 API：处理标记的底层<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamWriter</code><span class="Apple-converted-space">&nbsp;</span>和处理事件对象的高层<span class="Apple-converted-space">&nbsp;</span><code>XMLEventWriter</code>。<code>XMLStreamWriter</code><span class="Apple-converted-space">&nbsp;</span>提供了写入单个 XML 记号（比如开始和关闭标记或者元素属性）的方法，不检查这些标记是否格式良好。另一方面，<code>XMLEventWriter</code><span class="Apple-converted-space">&nbsp;</span>允许应用程序向输出中添加完整的 XML 事件。第 3 部分将详细讨论 StAX 序列化器 API。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><a name="N100CA"><span class="smalltitle" style="font-weight: bold; font-size: 15px; font-family: arial, nsimsun, sans-serif">为什么使用 StAX？</span></a></p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">开始学习一种新的处理 XML 的 API 之前，可能要问是否值得这样做。事实上，StAX 所采用的基于拉的方法和其他方法相比有一些突出的优点。首先，不管使用哪种 API 风格，都是应用程序调用读取器（解析器）而不是相反。通过保留解析过程的控制权，可以简化调用代码来准确地处理它预期的内容。或者发生意外时停止解析。此外，由于该方法不基于处理程序回调，应用程序不需要像使用 SAX 那样模拟解析器的状态。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">StAX 仍然保留了 SAX 相对于 DOM 的优点。通过把重心从结果对象模型转移到解析流本身，从理论上说应用程序能够处理无限的 XML 流，因为事件固有的临时性，不会在内存中累积起来。对于那些使用 XML 作为消息传递协议而非表示文档内容的那些应用程序尤其重要，比如 Web 服务或即时消息应用程序。比方说，如果只是将其转换成特定于应用程序的对象模型然后就将其丢弃，那么为 Web 服务路由器 servlet 提供一个 DOM 就没有多少用处。使用 StAX 直接转化成应用程序模型效率更高。对于 Extensible Messaging and Presence Protocol（XMPP）客户机，根本不能使用 DOM，因为 XMPP 客户机/服务器流是随着用户输入的消息实时生成。等待流的关闭标签（以便最终建立 DOM）就意味着等待整个会话结束。通过把 XML 作为一系列的事件来处理，应用程序能够以最合适的方式响应每个事件（比如显示收到的即时消息等等）。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">由于其双向性，StAX 也支持链式处理，特别是在事件层上。接收事件（无论什么来源）的能力被封装在 XMLEventConsumer（XMLEventWriter 的扩展）接口中。因此，可以模块化地编写应用程序从 XMLEventReader（也是一个普通的迭代器，可以按迭代器处理）读取和处理 XML 事件、然后传递给事件消费者（如果需要可以进一步扩展处理链）。在第 2 部分将看到，也可使用应用程序提供的筛选器（实现了 EventFilter 接口的类）来定制 XMLEventReader 或者使用 EventReaderDelegate 修饰已有的 XMLEventReader。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">总而言之，和 DOM 以及 SAX 相比，StAX 使应用程序更贴近底层的 XML。使用 StAX，应用程序不仅可以建立需要的对象模型（而不需要处理标准 DOM），而且可以随时这样做，而不必等到解析器回调。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">下一节将深入讨论基于指针的 API 以及如何有效地使用它处理 XML 流。</p><br>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<td style="line-height: 19px"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0"></td></tr></tbody></table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
<tbody>
<tr align="right">
<td style="line-height: 19px"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
<table cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td style="line-height: 19px" valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0"><br></td>
<td style="line-height: 19px" valign="top" align="right"><a class="fbox" style="font-size: 12px; color: rgb(92,129,167); line-height: 13px; font-family: verdana, nsimsun, arial, sans-serif; text-decoration: none" href="http://www.ibm.com/developerworks/cn/xml/x-stax1.html#main"><b>回页首</b></a></td></tr></tbody></table></td></tr></tbody></table><br><br>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><a name="N100DF"><span class="atitle" style="font-weight: bold; font-size: 18px; font-family: arial, sans-serif">基于指针的 API</span></a></p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">如果使用基于指针的 API，应用程序通过在 XML 标记流中移动逻辑指针来处理 XML。基于指针的解析器实质上是一个状态机，在事件的驱动下从一个良好定义的状态转移到另一个状态。这里的触发事件是随着应用程序使用适当的方法推动解析器在标记流中前进而解析出来的 XML 标记。在每个状态，都可使用一组方法获得上一个事件的信息。一般来说，并非每个状态下都能使用所有的方法。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">使用基于指针的方法，应用程序首先必须通过调用其<span class="Apple-converted-space">&nbsp;</span><code>createXMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>方法从<span class="Apple-converted-space">&nbsp;</span><code>XMLInputFactory</code><span class="Apple-converted-space">&nbsp;</span>得到<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamReader</code>。该方法有多个版本，支持不同类型的输入。比方说，可以创建<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>解析<span class="Apple-converted-space">&nbsp;</span><code>plain java.io.InputStream</code>、<code>java.io.Reader</code><span class="Apple-converted-space">&nbsp;</span>或者 JAXP Source（<code>javax.xml.transform.Source</code>）。从理论上说，后一种办法很容易和其他 JAXP 技术交互，比如 SAX 和 DOM。</p><br><a name="N1010B"><b>清单 2. 创建<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>解析<span class="Apple-converted-space">&nbsp;</span><code>InputStream</code><span class="Apple-converted-space">&nbsp;</span></b></a><br>
<table cellspacing="0" cellpadding="0" width="100" border="0">
<tbody>
<tr>
<td class="code-outline" style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 5px; padding-bottom: 5px; border-left: rgb(204,204,204) 1px solid; line-height: 19px; padding-top: 5px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><pre class="displaycode" style="margin-top: 0px; font-size: 11px; margin-bottom: 0px; font-family: 'Andale Mono', 'Lucida Console', monaco, fixed, monospace">                
URL url = new URL(uri);
InputStream input = url.openStream();
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader r = factory.createXMLStreamReader(uri, input);
// process the stream
// ...
r.close();
input.close();
</pre></td></tr></tbody></table><br>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>接口基本上定义了基于指针的 API（虽然标记常量在其超类型<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamConstants</code><span class="Apple-converted-space">&nbsp;</span>接口中定义）。之所以称为基于指针，是因为读取器就像是底层标记流上的指针。应用程序可以沿着标记流向前推进指针并分析当前指针所在位置的标记。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>提供了多种方法导航标记流。为了确定当前指针所指向的标记（或事件）的类型，应用程序可以调用<span class="Apple-converted-space">&nbsp;</span><code>getEventType()</code>。该方法返回接口<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamConstants</code><span class="Apple-converted-space">&nbsp;</span>中定义的一个标记常量。移动到下一个标记，应用程序可以调用<span class="Apple-converted-space">&nbsp;</span><code>next()</code>。该方法也返回解析的标记的类型，如果接着调用<span class="Apple-converted-space">&nbsp;</span><code>getEventType()</code><span class="Apple-converted-space">&nbsp;</span>则返回的值相同。只有当方法<span class="Apple-converted-space">&nbsp;</span><code>hasNext()</code><span class="Apple-converted-space">&nbsp;</span>返回 true 时（就是说还有其他标记需要解析）才能调用该方法（以及其他移动读取器的方法）。</p><br><a name="N10143"><b>清单 3. 使用<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>处理 XML 的常用模式</b></a><br>
<table cellspacing="0" cellpadding="0" width="100" border="0">
<tbody>
<tr>
<td class="code-outline" style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 5px; padding-bottom: 5px; border-left: rgb(204,204,204) 1px solid; line-height: 19px; padding-top: 5px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><pre class="displaycode" style="margin-top: 0px; font-size: 11px; margin-bottom: 0px; font-family: 'Andale Mono', 'Lucida Console', monaco, fixed, monospace">                
// create an XMLStreamReader
XMLStreamReader r = ...;
try {
 int event = r.getEventType();
 while (true) {
 switch (event) {
 case XMLStreamConstants.START_DOCUMENT:
 // add cases for each event of interest
 // ...
 }

 if (!r.hasNext())
 break;
 
 event = r.next();
 }
} finally {
 r.close();
}
</pre></td></tr></tbody></table><br>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">还与其他几种方法可以移动<span class="Apple-converted-space">&nbsp;</span><code>reader</code>。<span class="Apple-converted-space">&nbsp;</span><code>nextTag()</code><span class="Apple-converted-space">&nbsp;</span>方法将跳过所有的空白、注释或处理指令，直到遇到<span class="Apple-converted-space">&nbsp;</span><code>START_ELEMENT</code><span class="Apple-converted-space">&nbsp;</span>或<span class="Apple-converted-space">&nbsp;</span><code>END_ELEMENT</code>。该方法在解析只含元素的内容时很有用，如果在发现标记之前遇到非空白文本（不包括注释或处理指令），就会抛出异常。<code>getElementText()</code><span class="Apple-converted-space">&nbsp;</span>方法返回元素的开始和关闭标签（即<span class="Apple-converted-space">&nbsp;</span><code>START_ELEMENT</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>END_ELEMENT</code>）之间的所有文本内容。如果遇到嵌套的元素就会抛出异常。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">请注意，这里的 “标记” 和 “事件” 可以互换使用。虽然基于指针的 API 的文档说的是事件，但把输入源看成标记流很方便。而且不容易造成混乱，因为还有一整套基于事件的 API（那里的事件是真正的对象）。不过，<code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>的事件本质上并非都是标记。比方说，<code>START_DOCUMENT</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>END_DOCUMENT</code><span class="Apple-converted-space">&nbsp;</span>事件不需要对应的标记。前一个事件是解析开始之前发生，后者则在没有更多解析工作要做的时候发生（比如解析完成最后一个元素的关闭标签之后，读取器处于<span class="Apple-converted-space">&nbsp;</span><code>END_ELEMENT</code><span class="Apple-converted-space">&nbsp;</span>状态，但是如果没有发现更多的标记需要解析，读取器就会切换到<span class="Apple-converted-space">&nbsp;</span><code>END_DOCUMENT</code><span class="Apple-converted-space">&nbsp;</span>状态）。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><a name="N10183"><span class="smalltitle" style="font-weight: bold; font-size: 15px; font-family: arial, nsimsun, sans-serif">处理 XML 文档</span></a></p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">在每个解析器状态，应用程序都可通过可用的方法获得相关信息。比如，无论当前是什么类型的事件，<code>getNamespaceContext()</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>getNamespaceURI()</code><span class="Apple-converted-space">&nbsp;</span>方法可以获得当前有效的名称空间上下文和名称空间 URI。类似的，<code>getLocation()</code><span class="Apple-converted-space">&nbsp;</span>可以获得当前事件的位置信息。方法<code>hasName()</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>hasText()</code><span class="Apple-converted-space">&nbsp;</span>可以分别判断当前事件是否有名称（比如元素或属性）或文本（比如字符、注释或 CDATA）。方法<span class="Apple-converted-space">&nbsp;</span><code>isStartElement()</code>、<code>isEndElement()</code>、<code>isCharacters()</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>isWhiteSpace()</code><span class="Apple-converted-space">&nbsp;</span>可以方便地确定当前事件的性质。最后，方法 require(<code>int</code>,<span class="Apple-converted-space">&nbsp;</span><code>String</code>,<span class="Apple-converted-space">&nbsp;</span><code>String</code>) 可以声明预期的解析器状态；除非当前事件是指定的类型，并且本地名和名称空间（如果给出的话）与当前事件匹配，否则该方法将抛出异常。</p><br><a name="N101C0"><b>清单 4. 如果当前事件是<span class="Apple-converted-space">&nbsp;</span><code>START_ELEMENT</code><span class="Apple-converted-space">&nbsp;</span>使用有关的属性方法</b></a><br>
<table cellspacing="0" cellpadding="0" width="100" border="0">
<tbody>
<tr>
<td class="code-outline" style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 5px; padding-bottom: 5px; border-left: rgb(204,204,204) 1px solid; line-height: 19px; padding-top: 5px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><pre class="displaycode" style="margin-top: 0px; font-size: 11px; margin-bottom: 0px; font-family: 'Andale Mono', 'Lucida Console', monaco, fixed, monospace">                
if (reader.getEventType() == XMLStreamConstants.START_ELEMENT) {
 System.out.println("Start Element: " + reader.getName());
 for(int i = 0, n = reader.getAttributeCount(); i &lt; n; ++i) {
 QName name = reader.getAttributeName(i);
 String value = reader.getAttributeValue(i);
 System.out.println("Attribute: " + name + "=" + value);
 }
}
</pre></td></tr></tbody></table><br>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">创建之后，<code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>将从<span class="Apple-converted-space">&nbsp;</span><code>START_DOCUMENT</code><span class="Apple-converted-space">&nbsp;</span>状态开始（即<span class="Apple-converted-space">&nbsp;</span><code>getEventType()</code><span class="Apple-converted-space">&nbsp;</span>返回<span class="Apple-converted-space">&nbsp;</span><code>START_DOCUMENT</code>）。处理标记的时候应考虑到这一点。和迭代器不同，不需要先移动指针（使用<span class="Apple-converted-space">&nbsp;</span><code>next()</code>）来进入合法的状态。同样地，当读取器转换到最终状态<span class="Apple-converted-space">&nbsp;</span><code>END_DOCUMENT</code>之后，应用程序也不应再移动它。在这种状态下，<code>hasNext()</code><span class="Apple-converted-space">&nbsp;</span>方法将返回 false。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><code>START_DOCUMENT</code><span class="Apple-converted-space">&nbsp;</span>事件提供了获取关于文档本身信息的方法，如<span class="Apple-converted-space">&nbsp;</span><code>getEncoding()</code>、<code>getVersion()</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>isStandalone()</code>。应用程序也可调用<span class="Apple-converted-space">&nbsp;</span><code>getProperty(String)</code><span class="Apple-converted-space">&nbsp;</span>获得命名属性的值，不过一些属性仅在特定状态做了定义（比方说，如果当前事件是 DTD，则属性<code>javax.xml.stream.notations</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>javax.xml.stream.entities</code><span class="Apple-converted-space">&nbsp;</span>分别返回所有的符号和实体声明）。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">在<span class="Apple-converted-space">&nbsp;</span><code>START_ELEMENT</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>END_ELEMENT</code><span class="Apple-converted-space">&nbsp;</span>事件中，可以使用和元素名称以及名称空间有关的方法（如<span class="Apple-converted-space">&nbsp;</span><code>getName()</code>、<code>getLocalName()</code>、<code>getPrefix()</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>getNamespaceXXX()</code>），在<span class="Apple-converted-space">&nbsp;</span><code>START_ELEMENT</code><span class="Apple-converted-space">&nbsp;</span>事件中还可使用与属性有关的方法（<code>getAttributeXXX()</code>）。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><code>ATTRIBUTE</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>NAMESPACE</code><span class="Apple-converted-space">&nbsp;</span>也被识别为独立的事件，虽然在解析 典型的 XML 文档时不会用到。但是当<span class="Apple-converted-space">&nbsp;</span><code>ATTRIBUTE</code><span class="Apple-converted-space">&nbsp;</span>或<span class="Apple-converted-space">&nbsp;</span><code>NAMESPACE</code><span class="Apple-converted-space">&nbsp;</span>节点作为 XPath 查询结果返回时可以使用。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">和基于文本的事件（如<span class="Apple-converted-space">&nbsp;</span><code>CHARACTERS</code>、<code>CDATA</code>、<code>COMMENT</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>SPACE</code>），可使用各种<span class="Apple-converted-space">&nbsp;</span><code>getTextXXX()</code><span class="Apple-converted-space">&nbsp;</span>方法取得文本。可以分别使用<span class="Apple-converted-space">&nbsp;</span><code>getPITarget()</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>getPIData()</code><span class="Apple-converted-space">&nbsp;</span>检索<span class="Apple-converted-space">&nbsp;</span><code>PROCESSING_INSTRUCTION</code><span class="Apple-converted-space">&nbsp;</span>的目标和数据。<code>ENTITY_REFERENCE</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>DTD</code><span class="Apple-converted-space">&nbsp;</span>也支持<code>getText()</code>，<code>ENTITY_REFERENCE</code><span class="Apple-converted-space">&nbsp;</span>还支持<span class="Apple-converted-space">&nbsp;</span><code>getLocalName()</code>。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">解析完成后，应用程序关闭读取器并释放解析过程中获得的资源。请注意这样并没有关闭底层的输入源。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">清单 5 提供了一个完整的例子，使用基于指针的 API 处理 XML 文档。首先取得<span class="Apple-converted-space">&nbsp;</span><code>XMLInputFactory</code><span class="Apple-converted-space">&nbsp;</span>的默认实例并创建一个<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>解析给定的输入流。然后不断检查读取器的状态，根据当前事件的类型报告某些信息（比如在<span class="Apple-converted-space">&nbsp;</span><code>START_ELEMENT</code><span class="Apple-converted-space">&nbsp;</span>状态下报告元素名及元素属性）。最后，遇到<span class="Apple-converted-space">&nbsp;</span><code>END_DOCUMENT</code><span class="Apple-converted-space">&nbsp;</span>时关闭读取器。</p><br><a name="N1028F"><b>清单 5. 使用<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>解析 XML 文档的完整例子</b></a><br>
<table cellspacing="0" cellpadding="0" width="100" border="0">
<tbody>
<tr>
<td class="code-outline" style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 5px; padding-bottom: 5px; border-left: rgb(204,204,204) 1px solid; line-height: 19px; padding-top: 5px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><pre class="displaycode" style="margin-top: 0px; font-size: 11px; margin-bottom: 0px; font-family: 'Andale Mono', 'Lucida Console', monaco, fixed, monospace">                
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader r = factory.createXMLStreamReader(input);
try {
 int event = r.getEventType();
 while (true) {
 switch (event) {
 case XMLStreamConstants.START_DOCUMENT:
 out.println("Start Document.");
 break;
 case XMLStreamConstants.START_ELEMENT:
 out.println("Start Element: " + r.getName());
 for(int i = 0, n = r.getAttributeCount(); i &lt; n; ++i)
 out.println("Attribute: " + r.getAttributeName(i) 
 + "=" + r.getAttributeValue(i));
 
 break;
 case XMLStreamConstants.CHARACTERS:
 if (r.isWhiteSpace())
 break;
 
 out.println("Text: " + r.getText());
 break;
 case XMLStreamConstants.END_ELEMENT:
 out.println("End Element:" + r.getName());
 break;
 case XMLStreamConstants.END_DOCUMENT:
 out.println("End Document.");
 break;
 }
 
 if (!r.hasNext())
 break;

 event = r.next();
 }
} finally {
 r.close();
}
</pre></td></tr></tbody></table><br>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><a name="N10299"><span class="smalltitle" style="font-weight: bold; font-size: 15px; font-family: arial, nsimsun, sans-serif"><code>XMLStreamReader</code><span class="Apple-converted-space">&nbsp;</span>的高级用法</span></a></p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">通过调用<span class="Apple-converted-space">&nbsp;</span><code>XMLInputFactory</code><span class="Apple-converted-space">&nbsp;</span>的带有基本读取器的<span class="Apple-converted-space">&nbsp;</span><code>createFilteredReader</code><span class="Apple-converted-space">&nbsp;</span>方法和一个应用程序定义的筛选器（即实现<span class="Apple-converted-space">&nbsp;</span><code>StreamFilter</code><span class="Apple-converted-space">&nbsp;</span>的类实例），可以创建筛选过的<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamReader</code>。导航筛选过的读取器时，读取器每次移动到下一个标记之前都会询问筛选器。如果筛选器认可了当前事件，就将其公开给筛选过的读取器。否则跳过这个标记并检查下一个，依此类推。这种方法可以让开发人员创建一个仅处理解析内容子集的基于指针的 XML 处理程序，并与针对不同的扩展的内容模型的筛选器结合使用。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">执行更复杂的流操作，可以创建<span class="Apple-converted-space">&nbsp;</span><code>StreamReaderDelegate</code><span class="Apple-converted-space">&nbsp;</span>的子类并重写合适的方法。然后使用这个子类的实例包装基本<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamReader</code>，从而为应用程序提供一个修改过的基本 XML 流的视图。可通过这种技术对 XML 流执行简单的转换，比如筛掉或者替换特定的标记，甚至增加新的标记。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">清单 6 用定制的<span class="Apple-converted-space">&nbsp;</span><code>StreamReaderDelegate</code><span class="Apple-converted-space">&nbsp;</span>包装了基本<span class="Apple-converted-space">&nbsp;</span><code>XMLStreamReader</code>，重写了<span class="Apple-converted-space">&nbsp;</span><code>next()</code><span class="Apple-converted-space">&nbsp;</span>方法来跳过<span class="Apple-converted-space">&nbsp;</span><code>COMMENT</code><span class="Apple-converted-space">&nbsp;</span>和<span class="Apple-converted-space">&nbsp;</span><code>PROCESSING_INSTRUCTION</code><span class="Apple-converted-space">&nbsp;</span>事件。使用该读取器时，应用程序不用担心会遇到这种类型的标记。</p><br><a name="N102DC"><b>清单 6. 使用定制的<span class="Apple-converted-space">&nbsp;</span><code>StreamReaderDelegate</code><span class="Apple-converted-space">&nbsp;</span>筛选注释和处理指令</b></a><br>
<table cellspacing="0" cellpadding="0" width="100" border="0">
<tbody>
<tr>
<td class="code-outline" style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 5px; padding-bottom: 5px; border-left: rgb(204,204,204) 1px solid; line-height: 19px; padding-top: 5px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><pre class="displaycode" style="margin-top: 0px; font-size: 11px; margin-bottom: 0px; font-family: 'Andale Mono', 'Lucida Console', monaco, fixed, monospace">                
URL url = new URL(uri);
InputStream input = url.openStream();

XMLInputFactory f = XMLInputFactory.newInstance();
XMLStreamReader r = f.createXMLStreamReader(uri, input);
XMLStreamReader fr = new StreamReaderDelegate(r) {
 public int next() throws XMLStreamException {
 while (true) {
 int event = super.next();
 switch (event) {
 case XMLStreamConstants.COMMENT:
 case XMLStreamConstants.PROCESSING_INSTRUCTION:
 continue;
 default:
 return event;
 }
 }
 }
};

try {
 int event = fr.getEventType();
 while (true) {
 switch (event) {
 case XMLStreamConstants.COMMENT:
 case XMLStreamConstants.PROCESSING_INSTRUCTION:
 // this should never happen
 throw new IllegalStateException("Filter failed!");
 default:
 // process XML normally
 }

 if (!fr.hasNext())
 break;

 event = fr.next();
 }
} finally {
 fr.close();
}

input.close();
</pre></td></tr></tbody></table><br><br>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<td style="line-height: 19px"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0"></td></tr></tbody></table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
<tbody>
<tr align="right">
<td style="line-height: 19px"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
<table cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td style="line-height: 19px" valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0"><br></td>
<td style="line-height: 19px" valign="top" align="right"><a class="fbox" style="font-size: 12px; color: rgb(92,129,167); line-height: 13px; font-family: verdana, nsimsun, arial, sans-serif; text-decoration: none" href="http://www.ibm.com/developerworks/cn/xml/x-stax1.html#main"><b>回页首</b></a></td></tr></tbody></table></td></tr></tbody></table><br><br>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><a name="N102E6"><span class="atitle" style="font-weight: bold; font-size: 18px; font-family: arial, sans-serif">基于指针处理之外的其他技术</span></a></p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">可以看到，基于指针的 API 主要是为了提高效率。所有的状态信息可以直接从流读取器获得，不需要创建额外的对象。非常适用于性能和低内存占用至关重要的应用程序。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">人们早就认识到了拉式 XML 解析的好处。事实上，StAX 本身源于一种称为<span class="Apple-converted-space">&nbsp;</span><i>XML Pull Parsing</i><span class="Apple-converted-space">&nbsp;</span>的方法。XML Pull Parser API 类似于 StAX 所提供的基于指针的 API，可以通过分析解析器的状态获得上一个解析事件的信息，然后移动到下一个，依此类推。但没有提供基于事件迭代器的 API。这是一种非常轻型的方法，特别适合资源受限的环境，比如 J2ME。但是，很少有实现提供企业级特性如验证，因此 XML Pull 一直未受到企业 Java 开发人员的关注。</p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">基于以往拉式解析器实现的经验，StAX 的创建者选择了在基于指针的 API 之外增加一种面向对象的 API。虽然<span class="Apple-converted-space">&nbsp;</span><code>XMLEventReader</code><span class="Apple-converted-space">&nbsp;</span>接口看起来似乎很简单，但是基于事件迭代器的方法具有一个基于指针的方法不具备的重要优点。通过将解析器事件变成一级对象，从而让应用程序可以采用面向对象的方式处理它们。这样做有助于模块化和不同应用程序组件之间的代码重用。</p><br><a name="N10300"><b>清单 7. 使用 StAX<span class="Apple-converted-space">&nbsp;</span><code>XMLEventReader</code><span class="Apple-converted-space">&nbsp;</span>解析 XML</b></a><br>
<table cellspacing="0" cellpadding="0" width="100" border="0">
<tbody>
<tr>
<td class="code-outline" style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 5px; padding-bottom: 5px; border-left: rgb(204,204,204) 1px solid; line-height: 19px; padding-top: 5px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><pre class="displaycode" style="margin-top: 0px; font-size: 11px; margin-bottom: 0px; font-family: 'Andale Mono', 'Lucida Console', monaco, fixed, monospace">                
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
XMLEventReader reader = inputFactory.createXMLEventReader(input);
try {
 while (reader.hasNext()) {
 XMLEvent e = reader.nextEvent();
 if (e.isCharacters() &amp;&amp; ((Characters) e).isWhiteSpace())
 continue;
 
 out.println(e);
 }
} finally {
 reader.close();
}
</pre></td></tr></tbody></table><br><br>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<td style="line-height: 19px"><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0"></td></tr></tbody></table>
<table class="no-print" cellspacing="0" cellpadding="0" align="right">
<tbody>
<tr align="right">
<td style="line-height: 19px"><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
<table cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td style="line-height: 19px" valign="center"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0"><br></td>
<td style="line-height: 19px" valign="top" align="right"><a class="fbox" style="font-size: 12px; color: rgb(92,129,167); line-height: 13px; font-family: verdana, nsimsun, arial, sans-serif; text-decoration: none" href="http://www.ibm.com/developerworks/cn/xml/x-stax1.html#main"><b>回页首</b></a></td></tr></tbody></table></td></tr></tbody></table><br><br>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><a name="N1030A"><span class="atitle" style="font-weight: bold; font-size: 18px; font-family: arial, sans-serif">结束语</span></a></p>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">本文介绍了 StAX 及其基于指针的 API。第 2 部分将深入讨论事件迭代器 API。</p><br><br>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><a name="resources"><span class="atitle" style="font-weight: bold; font-size: 18px; font-family: arial, sans-serif">参考资料</span></a></p><b>学习</b><br>
<ul style="margin-top: 2px; margin-bottom: 2px; padding-bottom: 2px; padding-top: 2px">
<li>您可以参阅本文在 developerWorks 全球网站上的<span class="Apple-converted-space">&nbsp;</span><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/xml/library/x-stax1.html?S_TACT=105AGX52&amp;S_CMP=cn-a-x" target="_blank">英文原文</a>。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/library/x-stax2.html">使用 StAX 解析 XML，第 2 部分: 拉式解析和事件</a>（Peter Nehrer，developerWorks，2007 年 7 月）：本系列第 2 部分介绍基于事件迭代器的 API 以及它为 Java 开发人员带来的好处。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/cn/xml/x-stax3.html">使用 StAX 解析 XML，第 3 部分: 使用定制事件和编写 XML</a>（Peter Nehrer，developerWorks，2007 年 7 月）：将介绍定制化技术，该技术使用由应用程序定义的事件，您还将看到如何创建定制事件类并使用它们结合基于事件迭代器的 API 来处理 XML。最后（同样也是重要的一点），将回顾由 StAX 提供的可将 XML 编写为标记流和事件对象的序列化器 API。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://jcp.org/en/jsr/detail?id=173">JSR 173: Streaming API for XML</a>：阅读这份 Java Specification Request，它提出了可拉式解析 XML 的基于 Java 的 API。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.xmlpull.org/index.shtml">XML Pull Parsing</a>：这个站点致力于推广和培训拉式 XML 解析。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://dev2dev.bea.com/xml/stax.html">BEA Dev2Dev Online: StAX</a>：BEA 关于 StAX 的网页，包括 WebLogic StAX 实现的链接。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/cn/views/xml/tutorials.jsp?cv_doc_id=85087">利用 Java 技术进行 XML 编程，第 1 部分</a>（Doug Tidwell，developerWorks，2004 年 2 月）：获得关于使用 Java 进行 XML 编程的教程，内容包括 XML 的通用 API，以及如何解析、创建、操作和转换 XML 文档。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/cn/xml/x-jaxp/index.html">JAXP 全面介绍，第 1 部分</a>（Brett McLaughlin，developerWorks，2005 年 6 月）：了解如何使用 JAXP API 的解析和验证特性。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/cn/xml/x-tipstx/index.html">技巧: 使用 XML 流解析器</a>（Berthold Daum，developerWorks，2003 年 11 月）：这篇技巧介绍了如何利用 StAX 提供的流解析器高效解析 XML。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/cn/xml/x-tipstx4/index.html">技巧: 使用 StAX 编写 XML 文档</a>（Berthold Daum，developerWorks，2004 年 1 月）：使用 StAX 序列化器 XML —— 解析 XML 文档并将 XML 文档写入一个输出流。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/xml/library/wa-xslt/?S_TACT=105AGX52&amp;S_CMP=cn-a-x">An XSLT style sheet and an XML dictionary approach to internationalization</a>（Laura Menke，developerWorks，2001 年 4 月）：阅读 XSLT 用于解决实际问题的例子：通过词典驱动的方法对网页实现动态国际化，更新站点内容时减少需要编辑的文件。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/cn/xml/x-xslang/">XSLT 处理程序是如何工作的</a>（Benoît Marchal，developerWorks，2004 年 4 月）：了解 XSLT 处理程序的有关理论，提高 XSLT 编程效率。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/cn/xml/x-xslt20pt1.html">准备从 XSLT 1.0 升级到 2.0，第 1 部分: XSLT 的改进</a>（David Marston 和 Joanne Tong，developerWorks，2006 年 11 月）：对 XSLT 2.0 的主要特性和 XSLT 1.0 （目前使用的版本）的不足之处进行了介绍。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/certify/certs/xmsdreltop.shtml?S_TACT=105AGX52&amp;S_CMP=cn-a-x">IBM XML 认证</a>：了解如何才能成为一名 IBM 认证的 XML 及相关技术的开发人员。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/cn/xml/library/technical/xml.html">XML 技术库</a>：developerWorks 中国网站 XML 专区提供了大量技术文章、技巧、教程、标准以及 IBM 红皮书。<br><br></li>
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/cn/offers/techbriefings/">developerWorks 技术活动和网络广播</a>：随时关注技术的最新进展。<br><br></li>
<li>通过<span class="Apple-converted-space">&nbsp;</span><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/cn/xml">developerWorks 中国网站 XML 专区</a><span class="Apple-converted-space">&nbsp;</span>了解 XML 的方方面面。</li></ul><br><b>获得产品和技术</b><br>
<ul style="margin-top: 2px; margin-bottom: 2px; padding-bottom: 2px; padding-top: 2px">
<li>Sun 的<span class="Apple-converted-space">&nbsp;</span><a style="color: rgb(92,129,167)" href="https://jaxp.dev.java.net/">JAXP 项目页</a>：可以找到各种 JAXP 版本的下载链接。<br><br></li></ul><br><b>讨论</b><br>
<ul style="margin-top: 2px; margin-bottom: 2px; padding-bottom: 2px; padding-top: 2px">
<li><a style="color: rgb(92,129,167)" href="http://www.ibm.com/developerworks/community/">参与论坛讨论</a>。</li></ul><br><br>
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"><a name="author"><span class="atitle" style="font-weight: bold; font-size: 18px; font-family: arial, sans-serif">关于作者</span></a></p>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<td style="line-height: 19px" colspan="3"><img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="100%"></td></tr>
<tr valign="top" align="left">
<td style="line-height: 19px">
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px"></p></td>
<td style="line-height: 19px"><img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="4"></td>
<td style="line-height: 19px" width="100%">
<p style="margin-top: 0px; margin-bottom: 0px; padding-bottom: 8px; padding-top: 5px">Peter Nehrer 是一名专长于基于 Eclipse 的企业解决方案和 Java EE 应用程序的软件顾问。他创建了 Ecliptical Software Inc.，并且是一些和 Eclipse 有关的开放源码项目的贡献者。他拥有从马萨诸塞州大学阿默斯特校区获得的计算机科学硕士学位。</p></td></tr></tbody></table></span></span><br class="Apple-interchange-newline"><img src ="http://www.blogjava.net/beansoft/aggbug/331566.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/beansoft/" target="_blank">BeanSoft</a> 2010-09-09 19:23 <a href="http://www.blogjava.net/beansoft/archive/2010/09/09/331566.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaRebel的XXX</title><link>http://www.blogjava.net/beansoft/archive/2008/11/24/242373.html</link><dc:creator>BeanSoft</dc:creator><author>BeanSoft</author><pubDate>Mon, 24 Nov 2008 13:47:00 GMT</pubDate><guid>http://www.blogjava.net/beansoft/archive/2008/11/24/242373.html</guid><description><![CDATA[
		<p>本XXX只能用于 JavaRabel 的早期版本, 对最新版无效:  ZeroTurnaround JavaRebel 1.2.2 (200812021546) 如有需要可以 Mail 我.<br />XXX是什么, 大家自己体会. 原则上这个XXX是只供我本人自己试用的, 现在提供给大家来试用. 2K, 用法见文件注释.</p>
		<p>下载地址1:</p>
		<p>
				<a title="http://cid-519b3f7aa2172030.skydrive.live.com/self.aspx/java/jrebel.rar" href="http://cid-519b3f7aa2172030.skydrive.live.com/self.aspx/java/jrebel.rar">http://cid-519b3f7aa2172030.skydrive.live.com/self.aspx/java/jrebel.rar</a>
		</p>
		<p>下载地址2:</p>
		<p>
				<a href="http://beansoft.java-cn.org/download/jrebel.rar">http://beansoft.java-cn.org/download/jrebel.rar</a>
		</p>
<img src ="http://www.blogjava.net/beansoft/aggbug/242373.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/beansoft/" target="_blank">BeanSoft</a> 2008-11-24 21:47 <a href="http://www.blogjava.net/beansoft/archive/2008/11/24/242373.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Head First EJB 中文版电子书下载[MOVED]</title><link>http://www.blogjava.net/beansoft/archive/2008/05/02/197757.html</link><dc:creator>BeanSoft</dc:creator><author>BeanSoft</author><pubDate>Fri, 02 May 2008 09:28:00 GMT</pubDate><guid>http://www.blogjava.net/beansoft/archive/2008/05/02/197757.html</guid><description><![CDATA[
		<a title="Permanent Link to Head First EJB 中文版电子书下载" href="http://www.beansoft.biz/?p=1128" rel="bookmark">
				<font color="#225588">Head First EJB 中文版电子书下载</font>
		</a>
<img src ="http://www.blogjava.net/beansoft/aggbug/197757.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/beansoft/" target="_blank">BeanSoft</a> 2008-05-02 17:28 <a href="http://www.blogjava.net/beansoft/archive/2008/05/02/197757.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>New Features in EJB 3.1以及Spring加入Java EE 6 阵营</title><link>http://www.blogjava.net/beansoft/archive/2008/04/27/196416.html</link><dc:creator>BeanSoft</dc:creator><author>BeanSoft</author><pubDate>Sun, 27 Apr 2008 03:00:00 GMT</pubDate><guid>http://www.blogjava.net/beansoft/archive/2008/04/27/196416.html</guid><description><![CDATA[<p>New Features in EJB 3.1, <a href="http://www.theserverside.com/tt/articles/article.tss?l=NewFeaturesinEJB3-1">http://www.theserverside.com/tt/articles/article.tss?l=NewFeaturesinEJB3-1</a>. </p> <p>New Features in EJB 3.1 - Part 2, <a href="http://www.theserverside.com/tt/articles/article.tss?l=NewFeaturesEJB31">http://www.theserverside.com/tt/articles/article.tss?l=NewFeaturesEJB31</a></p> <p>Enterprise Java Community: The New Features in EJB 3.1 - Part 3 <a title="Enterprise Java Community- The New Features in EJB 3.1 - Part 3" href="http://www.theserverside.com/tt/articles/article.tss?l=NewFeaturesEJB31-3">Enterprise Java Community- The New Features in EJB 3.1 - Part 3</a></p> <p>看看下面的链接：</p> <p>JSR 316: Java EE 6, <a href="http://jcp.org/en/jsr/detail?id=316">http://jcp.org/en/jsr/detail?id=316</a>.</p> <p>成员列表（以前的反叛者，号称不用EJB的Spring后台公司，红字部分，也加入了Java EE 6 的大家庭，看来新版Java EE也许是大势所趋啊，呵呵）：</p> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td valign="top" width="100%"> <div> <div class="header3">Specification Lead</div> <table border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <td>&nbsp;</td> <td>Roberto Chinnici</td> <td width="20" nowrap>&nbsp;</td> <td>Sun Microsystems, Inc. </td></tr> <tr> <td><a href="http://jcp.org/en/press/news/star"><img border="0" hspace="3" alt="Star Spec Lead" vspace="2" src="http://jcp.org/images/jsr/stars-final-sml-anim-ir.gif" width="20" height="20"></a></td> <td>Bill Shannon</td> <td width="20" nowrap>&nbsp;</td> <td>Sun Microsystems, Inc. </td></tr></tbody></table>&nbsp;<br> <div class="header3">Expert Group</div> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tbody> <tr> <td valign="top" width="33%">BEA Systems</td> <td width="20" nowrap>&nbsp;</td> <td valign="top" width="33%">Bien, Adam</td> <td width="20" nowrap>&nbsp;</td> <td valign="top" width="33%">Blevins, David</td></tr> <tr> <td>Divakaran, Rejeev</td> <td width="20" nowrap>&nbsp;</td> <td>Ericsson AB</td> <td width="20" nowrap>&nbsp;</td> <td>Genender, Jeff</td></tr> <tr> <td>Goncalves, Antonio</td> <td width="20" nowrap>&nbsp;</td> <td>IBM</td> <td width="20" nowrap>&nbsp;</td> <td>Inria</td></tr> <tr> <td><strong><font color="#ff0000">Interface21 Inc</font></strong></td> <td width="20" nowrap>&nbsp;</td> <td>KEIL, Werner</td> <td width="20" nowrap>&nbsp;</td> <td>Kohen, Elika S.</td></tr> <tr> <td>Leme, Felipe</td> <td width="20" nowrap>&nbsp;</td> <td>NCsoft Corporation</td> <td width="20" nowrap>&nbsp;</td> <td>Oracle</td></tr> <tr> <td>Peking University</td> <td width="20" nowrap>&nbsp;</td> <td>Pramati Technologies</td> <td width="20" nowrap>&nbsp;</td> <td>Prasanna, Dhanji R.</td></tr> <tr> <td>Rahman, M. Reza</td> <td width="20" nowrap>&nbsp;</td> <td>Red Hat Middleware LLC</td> <td width="20" nowrap>&nbsp;</td> <td>SAP AG</td></tr> <tr> <td>Suleiman, Hani</td> <td width="20" nowrap>&nbsp;</td> <td>Sun Microsystems, Inc.</td> <td width="20" nowrap>&nbsp;</td> <td>Sybase</td></tr> <tr> <td>Tmax Soft, Inc.</td> <td width="20" nowrap>&nbsp;</td> <td>TongTech Ltd</td></tr></tbody></table></div></td></tr></tbody></table> <p>&nbsp;</p> <p>再看Spring直接开始了作为EJB容器的实现的支持项目，我一直说Spring只不过是另一个Application Server（而且还不是性能很好的那种），现在终于得到了验证，红字的就是 Rod 大叔（Java的开源，大多数最后都会成立公司，成为商业项目来运营，从Hibernate,JBoss再到Spring，无一例外，盖项目代码大了以后，就是开源了，外人也看不懂）：</p> <p><a title="http://static.interface21.com/projects/pitchfork/files/m4/docs/reference/html_single/" href="http://static.interface21.com/projects/pitchfork/files/m4/docs/reference/html_single/">http://static.interface21.com/projects/pitchfork/files/m4/docs/reference/html_single/</a></p> <h3><a name="d0e1"></a>Pitchfork: Spring JEE Support</h3> <h4>Reference Documentation </h4> <h5><strong><font color="#ff0000">Rod Johnson</font></strong></h5> <h5>Costin Leau</h5> <h5>Michael Chen</h5> <p>Version 1.0-m4 <p>At the moment, Spring JEE support understands the following annotations, which are part of the JSR 250 and JSR 220:  <ul> <li> <p>JSR 250 injection annotations (javax.annotation): @PostCostruct, @PreDestroy and @Resource</p> <li> <p>EJB3 interception annotations (javax.interceptor): @AroundInvoke, @ExcludeClassInterceptors, @ExcludeDefaultInterceptors, @Interceptors, @Invocation</p> <li> <p>EJB3 transaction annotations (javax.ejb): @Stateless, @ApplicationException and @TransactionAttribute</p> <li> <p>EJB3 injection annotation (javax.ejb): @EJB (since M2)</p></li></ul> <p>In short, Spring can understand Java EE 5.0 injection, interception and transactional metadata.</p><img src ="http://www.blogjava.net/beansoft/aggbug/196416.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/beansoft/" target="_blank">BeanSoft</a> 2008-04-27 11:00 <a href="http://www.blogjava.net/beansoft/archive/2008/04/27/196416.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>独家：Java EE 5 中文 API 文档在线阅读和操作视频(有声)</title><link>http://www.blogjava.net/beansoft/archive/2008/04/20/194353.html</link><dc:creator>BeanSoft</dc:creator><author>BeanSoft</author><pubDate>Sun, 20 Apr 2008 11:30:00 GMT</pubDate><guid>http://www.blogjava.net/beansoft/archive/2008/04/20/194353.html</guid><description><![CDATA[
		<p>
				<embed height="415" type="application/x-shockwave-flash" width="480" src="http://6.cn/player.swf?flag=0&amp;amp;vid=U7JkWvgnVutAJqMn8BRmUA" wmode="transparent" allowscriptaccess="always">
				</embed>
		</p>
		<p>如无法全屏，请点击这里：<a title="http://6.cn/watch/4599331.html" href="http://6.cn/watch/4599331.html">http://6.cn/watch/4599331.html</a> </p>
		<p>图文版说明及无声视频请参考<a href="/beansoft/archive/2008/04/17/193691.html">独家：Java EE 5 中文 API 文档在线阅读和操作视频</a></p>
<img src ="http://www.blogjava.net/beansoft/aggbug/194353.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/beansoft/" target="_blank">BeanSoft</a> 2008-04-20 19:30 <a href="http://www.blogjava.net/beansoft/archive/2008/04/20/194353.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>独家：Java EE 5 中文 API 文档在线阅读和操作视频</title><link>http://www.blogjava.net/beansoft/archive/2008/04/17/193691.html</link><dc:creator>BeanSoft</dc:creator><author>BeanSoft</author><pubDate>Thu, 17 Apr 2008 03:37:00 GMT</pubDate><guid>http://www.blogjava.net/beansoft/archive/2008/04/17/193691.html</guid><description><![CDATA[<p>本文由<a href="mailto:BeanSoft@126.com">BeanSoft@126.com</a>（刘长炯）原创，转载请注明出处！</p> <p> 最近互联网上挂起了一股到处散发广告传单，严重干扰工作学习的歪风。我想搞技术的爱国的话就多分享点资料和经验吧！这样总比那些整天只知道空谈爱国，动辄抵制XX的“爱国青年”强点。多share就是最大的爱国！</p> <p>相比较微软的开发工具详细的中文文档外，Java 的API长期以来只有英文，还好最近已经有了中文的Java SE文档。不过，Java EE 5 的中文API 却难得一见，然而，幸运的是现在我们终于可以看到中文的 Java EE 5文档了，虽然有些遗憾只能在线浏览，不过总比没有强，以后它们肯定会提供中文版的文档包下载的！</p> <p>&nbsp;</p> <p>这个阅读文档的地址就是<a title="http://doc.java.sun.com/DocWeb/" href="http://doc.java.sun.com/DocWeb/">http://doc.java.sun.com/DocWeb/</a>，而且，它采用开源的协议，读者可以注册一个用户参与翻译。也正因为如此，我认为其中的文档并不全面，需要有条件的人共同参与完成中文化文档。下面我们就看看如何阅读中文文档。</p> <p>进入首页：</p> <p><a href="http://www.blogjava.net/images/blogjava_net/beansoft/WindowsLiveWriter/JavaEE5API_981D/-2008-04-17_110035_2.png"><img border="0" alt="-2008-04-17_110035" src="http://www.blogjava.net/images/blogjava_net/beansoft/WindowsLiveWriter/JavaEE5API_981D/-2008-04-17_110035_thumb.png" width="952" height="233"></a> </p> <p><a href="http://www.blogjava.net/images/blogjava_net/beansoft/WindowsLiveWriter/JavaEE5API_981D/image_2.png"><img border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/beansoft/WindowsLiveWriter/JavaEE5API_981D/image_thumb.png" width="222" height="396"></a> <a href="http://www.blogjava.net/images/blogjava_net/beansoft/WindowsLiveWriter/JavaEE5API_981D/image_4.png"><img border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/beansoft/WindowsLiveWriter/JavaEE5API_981D/image_thumb_1.png" width="716" height="265"></a> </p> <p>如果要查看单篇中文文档，可以在“EJB日”上点右键，选择菜单项“在新窗口中打开”即可。如下图所示：</p> <p><a href="http://www.blogjava.net/images/blogjava_net/beansoft/WindowsLiveWriter/JavaEE5API_981D/image_6.png"><img border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/beansoft/WindowsLiveWriter/JavaEE5API_981D/image_thumb_2.png" width="442" height="339"></a> </p> <p>下面是操作视频：</p> <p>&nbsp;</p><embed height="768" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="1024" src="http://beansoft.java-cn.org/download/javaee5doc_cn.swf" quality="high" bgcolor="#FFFFFF"></embed><img src ="http://www.blogjava.net/beansoft/aggbug/193691.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/beansoft/" target="_blank">BeanSoft</a> 2008-04-17 11:37 <a href="http://www.blogjava.net/beansoft/archive/2008/04/17/193691.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐资料：Hibernate 3 入門和JPA 批注参考（中文）[MOVED]</title><link>http://www.blogjava.net/beansoft/archive/2008/03/08/184740.html</link><dc:creator>BeanSoft</dc:creator><author>BeanSoft</author><pubDate>Sat, 08 Mar 2008 12:40:00 GMT</pubDate><guid>http://www.blogjava.net/beansoft/archive/2008/03/08/184740.html</guid><description><![CDATA[
		<a href="http://www.beansoft.biz/?p=253">http://www.beansoft.biz/?p=253</a>
<img src ="http://www.blogjava.net/beansoft/aggbug/184740.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/beansoft/" target="_blank">BeanSoft</a> 2008-03-08 20:40 <a href="http://www.blogjava.net/beansoft/archive/2008/03/08/184740.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ant 入门讲解视频(22分03秒)[MOVED]</title><link>http://www.blogjava.net/beansoft/archive/2007/11/03/157955.html</link><dc:creator>BeanSoft</dc:creator><author>BeanSoft</author><pubDate>Sat, 03 Nov 2007 10:35:00 GMT</pubDate><guid>http://www.blogjava.net/beansoft/archive/2007/11/03/157955.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.blogjava.net/beansoft/archive/2007/11/03/157955.html'>阅读全文</a><img src ="http://www.blogjava.net/beansoft/aggbug/157955.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/beansoft/" target="_blank">BeanSoft</a> 2007-11-03 18:35 <a href="http://www.blogjava.net/beansoft/archive/2007/11/03/157955.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>