StAX API

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

StAX API 实际上是两个截然不同的 API 集:“ cursor” API 和“ iterator” API。本类稍后将详细解释这两个 API 集,但下面将简要介绍它们的主要功能。

Cursor API

顾名思义,StAX cursor API 表示一个游标,您可以使用它从头到尾遍历 XML 文档。该光标一次可以指向一件事,并且总是向前移动,从不向后移动,通常一次指向一个信息集元素。

光标的两个主要interface是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 信息作为字符串 返回,从而最大程度地减少了对象分配要求。

Iterator API

StAX iterator API 将 XML 文档流表示为一组离散事件对象。这些事件由应用程序提取,并由解析器按在源 XML 文档中读取它们的 Sequences 提供。

基本迭代器interface称为XMLEvent,并且XMLEvent table中列出了每种事件类型的子interface。用于读取迭代器事件的主要分析器interface是XMLEventReader,而用于写入迭代器事件的主要interface是XMLEventWriterXMLEventReaderinterface包含五个方法,其中最重要的是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;
    // ...
}

迭代器事件类型

Event Type Description
StartDocument 报告一组 XML 事件的开始,包括编码,XML 版本和独立属性。
StartElement 报告元素的开始,包括所有属性和名称空间声明;还提供对前缀,名称空间 URI 和开始标记的本地名称的访问。
EndElement 报告元素的结束标签。如果已经在其对应的StartElement上显式设置了超出范围的命名空间,则可以在此处重新调用它们。
Characters 对应于 XML CData部分和CharacterData实体。请注意,可忽略的空白和显着的空白也被报告为Character事件。
EntityReference 字符实体可以报告为离散事件,然后应用程序开发人员可以选择解析或传递未解析事件。默认情况下,实体是解析的。或者,如果您不想将实体报告为事件,则可以替换替换文本并将其报告为Characters
ProcessingInstruction 报告基础处理指令的目标和数据。
Comment 返回 Comment 文本。
EndDocument 报告一组 XML 事件的结束。
DTD 报告与流相关的 DTD 信息(如果有的话),为java\.lang\.String,并提供一种返回 DTD 中的自定义对象的方法。
Attribute 通常将属性报告为StartElement事件的一部分。但是,有时需要返回一个独立的Attribute事件作为属性;例如,当XQueryXPath表达式的结果返回名称空间时。
Namespace 与属性一样,名称空间通常报告为StartElement的一部分,但是有时需要将名称空间报告为离散的Namespace事件。

请注意,仅当要处理的文档包含 DTD 时,才会创建DTDEntityDeclarationEntityReferenceNotationDeclarationProcessingInstruction事件。

事件 Map 示例

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

<?xml version="1.0"?>
<BookCatalogue xmlns="http://www.publishing.org">
    <Book>
        <Title>Yogasana Vijnana: the Science of Yoga</Title>
        <ISBN>81-40-34319-4</ISBN>
        <Cost currency="INR">11.50</Cost>
    </Book>
</BookCatalogue>

该文档将被解析为 18 个主要事件和次要事件,如下表所示。请注意,以大括号(\{\})显示的次要事件通常是从主要事件而不是直接访问的。

# Element/Attribute Event
1 version="1.0" StartDocument
2 isCData = false data = "\n" IsWhiteSpace = true Characters
3 qname = BookCatalogue:http://www.publishing.org attributes = null namespaces = {BookCatalogue" -> http://www.publishing.org"} StartElement
4 qname = Book attributes = null namespaces = null StartElement
5 qname = Title attributes = null namespaces = null StartElement
6 isCData = false data = "Yogasana Vijnana: the Science of Yoga\n\t" IsWhiteSpace = false Characters
7 qname = Title namespaces = null EndElement
8 qname = ISBN attributes = null namespaces = null StartElement
9 isCData = false data = "81-40-34319-4\n\t" IsWhiteSpace = false Characters
10 qname = ISBN namespaces = null EndElement
11 qname = Cost attributes = {"currency" -> INR} namespaces = null StartElement
12 isCData = false data = "11.50\n\t" IsWhiteSpace = false Characters
13 qname = Cost namespaces = null EndElement
14 isCData = false data = "\n" IsWhiteSpace = true Characters
15 qname = Book namespaces = null EndElement
16 isCData = false data = "\n" IsWhiteSpace = true Characters
17 qname = BookCatalogue:http://www.publishing.org namespaces = {BookCatalogue" -> http://www.publishing.org"} EndElement
18 EndDocument

此示例中有几件重要的事情要注意:

在游标和迭代器 API 之间进行选择

在这一点上合理地问:“我应该选择什么 API?我应该创建XMLStreamReaderXMLEventReader的实例吗?为什么仍然有两种 API?”

Development Goals

StAX 规范的作者针对三种类型的开发人员:

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

比较游标和迭代器 API

在游标和迭代器 API 之间进行选择之前,应该注意一些可以使用迭代器 API 进行,而不能使用游标 API 进行的事情:

同样,在做出选择时,请记住一些一般性建议:

首页