跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

技巧: 使用 XML 流解析器

使用 Streaming API for XML 更有效地解析 XML

Berthold Daum (berthold.daum@bdaum.de)), 总裁, BDaum Industrial Communications
Berthold Daum 是德国 Ltzelbach 的一名顾问和作家。他的近作有 System Architecture with XMLModeling Business Objects with XML Schema(均由 Morgan Kauffman 出版),要了解这些书的更多信息,请访问 http://www.bdaum.de。可以通过 berthold.daum@bdaum.de与 Berthold 联系。

简介: 这篇技巧展示了如何利用与规范一起部署的 StAX 参考实现,有效地使用 Streaming API for XML (StAX) 解析 XML 文档。Berthold Daum 解释了 StAX 中可用的两个 API 层:迭代器风格的 API 和基于指针的 API。

发布日期: 2003 年 12 月 01 日
级别: 中级
访问情况 : 1944 次浏览
评论: 


XML 拉式解析器以其卓越的性能和低内存占用而闻名。但是由于功能有限,直到最近 XML 拉式解析器还仅限于特定的应用。StAX 改变了这一切,它是 Java Community Process JSR-173 (请参阅 参考资料)的成果。随着规范进程进入最后阶段,各个厂商很快将推出用于实际应用的版本实现。

使用 StAX

对于多数应用程序员而言,与 Simple API for XML (SAX) 相比, StAX 将更加直观更容易使用。有两个 API 层 可供程序员选择:

  • 方便的、容易使用的、迭代器风格的 API。
  • 快速的、基于底层指针的 API。

无论使用哪一种,客户应用程序都可以完全控制解析过程和维护事件循环。这是拉式解析器和推式解析器的主要区别,如 SAX 自行组织事件循环并通过回调通知客户应用程序。


使用迭代器风格的 API

我们从迭代器风格的 API 开始。 XMLEventReader 实例通过 next() 方法提交 XMLEvent 类型的对象。通过调用适当的 API,您可以确定事件的类型和细节。或者可以使用 Java 语言的 instanceof 操作符确定具体的事件子类型。


清单 1. 迭代 XML 事件
import java.io.*;
import java.util.Iterator;
import javax.xml.namespace.QName;
import javax.xml.stream.*;
import javax.xml.stream.events.*;
public class ParseByEvent {
public static void main(String[] args)
throws FileNotFoundException, XMLStreamException {
// Use the reference implementation for the XML input factory
System.setProperty("javax.xml.stream.XMLInputFactory",
"com.bea.xml.stream.MXParserFactory");
// Create the XML input factory
XMLInputFactory factory = XMLInputFactory.newInstance();
// Create the XML event reader
FileReader reader = new FileReader("somefile.xml");
XMLEventReader r =
factory.createXMLEventReader(reader);
// Loop over XML input stream and process events
while(r.hasNext()) {
XMLEvent e = r.next();
processEvent(e);
}
}
/**
* Process a single XML event
* @param e - the event to be processed
*/
private static void processEvent(XMLEvent e) {
if (e.isStartElement()) {
QName qname = ((StartElement) e).getName();
String namespaceURI = qname.getNamespaceURI();
String localName = qname.getLocalPart();
Iterator iter = ((StartElement) e).getAttributes();
while (iter.hasNext()) {
Attribute attr = (Attribute) iter.next();
QName attributeName = attr.getName();
String attributeValue = attr.getValue();
}
}
if (e.isEndElement()) {
QName qname = ((EndElement) e).getName();
}
if (e.isCharacters()) {
String text = ((Characters) e).getData();
}
if (e.isStartDocument()) {
String version = ((StartDocument) e).getVersion();
String encoding = ((StartDocument) e).getCharacterEncodingScheme();
boolean isStandAlone = ((StartDocument) e).isStandalone();
}
}
}

XML Information Set 的其他对象类型,如注解、处理指令或者实体,也可以类似地检测和处理。


使用基于指针的 API

尽管迭代器风格的 API 非常方便和易于使用,它也带来了一些开销。解析器需要创建事件对象,这些对象在以后被无用单元收集器回收。对于高性能极其重要的应用程序,您可以选择基于指针的 API。 XMLStreamReader 类型的特点是 next() 方法提交一个整数值(而不是事件对象)表示事件类型。客户机应用程序可以查询阅读器获得其他的信息。


清单 2. 基于指针的 XML 处理
import java.io.*;
import javax.xml.stream.*;
public class ParseByIterator {
public static void main(String[] args)
throws FileNotFoundException, XMLStreamException {
// Use reference implementation
System.setProperty(
"javax.xml.stream.XMLInputFactory",
"com.bea.xml.stream.MXParserFactory");
// Create an input factory
XMLInputFactory xmlif = XMLInputFactory.newInstance();
// Create an XML stream reader
XMLStreamReader xmlr =
xmlif.createXMLStreamReader(new FileReader("somefile.xml"));
// Loop over XML input stream and process events
while (xmlr.hasNext()) {
processEvent(xmlr);
xmlr.next();
}
}
/**
* Process a single event
* @param xmlr - the XML stream reader
*/
private static void processEvent(XMLStreamReader xmlr) {
switch (xmlr.getEventType()) {
case XMLStreamConstants.START_ELEMENT :
processName(xmlr);
processAttributes(xmlr);
break;
case XMLStreamConstants.END_ELEMENT :
processName(xmlr);
break;
case XMLStreamConstants.SPACE :
case XMLStreamConstants.CHARACTERS :
int start = xmlr.getTextStart();
int length = xmlr.getTextLength();
String text =
new String(xmlr.getTextCharacters(), start, length);
break;
case XMLStreamConstants.COMMENT :
case XMLStreamConstants.PROCESSING_INSTRUCTION :
if (xmlr.hasText()) {
String piOrComment = xmlr.getText();
}
break;
}
}
private static void processName(XMLStreamReader xmlr) {
if (xmlr.hasName()) {
String prefix = xmlr.getPrefix();
String uri = xmlr.getNamespaceURI();
String localName = xmlr.getLocalName();
}
}
private static void processAttributes(XMLStreamReader xmlr) {
for (int i = 0; i < xmlr.getAttributeCount(); i++)
processAttribute(xmlr, i);
}
private static void processAttribute(XMLStreamReader xmlr, int index) {
String prefix = xmlr.getAttributePrefix(index);
String namespace = xmlr.getAttributeNamespace(index);
String localName = xmlr.getAttributeName(index);
String value = xmlr.getAttributeValue(index);
}
}

类似地,您也可以检测和处理其他事件类型,如 CDATAENTITY_REFERENCESTART_DOCUMENT 。根据我使用参考实现的体会, XMLStreamReader 解析文档比 XMLEventReader 快大约 30%。


下一步

这篇技巧演示了使用 Streaming API for XML (StAX) 的两个不同层次解析 XML 文档。在以后的技巧中,我将介绍 StAX 在具体场景中的应用以及如何通过 StAX 创建 XML 文档。


参考资料

关于作者

Berthold Daum 是德国 Ltzelbach 的一名顾问和作家。他的近作有 System Architecture with XMLModeling Business Objects with XML Schema(均由 Morgan Kauffman 出版),要了解这些书的更多信息,请访问 http://www.bdaum.de。可以通过 berthold.daum@bdaum.de与 Berthold 联系。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML
ArticleID=21531
ArticleTitle=技巧: 使用 XML 流解析器
publish-date=12012003
author1-email=berthold.daum@bdaum.de)
author1-email-cc=

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。