文档

Java™ 教程
隐藏目录
StAX API
路径:Java XML处理API (JAXP)
课程:XML流式API

StAX API

StAX API公开了用于迭代、基于事件的处理XML文档的方法。XML文档被视为一系列经过过滤的事件,并且信息集状态可以以过程化的方式存储。此外,与SAX不同,StAX API是双向的,可以同时读取和写入XML文档。

StAX API实际上是两个不同的API集:游标API和迭代器API。这两个API集将在本课程的后面详细介绍,但它们的主要特点如下。

游标API

顾名思义,StAX游标API表示一个游标,您可以使用该游标从头到尾遍历XML文档。该游标一次只能指向一个元素,并且始终向前移动,通常一次移动一个信息集元素。

两个主要的游标接口是XMLStreamReaderXMLStreamWriterXMLStreamReader包含用于从XML信息模型中检索的所有可能信息的访问器方法,包括文档编码、元素名称、属性、命名空间、文本节点、起始标记、注释、处理指令、文档边界等等;例如:

public interface XMLStreamReader {
    public int next() throws XMLStreamException;
    public boolean hasNext() throws XMLStreamException;

    public String getText();
    public String getLocalName();
    public String getNamespaceURI();
    // ... other methods not shown
}

您可以调用XMLStreamReader上的方法,如getTextgetName,以获取当前游标位置的数据。XMLStreamWriter提供了与StartElementEndElement事件类型相对应的方法;例如:

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

游标API在许多方面与SAX相似。例如,可用于直接访问字符串和字符信息的方法,并且可以使用整数索引来访问属性和命名空间信息。与SAX一样,游标API方法将XML信息作为字符串返回,从而减少了对象分配的要求。

迭代器API

StAX迭代器API将XML文档流表示为一组离散的事件对象。这些事件由应用程序拉取并由解析器按照源XML文档中的顺序提供。

基本迭代器接口称为XMLEvent,并且每个事件类型在 XMLEvent表中都有子接口。用于读取迭代器事件的主要解析器接口是XMLEventReader,用于写入迭代器事件的主要接口是XMLEventWriterXMLEventReader接口包含五个方法,其中最重要的是nextEvent,它返回XML流中的下一个事件。XMLEventReader实现了java.util.Iterator,这意味着从XMLEventReader返回的结果可以被缓存或传递到可以与标准Java迭代器一起工作的例程中,例如:

public interface XMLEventReader extends Iterator {
    public XMLEvent nextEvent() throws XMLStreamException;
    public boolean hasNext();
    public XMLEvent peek() throws XMLStreamException;
    // ...
}

类似地,在迭代器API的输出方面,你有:

public interface XMLEventWriter {
    public void flush() throws XMLStreamException;
    public void close() throws XMLStreamException;
    public void add(XMLEvent e) throws XMLStreamException;
    public void add(Attribute attribute) throws XMLStreamException;
    // ...
}

迭代器事件类型

XMLEvent

事件类型

描述

StartDocument

报告一组XML事件的开始,包括编码、XML版本和独立属性。

StartElement

报告元素的开始,包括任何属性和命名空间声明;还提供了访问开始标签的前缀、命名空间URI和本地名称的方法。

EndElement

报告元素的结束标记。如果已经在相应的StartElement上显式设置了命名空间,那么在这里可以重新调用已经过期的命名空间。

Characters

对应于XML的CData部分和CharacterData实体。请注意,可忽略的空格和重要的空格也被报告为Character事件。

EntityReference

字符实体可以作为离散事件报告,应用程序开发人员可以选择解析或保持未解析。默认情况下,实体将被解析。或者,如果不想将实体作为事件报告,则可以替换并将替换文本报告为Characters

ProcessingInstruction

报告底层处理指令的目标和数据。

Comment

返回注释的文本。

EndDocument

报告一组XML事件的结束。

DTD

报告与流相关联的DTD(如果有)的java.lang.String信息,并提供了一种返回在DTD中找到的自定义对象的方法。

Attribute

属性通常作为StartElement事件的一部分报告。但是,有时候希望将属性作为独立的Attribute事件返回;例如,当命名空间作为XQueryXPath表达式的结果返回时。

Namespace

与属性一样,命名空间通常作为StartElement的一部分报告,但有时希望将命名空间作为离散的Namespace事件报告。

请注意,只有在处理的文档中包含DTD时,才会创建DTDEntityDeclarationEntityReferenceNotationDeclarationProcessingInstruction事件。

事件映射示例

作为事件迭代器API如何映射XML流的示例,考虑以下XML文档:

<?xml version="1.0"?>
<BookCatalogue xmlns="http://www.publishing.org">
    <Book>
        <Title>瑜伽科学:瑜伽的科学</Title>
        <ISBN>81-40-34319-4</ISBN>
        <Cost currency="INR">11.50</Cost>
    </Book>
</BookCatalogue>

该文档将被解析为十八个主要和次要事件,如下表所示。请注意,次要事件通常从主要事件而不是直接访问。

#

元素/属性

事件

1

version="1.0"

开始文档

2

isCData = false data = "\n" IsWhiteSpace = true

字符

3

qname = BookCatalogue:http://www.publishing.org attributes = null namespaces = {BookCatalogue" -> http://www.publishing.org"}

开始元素

4

qname = Book attributes = null namespaces = null

开始元素

5

qname = Title attributes = null namespaces = null

开始元素

6

isCData = false data = "Yogasana Vijnana: the Science of Yoga\n\t" IsWhiteSpace = false

字符

7

qname = Title namespaces = null

结束元素

8

qname = ISBN attributes = null namespaces = null

开始元素

9

isCData = false data = "81-40-34319-4\n\t" IsWhiteSpace = false

字符

10

qname = ISBN 命名空间 = null

EndElement

11

qname = Cost 属性 = {"currency" -> INR} 命名空间 = null

StartElement

12

isCData = false 数据 = "11.50\n\t" IsWhiteSpace = false

Characters

13

qname = Cost 命名空间 = null

EndElement

14

isCData = false 数据 = "\n" IsWhiteSpace = true

Characters

15

qname = Book 命名空间 = null

EndElement

16

isCData = false 数据 = "\n" IsWhiteSpace = true

Characters

17

qname = BookCatalogue:http://www.publishing.org 命名空间 = {BookCatalogue" -> http://www.publishing.org"}

EndElement

18

EndDocument

在这个例子中有几个重要的事情需要注意:

选择Cursor和Iterator API

现在可以合理地问一下,“我应该选择哪个API?我应该创建XMLStreamReader还是XMLEventReader的实例?为什么会有两种类型的API?”

开发目标

StAX规范的作者针对三类开发者:

鉴于这些广泛的开发类别,StAX的作者认为定义两个小巧、高效的API比重载一个更大且必然更复杂的API更有用。

比较Cursor和Iterator API

在选择Cursor和Iterator API之前,你应该注意一些使用Iterator API而不能使用Cursor API的事情:

同样,在做选择时,请牢记以下一些建议:


上一页: 为什么使用StAX?
下一页: 使用StAX