`
chenlong_1988
  • 浏览: 183463 次
  • 性别: Icon_minigender_2
社区版块
存档分类

转载stax

阅读更多

使用 XML 的流 API (StAX)

下列部分描述了如何使用“XML 的流 API”解析和生成 XML 文档:

<!--[if !supportLists]-->§                         <!--[endif]-->XML 的流 API 概述

<!--[if !supportLists]-->§                         <!--[endif]-->使用 XMLStreamReader 接口解析 XML:典型步骤

<!--[if !supportLists]-->§                         <!--[endif]--> XMLStreamWriter 接口生成 XML:典型步骤

<!--[if !supportLists]-->§                         <!--[endif]--> XMLInputFactory 接口定义的属性

<!--[if !supportLists]-->§                         <!--[endif]--> XMLOutputFactory 接口定义的属性

 


XML 的流 API 概述

Java Community Processs JSR-173 指定的 XML的流 API (StAX) 提供了简单直观的解析和生成 XML 文档的方式。它与 SAX API 类似,但启用对 XML 文档的基于流的过程处理,而不要求您编写 SAX 事件处理程序;在使用复杂 XML 文档时,编写 SAX 事件处理程序将变得会非常复杂。换句话说,与 SAX 相比,StAX 提供了更多对解析的控制。

在程序使用 SAX 解析 XML 文档时,此程序必须创建在要解析的事件发生时对其进行监听的事件监听器,此程序必须响应事件,而不是请求特定事件。相比而言,如果使用 StAX,则可以有系统地逐步解析 XML 文档,请求某些事件类型(如元素的开始)、迭代元素的特性、跳到文档开头、随时停止处理、获取特定元素的子元素并根据需要筛选掉元素。由于是在请求事件而非响应事件,因此常将使用 StAX 称为“pull parsing”

StAX 包含两个 API游标 API”事件迭代器 API”,它们中的任一个都可以用于读取和写入 XML。下列部分描述了各个 API 及它们的强项。

游标 API 的描述

通过游标 API 的基本功能,编程人员能够以最轻松且有效方式来解析和生成 XML。对于 StAX 两个 API 而言,大多数编程人员乐意使用此 API

游标 API 可在一组事件(例如开始元素、注释和特性)中迭代,即使可能并未实现这些事件。游标 API 具有两个主要接口:用于解析 XML XMLStreamReader,以及用于生成 XML XMLStreamWriter

XMLStreamReader 接口

游标 API 使用 XMLStreamReader 接口在 XML 文档上移动虚拟游标,并允许通过调用 hasNext()next()getEventType() getText() 之类的方法调用访问数据和底层状态。XMLStreamReader 接口只允许以向前和只读方式访问 XML

可使用 XMLInputFactory 类新建 XMLStreamReader 的实例。在获取新读取器时,您可以设置各种属性;有关详情信息,请参阅 XMLInputFactory 接口定义的属性

在使用 XMLStreamReader 接口的 next() 方法解析 XML 时,读取器可获取下一个解析事件,并返回一个整数(此整数可标识刚读取的事件的类型)。解析与 XML 文档的部分相对应的事件,如 XML 声明、开始和结束元素标记、字符数据、空格、注释和处理指令。XMLStreamConstant 接口可指定 next() 方法返回的整数所对应的事件。还可以使用 XMLStreamReader getEventType() 方法来确定事件类型。

XMLStreamReader 接口具有很多获取 XML 文档中特定数据的方法。其中的某些方法包括:

<!--[if !supportLists]-->§                         <!--[endif]-->getLocalName() - 返回当前事件的本地名称。

<!--[if !supportLists]-->§                         <!--[endif]-->getPrefix() - 返回当前事件的前缀。

<!--[if !supportLists]-->§                         <!--[endif]-->getAttributeXXX() - 返回有关当前特性事件的信息的一组方法。

<!--[if !supportLists]-->§                         <!--[endif]-->getNamespaceXXX() - 返回有关当前名称空间事件的信息的一组方法。

<!--[if !supportLists]-->§                         <!--[endif]-->getTextXXX() - 返回有关当前文本事件的信息的一组方法。

<!--[if !supportLists]-->§                         <!--[endif]-->getPIData() - 返回当前处理的指令事件的数据部分。

对于每种事件类型而言,只有某些方法是有效的;如果您尝试对无效事件类型调用方法,StAX 处理器将引发 java.lang.IllegalStateException。例如,尝试对名称空间事件调用 getAttributeXXX() 方法是错误的。有关完整事件列表及其有效 XMLStreamReader 方法的信息,请参阅 StAX specification

XMLStreamWriter 接口

游标 API 使用 XMLStreamWriter 接口指定如何生成 XML

可使用 XMLOutputFactory 类新建 XMLStreamWriter 的实例。在获取新编写器时,可以设置用于修复名称空间和前缀的属性;有关详情信息,请参阅 XMLOutputFactory 接口定义的属性

XMLStreamWriter 接口定义了一组 writeXXX() 方法来写入 XML 文档的标准部分,例如:

<!--[if !supportLists]-->§                         <!--[endif]-->writeStartElement()

<!--[if !supportLists]-->§                         <!--[endif]-->writeEndDocument()

<!--[if !supportLists]-->§                         <!--[endif]-->writeAttribute()

<!--[if !supportLists]-->§                         <!--[endif]-->writeNamespace()

<!--[if !supportLists]-->§                         <!--[endif]-->writeCData()

必须使用这些方法,显式写入 XML 文档的每个部分(包括特性和命名空间)。

可使用 flush() 方法将任何缓存数据写入输出,使用 close() 方法关闭编写器,并释放所有资源。

在生成 XML 时,XMLStreamWriter 不检查生成文档的格式是否标准;创建标准格式的 XML 文档是编程人员的职责。要打印特殊字符 &< >,请使用 writeCharacters() 方法。

事件迭代器 API 的描述

事件迭代器 API 是位于游标 API 顶端的层。它易于扩展并简化了管道操作。管道操作指多个 XML XML 的转换。通过使用事件迭代器 API,编程人员无需在管道的每个阶段除序列化和序列化 XML;而是只需在管道的每个末尾处执行操作,并使用 API 方法(如 nextEvent())在中间阶段进行通信。事件迭代器 API 具有两个主要接口:用于解析 XML XMLEventReader,以及用于生成 XML XMLEventWriter

由于游标 API StAX 中最常用的 API,故本部分不再详细描述事件迭代器 API 的用法,只显示一个示例。有关使用此 API 的详细信息,请参阅 StAX specification

以下示例显示了一个简单程序,此程序使用 StAX XMLEventReader 接口解析 XML 文档。此程序采用单个参数,即一个 XML 文件,并使用此参数创建 XMLEventReader 对象。程序然后使用此读取器迭代事件流,并进行打印。

package examples.event;

import java.io.FileReader;
import javax.xml.stream.*;
import javax.xml.stream.events.*;
import javax.xml.stream.util.*;
import javax.xml.namespace.QName;

/**
 *
迭代事件的简单示例
 *
 * @
作者版权所有 (c) 2002 BEA System。保留所有权利。
*/

public class Parse {
  private static String filename = null;

  private static void printUsage() {
    System.out.println("usage: java examples.event.Parse <xmlfile>");
  }

  public static void main(String[] args) throws Exception {
    try {
      filename = args[0];
    } catch (ArrayIndexOutOfBoundsException aioobe){
      printUsage();
      System.exit(0);
    }

    XMLInputFactory factory = XMLInputFactory.newInstance();
    XMLEventReader r =
      factory.createXMLEventReader(new FileReader(filename));
    while(r.hasNext()) {
      XMLEvent e = r.nextEvent();
      System.out.println("ID:"+e.hashCode()+"["+e+"]");
    }
  }
}

StAX 的主要接口和类

下表描述了 XML 的流 API 的主要接口和类。

4-1 XML 的流 API 的主要接口和类

接口或类

用于游标 API 还是事件迭代 API

描述

XMLInputFactory class

二者

用于创建 XMLStreamReader XMLEventReader 实例的工厂类。

XMLOutputFactory class

二者

用于创建 XMLStreamWriter XMLEventWriter 实例的工厂类。

XMLEventFactory class

事件迭代器

用于创建 XMLEvent 实例的工厂类。

XMLStreamReader interface

游标

用于解析 XML 文档的接口。通过此接口,可以查看下一个事件、获取下一个事件和检查更多事件。

XMLStreamWriter interface

游标

用于生成 XML 文档的接口。它提供了一组 writeXXX() 方法,用于生成 XML 文档的特定部分,如开始元素和特性等。

XMLEventReader interface

事件迭代器

用于解析 XML 事件的接口。通过此接口,可以查看下一个事件、获取下一个事件和检查更多事件。

XMLEventWriter interface

事件迭代器

用于生成 XML 的接口。它可使用 add() 方法将 XMLEvent 添加到输出流。

XMLEvent

事件迭代器

用于处理事件的基本接口。从 XMLEvent 扩展的所有特定 XML 事件,如 StartElement Attribute 等。

XMLStreamException exception

二者

意外处理错误的基异常,如缺少标准格式的 XML 文档结构。

 


使用 XMLStreamReader 接口解析 XML:典型步骤

以下过程描述了使用 StAX 游标 API XMLStreamReader 接口解析 XML 文档的典型步骤。此过程在其描述中使用了使用 StAX 解析 XML 的示例中的示例。

<!--[if !supportLists]-->1.          <!--[endif]-->导入 javax.xml.stream.* 类。

<!--[if !supportLists]-->2.          <!--[endif]-->可使用 XMLInputFactory.newInstance() 方法实例化 XMLInputFactory,如以下代码摘录所示:

XMLInputFactory xmlif = XMLInputFactory.newInstance();

有关可以设置的属性列表的信息,请参阅 XMLInputFactory 接口定义的属性

<!--[if !supportLists]-->3.          <!--[endif]-->可使用 XMLInputFactory.createXMLStreamReader() 方法实例化基于 XML 文档的 XMLStreamReader 对象。

有关详细信息,请参阅获取 XMLStreamReader 对象

<!--[if !supportLists]-->4.          <!--[endif]-->可使用 hasNext() next() 方法逐一查看 XML 事件,以解析 XML 文档,如以下代码摘录所示:

while(xmlr.hasNext()){
      printEvent(xmlr);
      xmlr.next();

在此示例中,xmlr XMLStreamReader 实例,本地 printEvent() 方法(不属于 StAX API)用于确定特定事件类型,如下一步中所述。

<!--[if !supportLists]-->5.          <!--[endif]-->在解析 XML 文档期间,确定当前的特定事件类型并采取相应的操作。事件类型包括 XML 文档的开始和结束、XML 元素的开始和结束、注释和实体引用等。

请参阅确定特定 XML 事件类型

<!--[if !supportLists]-->6.          <!--[endif]-->如果当前事件类型是开始元素或结束元素,则可根据需要获取其特性。

请参阅获取元素的特性

<!--[if !supportLists]-->7.          <!--[endif]-->如果当前事件类型是开始元素或结束元素,则可根据需要获取其名称空间。

请参阅获取元素的名称空间

<!--[if !supportLists]-->8.          <!--[endif]-->如果当前事件类型包含文本数据,如 CDATA 或注释,则可根据需要获取实际数据。

请参阅获取文本数据

<!--[if !supportLists]-->9.          <!--[endif]-->可根据需要获取位置信息,如当前事件的行号或列号。

请参阅获取位置信息

<!--[if !supportLists]-->10.      <!--[endif]-->关闭流。

请参阅关闭输入流

使用 StAX 解析 XML 的示例

以下示例显示了一个简单程序,此程序使用 StAX XMLStreamReader 接口解析 XML 文档。

此程序采用单个参数,即一个 XML 文件,并使用此参数创建 XMLStreamReader 对象。此程序然后使用读取器迭代事件流,确定每个事件的类型,如 XML 元素的开始、元素的特性列表和处理指令等。此程序可打印出有关这些事件的信息,在适当时使用内部方法打印出特性列表和名称空间列表。

稍后各部分将描述用粗体显示的代码。

package examples.basic;

import java.io.FileReader;
import java.util.Iterator;
import javax.xml.stream.*;
import javax.xml.namespace.QName;

/**
 *
这个简单示例
 *
演示了 XMLStreamReader 类。
*
 *
作者版权所有 (c) 2003 BEA Systems。保留所有权利。
*/

public class Parse {
  private static String filename = null;

  private static void printUsage() {
    System.out.println("usage: java examples.basic.Parse <xmlfile>");
  }

  public static void main(String[] args) throws Exception {
    try {
      filename = args[0];
    } catch (ArrayIndexOutOfBoundsException aioobe){
      printUsage();
      System.exit(0);
    }

    //
    //
获取输入工厂
    //
    XMLInputFactory xmlif = XMLInputFactory.newInstance();
    System.out.println("FACTORY: " + xmlif);

    //
    //
实例化读取器
    //
    XMLStreamReader xmlr = xmlif.createXMLStreamReader(new FileReader(filename));
    System.out.println("READER:  " + xmlr + "\n");

    //
    //
解析 XML
    //
    while(xmlr.hasNext()){
      printEvent(xmlr);
      xmlr.next();
    }

    //
    //
关闭读取器
    //
    xmlr.close();

  }

  private static void printEvent(XMLStreamReader xmlr) {

    System.out.print("EVENT:["+xmlr.getLocation().getLineNumber()+"]["+
                     xmlr.getLocation().getColumnNumber()+"] ");

    System.out.print(" [");

    switch (xmlr.getEventType()) {

    case XMLStreamConstants.START_ELEMENT:
      System.out.print("<");
      printName(xmlr);
      printNamespaces(xmlr);
      printAttributes(xmlr);
      System.out.print(">");
      break;

    case XMLStreamConstants.END_ELEMENT:
      System.out.print("</");
      printName(xmlr);
      System.out.print(">");
      break;

    case XMLStreamConstants.SPACE:

    case XMLStreamConstants.CHARACTERS:
      int start = xmlr.getTextStart();
      int length = xmlr.getTextLength();
      System.out.print(new String(xmlr.getTextCharacters(),
                                  start,
                                  length));
      break;

    case XMLStreamConstants.PROCESSING_INSTRUCTION:
      System.out.print("<?");
      if (xmlr.hasText())
        System.out.print(xmlr.getText());
      System.out.print("?>");
      break;

    case XMLStreamConstants.CDATA:
      System.out.print("<![CDATA[");
      start = xmlr.getTextStart();
      length = xmlr.getTextLength();
      System.out.print(new String(xmlr.getTextCharacters(),
                                  start,
                                  length));
      System.out.print("]]>");
      break;

    case XMLStreamConstants.COMMENT:
      System.out.print("<!--");
      if (xmlr.hasText())
        System.out.print(xmlr.getText());
      System.out.print("-->");
      break;

    case XMLStreamConstants.ENTITY_REFERENCE:
      System.out.print(xmlr.getLocalName()+"=");
      if (xmlr.hasText())
        System.out.print("["+xmlr.getText()+"]");
      break;

    case XMLStreamConstants.START_DOCUMENT:
      System.out.print("<?xml");
      System.out.print(" version='"+xmlr.getVersion()+"'");
      System.out.print(" encoding='"+xmlr.getCharacterEncodingScheme()+"'");
      if (xmlr.isStandalone())
        System.out.print(" standalone='yes'");
      else
        System.out.print(" standalone='no'");
      System.out.print("?>");
      break;

    }
    System.out.println("]");
  }

  private static void printName(XMLStreamReader xmlr){
    if(xmlr.hasName()){
      String prefix = xmlr.getPrefix();
      String uri = xmlr.getNamespaceURI();
      String localName = xmlr.getLocalName();
      printName(prefix,uri,localName);
    }
  }

  private static void printName(String prefix,
                                String uri,
                                String localName) {
    if (uri != null && !("".equals(uri)) ) System.out.print("['"+uri+"']:");
    if (prefix != null) System.out.print(prefix+":");
    if (localName != null) System.out.print(localName);
  }

  private static void printAttributes(XMLStreamReader xmlr){
    for (int i=0; i < xmlr.getAttributeCount(); i++) {
      printAttribute(xmlr,i);
    }
  }

  private static void printAttribute(XMLStreamReader xmlr, int index) {
    String prefix = xmlr.getAttributePrefix(index);
    String namespace = xmlr.getAttributeNamespace(index);
    String localName = xmlr.getAttributeLocalName(index);
    String value = xmlr.getAttributeValue(index);
    System.out.print(" ");
    printName(prefix,namespace,localName);
    System.out.print("='"+value+"'");
  }

  private static void printNamespaces(XMLStreamReader xmlr){
    for (int i=0; i < xmlr.getNamespaceCount(); i++) {
      printNamespace(xmlr,i);
    }
  }

  private static void printNamespace(XMLStreamReader xmlr, int index) {
    String prefix = xmlr.getNamespacePrefix(index);
    String uri = xmlr.getNamespaceURI(index);
    System.out.print(" ");
    if (prefix == null)
      System.out.print("xmlns='"+uri+"'");
    else
      System.out.print("xmlns:"+prefix+"='"+uri+"'");
  }
}

获取 XMLStreamReader 对象

可使用 XMLInputFactory.createXMLStreamReader() 方法实例化基于 XML 文档的 XMLStreamReader 对象,如以下代码摘录所示:

XMLStreamReader xmlr = xmlif.createXMLStreamReader(new FileReader(filename));

在此示例中,xmlif XMLInputFactory 实例。

createXMLStreamReader() 方法的各种签名允许将下列 XML 文档格式作为参数:

<!--[if !supportLists]-->§                         <!--[endif]-->java.io.InputStream

<!--[if !supportLists]-->§                         <!--[endif]-->java.io.Reader(如示例所示)

<!--[if !supportLists]-->§                         <!--[endif]-->javax.xml.transform.Source(在 JAXP API 中指定)

确定特定 XML 事件类型

要在解析 XML 文档时确定特定事件类型,请使用 XMLStreamReader.next() XMLStreamReader.getEventType() 方法。next() 方法可读取下一个事件,并返回一个整数(此整数可标识所读取的事件类型);getEventType() 方法只返回标识当前事件类型的整数。XMLStreamReader XMLStreamConstants 超接口可定义事件类型常量,如以下列表所示:

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.ATTRIBUTE

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.CDATA

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.CHARACTERS

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.COMMENT

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.DTD

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.END_DOCUMENT

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.END_ELEMENT

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.ENTITY_DECLARATION

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.ENTITY_REFERENCE

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.NAMESPACE

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.NOTATION_DECLARATION

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.PROCESSING_INSTRUCTION

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.SPACE

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.START_DOCUMENT

<!--[if !supportLists]-->§                         <!--[endif]-->XMLStreamConstants.START_ELEMENT

以下示例显示了如何使用 Java case 语句来确定 XMLStreamReader.next() 方法返回的特定事件类型。此示例使用 XMLStreamReader.getEventType() 方法确定由 next() 方法返回的当前事件的整数事件类型。为了简化起见,此示例仅打印已找到的事件,后面的部分显示事件的进一步处理。

switch (xmlr.getEventType()) {

case XMLStreamConstants.START_ELEMENT:
  System.out.print("Start Element\n");
  break;

case XMLStreamConstants.END_ELEMENT:
  System.out.print("End Element\n");
  break;

case XMLStreamConstants.SPACE:
  System.out.print("Space\n");
  break;

case XMLStreamConstants.CHARACTERS:
  System.out.print("Characters\n");
  break;

case XMLStreamConstants.PROCESSING_INSTRUCTION:
  System.out.print("Processing Instrcutions\n");
  break;

case XMLStreamConstants.CDATA:
  System.out.print("CDATA\n");
  break;

case XMLStreamConstants.COMMENT:
  System.out.print("Comment\n");
  break;

case XMLStreamConstants.DTD:
  System.out.print("DTD\n");
  break;

case XMLStreamConstants.ENTITY_REFERENCE:
  System.out.print("Entity Reference\n");
  break;

case XMLStreamConstants.ENTITY_DECLARATION:
  System.out.print("Entity Declaration\n");
  break;

case XMLStreamConstants.START_DOCUMENT:
  System.out.print("Start Document\n");
  break;

case XMLStreamConstants.END_DOCUMENT:
  System.out.print("End Document\n");
  break;

}

获取元素的全名

元素的全名包含其前缀、名称空间 URI 和本地名称;一旦确定了当前事件是开始元素还是结束元素,就可以分别使用 XMLStreamReader 接口的 getPrefix()getNamespaceURI() getLocalName() 方法获取此信息。

例如,假定在此示例程序中开始元素事件的 case 语句如下所示:

case XMLStreamConstants.START_ELEMENT:

  System.out.print("<");
  printName(xmlr);
  printNamespaces(xmlr);
  printAttributes(xmlr);
  System.out.print(">");
  break;

注意:

printNamespaces() printAttributes() 方法将在其他部分中讨论。

两个本地 printName() 方法可使用 getXXX() 方法,如下:

private static void printName(XMLStreamReader xmlr){
  if(xmlr.hasName()){
    String prefix = xmlr.getPrefix();
    String uri = xmlr.getNamespaceURI();
    String localName = xmlr.getLocalName();
    printName(prefix,uri,localName);
  }
}

private static void printName(String prefix,
                              String uri,
                              String localName) {
  if (uri != null && !("".equals(uri)) ) System.out.print("['"+uri+"']:");
  if (prefix != null) System.out.print(prefix+":");
  if (localName != null) System.out.print(localName);
}

获取元素的特性

一旦确定了当前事件是开始元素、结束元素还是特性,就可以使用 XMLStreamReader 接口的 getAttributeXXX() 方法获取特性的列表及其值。

警告:

只能将 getAttributeXXX() 方法用于开始元素、结束元素和特性事件;如果尝试在其他任何事件类型上执行这些方法,将引发 java.lang.IllegalStateException

可使用 getAttributeCount() 方法返回当前元素的特性数目,并在迭代特性列表的循环中使用此计数。此方法的计数中不包含名称空间。其他 getAttributeXXX() 方法可返回特定特性的前缀、名称空间 URI、本地名称和值。

例如,假定此示例程序的开始元素事件的 case 语句如下所示:

case XMLStreamConstants.START_ELEMENT:

  System.out.print("<");
  printName(xmlr);
  printNamespaces(xmlr);
  printAttributes(xmlr);
  System.out.print(">");
  break;

注意:

printName() printNamespaces() 方法将在其他部分中讨论。

以下本地 printAttributes() 方法显示了一种迭代特性列表的方法;由于特性索引基于零,因此 for 循环将从 0 开始:

private static void printAttributes(XMLStreamReader xmlr){

  for (int i=0; i < xmlr.getAttributeCount(); i++) {
    printAttribute(xmlr,i);
  }
}

以下本地 printAttribute() 方法显示了如何打印出特定特性的所有信息:

private static void printAttribute(XMLStreamReader xmlr, int index) {
  String prefix = xmlr.getAttributePrefix(index);
  String namespace = xmlr.getAttributeNamespace(index);
  String localName = xmlr.getAttributeLocalName(index);
  String value = xmlr.getAttributeValue(index);
  System.out.print(" ");
  printName(prefix,namespace,localName);
  System.out.print("='"+value+"'");
}

printName() 方法在获取元素的全名中描述。

获取元素的名称空间

一旦确定了当前事件是开始元素、结束元素还是名称空间,就可以使用 XMLStreamReader 接口的 getNamespaceXXX() 方法获取为事件声明的名称空间的列表。

警告:

只能将 getNamespaceXXX() 方法用于开始元素、结束元素和名称空间事件;如果尝试在其他任何事件类型上执行这些方法,将引发 java.lang.IllegalStateException

可使用 getNamespaceCount() 方法返回为当前事件声明的名称空间数目,并在迭代列表的循环中使用此计数。如果当前事件是结束元素,此计数则指将要超出范围的名称空间的数目。其他 getNamespaceXXX() 方法可返回特定名称空间的前缀和名称空间 URI

例如,假定此示例程序的开始元素事件的 case 语句如下所示:

case XMLStreamConstants.START_ELEMENT:

  System.out.print("<");
  printName(xmlr);
  printNamespaces(xmlr);
  printAttributes(xmlr);
  System.out.print(">");
  break;

注意:

printName() printAttributes() 方法将在其他部分中讨论。

以下本地 printNamespaces() 方法显示一种迭代开始元素名称空间列表的方法;由于名称空间索引基于零,故 for 循环从 0 开始:

private static void printNamespaces(XMLStreamReader xmlr){
  for (int i=0; i < xmlr.getNamespaceCount(); i++) {
    printNamespace(xmlr,i);
  }
}

以下的本地 printNamespace() 方法显示如何打印特定名称空间的所有信息:

private static void printNamespace(XMLStreamReader xmlr, int index) {
  String prefix = xmlr.getNamespacePrefix(index);
  String uri = xmlr.getNamespaceURI(index);
  System.out.print(" ");
  if (prefix == null)
    System.out.print("xmlns='"+uri+"'");
  else
    System.out.print("xmlns:"+prefix+"='"+uri+"'");
}

getNamespacePrefix() 方法为默认名称空间声明返回 null

获取文本数据

XMLStreamReader 接口包含各种 getTextXXX() 方法,以便从注释和 CDATA 之类的事件获取文本数据。

使用 getTextStart() 方法获取存储当前文本事件第一个字符的文本字符数组的偏移量。使用 getTextLength() 方法获取文本字符数组中字符序列的长度。最后,使用 getTextCharacters() 方法返回当前事件的字符数组。字符数组仅包含有关当前事件的文本信息,一旦调用 next() 方法读取输入流的下一个事件,字符数组将用新信息来填写。

以下示例显示如何为 CDATA 事件打印文本数据:

case XMLStreamConstants.CDATA:
  System.out.print("<![CDATA[");
  start = xmlr.getTextStart();
  length = xmlr.getTextLength();
  System.out.print(new String(xmlr.getTextCharacters(),
                              start,
                              length));
  System.out.print("]]>");
  break;

如果首先要检查字符事件实际上具有文本,请使用 hasText() 方法,如以下示例所示:

case XMLStreamConstants.COMMENT:
  System.out.print("<!--");
  if (xmlr.hasText())
    System.out.print(xmlr.getText());
  System.out.print("-->");
  break;

获取位置信息

StAX API Location 接口提供了获取事件位置信息的方法,如行号或列号,以及正在解析的 XML 的公共 ID 和系统 ID。使用 XMLStreamReader 接口的 getLocation() 方法返回当前事件的 Location 对象,如以下示例所示:

System.out.print("EVENT:["+xmlr.getLocation().getLineNumber()+"]["+
                     xmlr.getLocation().getColumnNumber()+"] ");

关闭输入流

在完成使用后,明确关闭 XMLStreamReader 是一个良好的编程实践,这样做可以释放资源。要关闭读取器,请使用 XMLStreamReader.close() 方法,如以下示例所示:

//
//
关闭读取器
//
xmlr.close();

 


XMLStreamWriter 接口生成 XML:典型步骤

下列过程描述使用 StAX 游标 API XMLStreamWriter 接口生成新 XML 文档的典型步骤。

<!--[if !supportLists]-->1.          <!--[endif]-->导入 javax.xml.stream.* 类。

<!--[if !supportLists]-->2.          <!--[endif]-->使用 XMLOutputFactory.newInstance() 方法来实例化 XMLOutputFactory,如下列代码摘录所示:

XMLOutputFactory xmlof = XMLOutputFactory.newInstance();

有关可以设置的属性列表的信息,请参阅 XMLOutputFactory 接口定义的属性

<!--[if !supportLists]-->3.          <!--[endif]-->使用 XMLOutputFactory.createXMLStreamWriter() 方法实例化 XMLStreamWriter 对象,为其传送文件名或将包含 XML 的对象。

有关详细信息,请参阅获取 XMLStreamWriter 对象

<!--[if !supportLists]-->4.          <!--[endif]--> XML 声明添加到输出。 XML 声明添加到输出流

<!--[if !supportLists]-->5.          <!--[endif]-->将标准 XML 对象,如开始元素、注释和字符添加到输出。请参阅将标准 XML 事件添加到输出流

<!--[if !supportLists]-->6.          <!--[endif]-->将特性和名称空间声明添加到开始元素。请参阅将特性和名称空间声明添加到开始元素

<!--[if !supportLists]-->7.          <!--[endif]-->关闭输出流。请参阅关闭输出流

使用 StAX 生成 XML 的示例

以下示例显示一个简单程序,此程序使用 StAX XMLStreamWriter 接口生成 XML 文档。

程序首先创建 XMLStreamWriter 的实例,指定将输出写入当前目录的 outFile.xml 文件。然后使用各种 writeXXX() 方法生成如下的 XML 文件:

<?xml version='1.0' encoding='utf-8'?>

<!-- 这是注释 -->
<person xmlns:one="http://namespaceOne" gender="f">
    <one:name hair="pigtails" freckles="yes">Pippi Longstocking</one:name>
</person>

XMLStreamWriter 接口并不检查 XML 文档的格式是否标准,确保格式的标准(例如每个开始元素都有一个相应的结束元素等)是编程人员的职责。此示例还显示如何使用 writeCharacters("\n") 方法,将新行添加到输出,以便使写入文本文件时 XML 的可读性更好。

稍后各节将描述以粗体显示的代码。

package examples.basic;

import java.io.FileOutputStream;
import java.util.Iterator;
import javax.xml.stream.*;
import javax.xml.namespace.QName;

/**
 *
此简单示例说明如何
 *
使用 XMLStreamWriter 类生成 XML
*
 *
生成的 XML 文件如下所示:
 *
 *   <?xml version='1.0' encoding='utf-8'?>
*
 *   <!--
这是注释 -->
 *   <person xmlns:one="http://namespaceOne" gender="f">
 *       <one:name hair="pigtails" freckles="yes">Pippi Longstocking</one:name>
 *   </person>
 *
 *
 * @
作者版权所有 (c) 2003 BEA Systems。保留所有权利。
*/

public class Generate {

  public static void main(String args[]) throws Exception {

    //
    //
获取输出工厂
    //
    XMLOutputFactory xmlof = XMLOutputFactory.newInstance();
    System.out.println("FACTORY: " + xmlof);

    //
    //
实例化编写器
    //
    XMLStreamWriter xmlw = xmlof.createXMLStreamWriter(new FileOutputStream ("outFile.xml"));
    System.out.println("READER:  " + xmlw + "\n");

    //
    //
生成 XML
    //

    // 编写默认的 XML 声明
    xmlw.writeStartDocument();
    xmlw.writeCharacters("\n");
    xmlw.writeCharacters("\n");

    // 编写注释
    xmlw.writeComment("this is a comment");
    xmlw.writeCharacters("\n");

    // 编写有一个“gender”特性的根元素“person”
    xmlw.writeStartElement("person");
    xmlw.writeNamespace("one", "http://namespaceOne");
    xmlw.writeAttribute("gender","f");
    xmlw.writeCharacters("\n");

    // 编写有某些内容和两个特性的“name”元素
    xmlw.writeCharacters("    ");
    xmlw.writeStartElement("one", "name", "http://namespaceOne");
    xmlw.writeAttribute("hair","pigtails");
    xmlw.writeAttribute("freckles","yes");
    xmlw.writeCharacters("Pippi Longstocking");

    // 结束“name”元素
    xmlw.writeEndElement();
    xmlw.writeCharacters("\n");

    // 结束“person”元素
    xmlw.writeEndElement();

    // 结束 XML 文档
    xmlw.writeEndDocument();

    // 关闭 XMLStreamWriter 以释放资源
    xmlw.close();

  }

}

获取 XMLStreamWriter 对象

使用 XMLOutputFactory.createXMLStreamWriter() 方法来实例化来实例化基于 XML 文档的 XMLStreamWriter 对象,如下列代码摘录所示:

XMLStreamWriter xmlw = xmlof.createXMLStreamWriter(new FileOutputStream ("outFile.xml"));

在本例中,xmlof XMLOutputFactory 实例。

createXMLStreamWriter() 方法的各种签名允许将下列 XML 文档格式作为参数:

<!--[if !supportLists]-->§                         <!--[endif]-->java.io.OutputStream (如示例所示)

<!--[if !supportLists]-->§                         <!--[endif]-->java.io.Writer

<!--[if !supportLists]-->§                         <!--[endif]-->javax.xml.transform.Result(在 JAXP API 中指定)

XML 声明添加到输出流

可使用 XMLStreamWriter.writeStartDocument() 方法,将 XML 声明作为 XML 文档的第一行进行添加,如以下代码摘录所示:

xmlw.writeStartDocument();

此方法没有任何参数,可写入默认 XML 声明:

<?xml version='1.0' encoding='utf-8'?>

如果要指定不同编码或 XML 版本,请使用 writeStartDocument() 方法的下列特性:

<!--[if !supportLists]-->§                         <!--[endif]-->writeStartDocument(java.lang.String version)

<!--[if !supportLists]-->§                         <!--[endif]-->writeStartDocument(java.lang.String encoding, java.lang.String version)

通过 writeStartDocument() 方法设置编码并不会设置底层输出的实际编码;它仅指定为 XML 声明的 encoding 特性写入的值。要实际设置输出的编码,必须在使用相应的 XMLOutputFactory.createXMLStreamWriter() 方法创建 XMLStreamWriter 实例时指定 encoding 参数。

将标准 XML 事件添加到输出流

可使用 XMLStreamWriter.writeXXX() 方法,将标准 XML 事件,如开始元素、结束元素、注释、CDATA 和实体引用等添加到输出流。XXX 指特定的事件,如 writeStartElement()writeEndElement()writeComment() writeCData() 等。可通过将名称和文本数据作为一个 String 进行传送来创建大多数元素。

XMLStreamWriter 接口不会验证数据,也不检查文档格式是否标准,确保格式标准(例如每个开始元素都有一个相应的结束元素等)是编程人员的职责。编程人员还需要确保开始和结束元素事件嵌套的正确性。要在写入文本文件时使输出的 XML 更便于人员阅读,请使用 writeCharacters("\n") 方法在适当的位置添加新的行。

例如,假定要创建下列 XML 段:

<!-- 这是注释 -->
<name>Jane Doe</name>

将此元素添加到输出流的 Java 代码如下:

xmlw.writeComment("This is a comment");
xmlw.writeCharacters("\n");

xmlw.writeStartElement("name");
xmlw.writeCharacters("Jane Doe");
xmlw.writeEndElement();
xmlw.writeCharacters("\n");

将特性和名称空间声明添加到开始元素

可紧随开始元素事件使用 writeAttribute() 方法将特性添加到开始元素。可以为特性指定前缀及其绑定到的 URI,或不指定任何前缀。

例如,假定要创建下列 XML 段:

<person gender="f">

生成此 XML Java 代码如下:

xmlw.writeStartElement("person");
xmlw.writeAttribute("gender","f");
xmlw.writeCharacters("\n");

可使用 writeNamespace() 方法将名称空间写入输出流。编程人员负责确保当前事件(例如开始元素)允许名称空间的写入;如果当前事件不允许名称空间的写入,将引发 javax.xml.stream.XMLStreamException。可使用其他 writeXXX() 方法的相应特性指定事件的前缀及其绑定到的 URI

例如,下列 XML 输出显示了 <person> 元素的名称空间声明,以及为 <one> 子元素指定的 one 前缀:

<person xmlns:one="http://namespaceOne" gender="f">
    <one:name hair="pigtails" freckles="yes">Pippi Longstocking</one:name>
</person>

生成此 XML Java 代码如下:

    // 编写有一个“gender”特性的根元素“person”
    xmlw.writeStartElement("person");
    xmlw.writeNamespace("one", "http://namespaceOne");
    xmlw.writeAttribute("gender","f");
    xmlw.writeCharacters("\n");

    // 编写有某些内容和两个特性的“name”元素
    xmlw.writeCharacters("    ");
    xmlw.writeStartElement("one", "name", "http://namespaceOne");
    xmlw.writeAttribute("hair","pigtails");
    xmlw.writeAttribute("freckles","yes");
    xmlw.writeCharacters("Pippi Longstocking");

    // 结束“name”元素
    xmlw.writeEndElement();
    xmlw.writeCharacters("\n");

    // 结束“person”元素
    xmlw.writeEndElement();

关闭输出流

完成 XMLStreamWriter 的使用后明确将其关闭以释放资源是一个很好的编程实践。要关闭编写器,请使用 XMLStreamReader.close() 方法,如以下示例所示:

    // 关闭 XMLStreamWriter 以释放资源
    xmlw.close();

 


XMLInputFactory 接口定义的属性

下表列出在使用 XMLInputFactory 生成 XMLStreamReader XMLEventReader 对象时,可以设置的标准属性。

注意:

下表所有属性的前面均以 javax.xml.stream 开始,如 javax.xml.stream.isValidating

4-2 标准 XMLInputFactory 属性

属性

描述

返回类型

默认值

isValidating

指定实现特定的 DTD 验证是处于启用状态还是禁用状态。

Boolean

False

isNamespaceAware

指定名称空间处理是处于启用状态还是禁用状态。用于 XML 1.0 支持。

Boolean

True

isCoalescing

指定是否合并相邻的字符数据。

Boolean

False

isReplacingEntityReferences

指定内部实体引用是否应替换为其替换文本,且作为字符进行报告。

Boolean

True

isSupportingExternalEntities

指定是否解析外部已解析的实体。

Boolean

False

supportDTD

指定使用的处理器支持 DTD,还是不支持 DTD

Boolean

True

reporter

指定应使用的 javax.xml.stream.XMLReporter 的实现。

XMLReporter

Null

resolver

指定应使用的 javax.xml.stream.XMLResolver 的实现。

XMLResolver

Null

allocator

指定应使用的 javax.xml.stream.util.XMLEventAllocator 的实现。

util.XMLEventAllocator

Null

 


XMLOutputFactory 接口定义的属性

下表列出在使用 XMLOutputFactory 生成 XMLStreamWriter XMLEventWriter 对象时,可以设置的标准属性。

注意:

下表所有属性的前面均以 javax.xml.stream 开始,如 javax.xml.stream.isValidating

4-3 标准 XMLOutputFactory 属性

属性

描述

返回类型

默认值

isRepairingNamespaces

指定编写器使用默认名称空间前缀声明。

在生成 XML 时,存在 StAX 处理器如何修复名称空间和前缀的严格规则。有关详细信息,请参阅 StAX specification

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics