786.md 12.3 KB
Newer Older
W
init  
wizardforcel 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
# 使用 StAX

> 原文: [https://docs.oracle.com/javase/tutorial/jaxp/stax/using.html](https://docs.oracle.com/javase/tutorial/jaxp/stax/using.html)

通常,StAX 程序员使用 `XMLInputFactory``XMLOutputFactory``XMLEventFactory` 类创建 XML 流读取器,编写器和事件。通过在工厂上设置属性来完成配置,从而可以使用工厂上的 `setProperty` 方法将特定于实现的设置传递给底层实现。同样,可以使用 `getProperty` 工厂方法查询特定于实现的设置。

下面介绍 `XMLInputFactory``XMLOutputFactory``XMLEventFactory` 类,然后讨论资源分配,命名空间和属性管理,错误处理,最后阅读和使用游标和迭代器 API 编写流。

## StAX 工厂类

StAX 工厂类。 `XMLInputFactory``XMLOutputFactory``XMLEventFactory` ,让您定义和配置 XML 流阅读器,流编写器和事件类的实现实例。

### 的 XMLInputFactory

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

从[JGP]派生, `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 规范。

W
wizardforcel 已提交
29 30 31
`javax.xml.stream.XMLInputFactory` Properties 
 

W
wizardforcel 已提交
32
| 属性 | 描述 |
W
init  
wizardforcel 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
| :-- | :-- |
| `isValidating` | 打开特定于实现的验证。 |
| `是合并` | **(必需)**要求处理器合并相邻的字符数据。 |
| `isNamespaceAware` | 关闭名称空间支持。所有实现都必须支持名称空间。支持非命名空间感知文档是可选的。 |
| `isReplacingEntityReferences` | **(必需)**要求处理器用其替换值替换内部实体引用,并将它们报告为描述实体的字符或事件集。 |
| `isSupportingExternalEntities` | **(必填)**要求处理器解析外部解析的实体。 |
| `记者` | **(必需)**设置并获取 `XMLReporter` 接口的实现。 |
| `旋转变压器` | **(必需)**设置并获取 `XMLResolver` 接口的实现。 |
| `分配器` | **(必需)**设置并获取 `XMLEventAllocator` 接口的实现。 |

### XMLOutputFactory

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

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

### XMLEventFactory

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

`XMLEventFactory` 没有默认属性。

## 资源,命名空间和错误

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

### 资源分辨率

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

### 属性和命名空间

属性由 StAX 处理器使用游标界面中的查找方法和字符串以及迭代器接口中的`属性``命名空间`事件进行报告。请注意,命名空间被视为属性,尽管命名空间与游标和迭代器 API 中的属性分开报告。另请注意,对于 StAX 处理器,名称空间处理是可选的。有关命名空间绑定和可选命名空间处理的完整信息,请参阅 StAX 规范。

### 错误报告和异常处理

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

## 阅读 XML 流

如本课程前面所述,使用 StAX 处理器读取 XML 流的方式 - 更重要的是,您获得的内容 - 根据您使用的是 StAX 游标 API 还是事件迭代器 API 而有很大差异。以下两节介绍如何使用这些 API 读取 XML 流。

### 使用 XMLStreamReader

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

*   获取属性的值

*   阅读 XML 内容

*   确定元素是否包含内容或为空

*   获取对属性集合的索引访问权限

*   获取对命名空间集合的索引访问权限

*   获取当前事件的名称(如果适用)

*   获取当前事件的内容(如果适用)

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

### 读取属性,属性和命名空间

`XMLStreamReader.next` 方法加载流中下一个事件的属性。然后,您可以通过调用 `XMLStreamReader.getLocalName``XMLStreamReader.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 流的方法:

*   `next` :返回流中的下一个事件

*   `nextEvent` :返回下一个键入的 XMLEvent

*   `hasNext` :如果要在流中处理更多事件,则返回 true

*   `peek` :返回事件但不迭代到下一个事件

例如,以下代码片段说明了 `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` 方法创建的`迭代器`来读取命名空间。仅返回当前 `StartElement` 的命名空间,并且应用程序可以使用 `StartElement.getNamespaceContext` 获取当前命名空间上下文。

## 编写 XML 流

StAX 是一个双向 API,游标和事件迭代器 API 都有自己的一组用于编写 XML 流的接口。与用于读取流的接口一样,游标和事件迭代器的编写器 API 之间存在显着差异。以下部分描述了如何使用这些 API 编写 XML 流。

### 使用 XMLStreamWriter

StAX 游标 API 中的 `XMLStreamWriter` 接口允许应用程序写回 XML 流或创建全新的流。 XMLStreamWriter 有一些方法可以让你:

*   编写格式良好的 XML

*   冲洗或关闭输出

*   写限定名称

请注意, `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` ,直到在流中添加或遇到`属性``命名空间`以外的事件。这意味着当您将`属性``命名空间`添加到流时,它会附加到当前 `StartElement` 事件。

您可以使用`字符`方法转义`&amp;``&lt;``&gt;``“`

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