文档

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

使用StAX

一般来说,StAX程序员使用XMLInputFactoryXMLOutputFactoryXMLEventFactory类来创建XML流读取器、写入器和事件。通过在工厂上设置属性来进行配置,可以将实现特定的设置传递给底层实现,使用工厂上的setProperty方法。类似地,可以使用getProperty工厂方法查询实现特定的设置。

下面描述了XMLInputFactoryXMLOutputFactoryXMLEventFactory类,然后讨论资源分配、命名空间和属性管理、错误处理,最后使用游标和迭代器API读取和写入流。

StAX工厂类

StAX工厂类XMLInputFactoryXMLOutputFactoryXMLEventFactory允许您定义和配置XML流读取器、写入器和事件的实现实例。

XMLInputFactory

XMLInputFactory类允许您配置工厂创建的XML流读取器处理器的实现实例。通过调用newInstance方法来创建XMLInputFactory抽象类的新实例。然后使用静态方法XMLInputFactory.newInstance创建一个新的工厂实例。

继承自JAXP,XMLInputFactory.newInstance方法通过以下查找过程确定要加载的特定XMLInputFactory实现类:

  1. 使用javax.xml.stream.XMLInputFactory系统属性。

  2. 使用Java SE平台的Java运行时环境(JRE)目录中的lib/xml.stream.properties文件。

  3. 如果可用,使用Services API通过查找JRE可用的JAR文件中的META-INF/services/javax.xml.stream.XMLInputFactory文件确定类名。

  4. 使用平台默认的XMLInputFactory实例。

在获取到适当的XMLInputFactory引用之后,应用程序可以使用工厂来配置和创建流实例。下表列出了XMLInputFactory支持的属性。有关更详细的列表,请参阅StAX规范。

javax.xml.stream.XMLInputFactory 属性

属性

描述

isValidating

打开实现特定的验证。

isCoalescing

(必需) 要求处理器合并相邻的字符数据。

isNamespaceAware

关闭命名空间支持。所有实现都必须支持命名空间。对非命名空间感知文档的支持是可选的。

isReplacingEntityReferences

(必需) 要求处理器将内部实体引用替换为它们的替换值,并将它们报告为字符或描述实体的一组事件。

isSupportingExternalEntities

(必需) 要求处理器解析外部解析实体。

reporter

(必需) 设置和获取 XMLReporter 接口的实现。

resolver

(必需) 设置和获取 XMLResolver 接口的实现。

allocator

(必需) 设置和获取 XMLEventAllocator 接口的实现。

XMLOutputFactory

通过调用类的 newInstance 方法来创建抽象类 XMLOutputFactory 的新实例。然后使用静态方法 XMLOutputFactory.newInstance 创建一个新的工厂实例。获取实例的算法与 XMLInputFactory 相同,但是引用了 javax.xml.stream.XMLOutputFactory 系统属性。

XMLOutputFactory仅支持一个属性,javax.xml.stream.isRepairingNamespaces。此属性是必需的,其目的是创建默认前缀并将其与命名空间URI关联起来。有关更多信息,请参见StAX规范。

XMLEventFactory

通过调用类的newInstance方法来创建抽象类XMLEventFactory的新实例。然后使用静态方法XMLEventFactory.newInstance来创建新的工厂实例。此工厂引用javax.xml.stream.XMLEventFactory属性来实例化工厂。获取实例的算法与XMLInputFactoryXMLOutputFactory相同,但引用了javax.xml.stream.XMLEventFactory系统属性。

XMLEventFactory没有默认属性。

资源,命名空间和错误

StAX规范处理资源解析,属性和命名空间以及错误和异常,如下所述。

资源解析

XMLResolver接口提供了在XML处理期间解析资源的方法。应用程序在XMLInputFactory上设置接口,然后该工厂实例在创建的所有处理器上设置接口。

属性和命名空间

StAX处理器使用游标接口中的查找方法和字符串以及迭代器接口中的AttributeNamespace事件来报告属性。请注意,命名空间被视为属性,尽管在游标和迭代器API中,命名空间与属性分别报告。还要注意,对于StAX处理器来说,命名空间处理是可选的。有关命名空间绑定和可选命名空间处理的完整信息,请参见StAX规范。

错误报告和异常处理

所有致命错误都通过javax.xml.stream.XMLStreamException接口报告。所有非致命错误和警告都使用javax.xml.stream.XMLReporter接口报告。

读取XML流

正如本课程前面所述,使用StAX处理器读取XML流以及您得到的返回值,根据使用StAX游标API还是事件迭代器API而有很大的不同。以下两个部分描述了如何使用这些API之一读取XML流。

使用XMLStreamReader

在StAX游标API中,XMLStreamReader接口允许您只能以前向方式读取XML流或文档,每次只读取一个信息项。以下方法可用于从流中提取数据或跳过不需要的事件:

XMLStreamReader的实例在任何时候只有一个当前事件,其方法操作该事件。当您在流上创建XMLStreamReader实例时,初始当前事件是START_DOCUMENT状态。然后,可以使用XMLStreamReader.next方法前进到流中的下一个事件。

读取属性、属性和命名空间

XMLStreamReader.next方法加载流中下一个事件的属性。然后,您可以通过调用XMLStreamReader.getLocalNameXMLStreamReader.getText方法访问这些属性。

XMLStreamReader游标位于StartElement事件上时,它会读取事件的名称和任何属性,包括命名空间。可以使用索引值访问事件的所有属性,也可以通过命名空间URI和本地名称查找属性。但请注意,只有当前StartEvent上声明的命名空间可用;先前声明的命名空间不会被保留,重新声明的命名空间也不会被删除。

XMLStreamReader方法

XMLStreamReader提供以下方法来检索有关命名空间和属性的信息:

int getAttributeCount();
String getAttributeNamespace(int index);
String getAttributeLocalName(int index);
String getAttributePrefix(int index);
String getAttributeType(int index);
String getAttributeValue(int index);
String getAttributeValue(String namespaceUri, String localName);
boolean isAttributeSpecified(int index);

还可以使用另外三个方法访问命名空间:

int getNamespaceCount();
String getNamespacePrefix(int index);
String getNamespaceURI(int index);

实例化XMLStreamReader

此示例取自StAX规范,演示了如何实例化输入工厂、创建读取器并迭代XML流的元素:

XMLInputFactory f = XMLInputFactory.newInstance();
XMLStreamReader r = f.createXMLStreamReader( ... );
while(r.hasNext()) {
    r.next();
}

使用XMLEventReader

StAX事件迭代器API中的XMLEventReader API提供了将XML流中的事件映射到分配的事件对象的方法,这些对象可以自由重用,并且API本身可以扩展以处理自定义事件。

XMLEventReader提供了四种迭代解析XML流的方法:

例如,以下代码片段演示了XMLEventReader方法的声明:

package javax.xml.stream;
import java.util.Iterator;

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

要读取流中的所有事件并将它们打印出来,可以使用以下代码:

while(stream.hasNext()) {
    XMLEvent event = stream.nextEvent();
    System.out.print(event);
}

读取属性

您可以通过其关联的javax.xml.stream.StartElement访问属性,如下所示:

public interface StartElement extends XMLEvent {
    public Attribute getAttributeByName(QName name);
    public Iterator getAttributes();
}

您可以使用StartElement接口上的getAttributes方法,在该StartElement上使用Iterator来遍历所有声明的属性。

读取命名空间

类似于读取属性,可以通过调用StartElement接口上的getNamespaces方法来使用Iterator读取命名空间。只返回当前StartElement的命名空间,并且应用程序可以使用StartElement.getNamespaceContext获取当前的命名空间上下文。

编写XML流

StAX是一个双向API,光标和事件迭代器API都有自己的接口集来编写XML流。与用于读取流的接口一样,光标和事件迭代器的编写器API之间存在重要的差异。以下各节将介绍如何使用这些API编写XML流。

使用XMLStreamWriter

StAX游标API中的XMLStreamWriter接口允许应用程序向XML流写入数据,或创建全新的流。XMLStreamWriter具有以下方法:

请注意,XMLStreamWriter的实现不需要对输入执行格式良好性或有效性检查。某些实现可能会执行严格的错误检查,而其他实现可能不会。您实现的规则适用于XMLOutputFactory类中定义的属性。

writeCharacters方法用于转义字符,如&<>"。绑定前缀可以通过传递前缀的实际值、使用setPrefix方法或设置默认命名空间声明的属性来处理。

以下示例摘自StAX规范,展示了如何实例化一个输出工厂、创建一个写入器并写入XML输出:

XMLOutputFactory output = XMLOutputFactory.newInstance();
XMLStreamWriter writer = output.createXMLStreamWriter( ... );

writer.writeStartDocument();
writer.setPrefix("c","http://c");
writer.setDefaultNamespace("http://c");

writer.writeStartElement("http://c","a");
writer.writeAttribute("b","blah");
writer.writeNamespace("c","http://c");
writer.writeDefaultNamespace("http://c");

writer.setPrefix("d","http://c");
writer.writeEmptyElement("http://c","d");
writer.writeAttribute("http://c", "chris","fry");
writer.writeNamespace("d","http://c");
writer.writeCharacters("Jean Arp");
writer.writeEndElement();

writer.flush();

该代码生成以下XML(换行不是规范的):

<?xml version=’1.0’ encoding=’utf-8’?>
<a b="blah" xmlns:c="http://c" xmlns="http://c">
<d:d d:chris="fry" xmlns:d="http://c"/>Jean Arp</a>

使用XMLEventWriter

StAX事件迭代器API中的XMLEventWriter接口允许应用程序向XML流写入数据,或创建全新的流。该API可以扩展,但主要API如下:

public interface XMLEventWriter {
    public void flush() throws XMLStreamException;
    public void close() throws XMLStreamException;
    public void add(XMLEvent e) throws XMLStreamException;
    // ... other methods not shown.
}

XMLEventWriter的实例由XMLOutputFactory的实例创建。流事件会被迭代地添加,一旦添加到事件写入器实例后,事件就无法修改。

属性、转义字符、绑定前缀

StAX实现要求将最后一个StartElement缓冲,直到在流中添加或遇到除AttributeNamespace之外的事件。这意味着当您向流中添加AttributeNamespace时,它将附加到当前的StartElement事件。

您可以使用Characters方法转义字符,例如&<>"

可以使用setPrefix(...)方法显式绑定输出时使用的前缀,可以使用getPrefix(...)方法获取当前前缀。请注意,默认情况下,XMLEventWriter将命名空间绑定添加到其内部命名空间映射中。前缀在绑定它们的事件的相应EndElement之后失效。


上一页: StAX API
下一页: Oracle的流式XML解析器实现