`
chenlong_1988
  • 浏览: 185906 次
  • 性别: 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

 

 

 

分享到:
评论

相关推荐

    stax-api.jar

    `stax-api.jar`是Java中用于处理XML流的STAX(Streaming API for XML)的API接口库,它提供了与XML数据交互的一套标准化接口。 STAX(Streaming API for XML)是一种低级别的XML解析方法,相比DOM(Document Object...

    stax-api 1.0.1

    STAX(Streaming API for XML)是Java平台上的一个XML处理API,它提供了对XML文档的事件驱动解析。与DOM(Document Object Model)不同,STAX不是加载整个XML文档到内存中形成一个树形结构,而是通过事件(如开始...

    stax-api-1.0-2

    **STAX API 1.0-2:XML处理的关键组件** STAX,全称为Streaming API for XML,是一种用于处理XML的Java API。STAX提供了一种流式处理XML文档的方法,与DOM(Document Object Model)相比,它更加高效且内存占用更低...

    stax-api-1.0.1、stax2-api-3.1.1、woodstox-core-asl-4.1.1

    STAX(Streaming API for XML)是一种用于处理XML的Java API,它提供了事件驱动的解析方式,使得开发者可以高效地读取和写入XML文档。在Java世界中,STAX提供了比DOM(Document Object Model)更高效的处理XML的方式...

    stax2-api-3.1.4-API文档-中英对照版.zip

    赠送jar包:stax2-api-3.1.4.jar; 赠送原API文档:stax2-api-3.1.4-javadoc.jar; 赠送源代码:stax2-api-3.1.4-sources.jar; 赠送Maven依赖信息文件:stax2-api-3.1.4.pom; 包含翻译后的API文档:stax2-api-...

    stax-ex-1.8.3.zip

    《STAX EX 1.8.3:深入解析Java XML处理库》 在Java编程领域,XML(Extensible Markup Language)作为一种数据交换和存储格式,广泛应用于各种应用场景。处理XML时,Java提供了多种API,其中STAX(Streaming API ...

    jaxb+stax+demo

    在"jaxb+stax+demo"的示例中,通常会展示如何结合JAXB和STAX来高效地解析和生成XML。具体步骤可能包括以下几点: 1. **定义Java类**:首先,我们需要创建一些Java类,这些类将代表XML文档中的元素和属性。JAXB使用...

    stax-api-1.0.1 java 操作 xml 文件 一个很好用的包

    STAX(Streaming API for XML)是Java平台上的一个XML处理API,它提供了高效且灵活的方式来读取和写入XML文档。STAX的核心理念是事件驱动,即解析XML时,每遇到一个XML元素或属性,都会触发一个相应的事件,程序通过...

    stax-ex-1.8.jar

    stax-ex-1.8.jarstax-ex-1.8.jarstax-ex-1.8.jar

    staxmate-with-stax2-1.3.0.jar包

    **StaxMate与STAX2 1.3.0.jar包详解** 在Java开发中,处理XML文档是一项常见的任务。为了高效地解析和生成XML,开发者通常会利用各种API,如DOM(Document Object Model)、SAX(Simple API for XML)和STAX...

    java Stax 解析xml

    ### Java StAX解析XML详解 #### 一、简介与背景 在Java开发中,XML是一种常用的数据交换格式,尤其在处理配置文件或与其他系统进行数据交互时。Java提供了多种解析XML的技术,包括DOM(Document Object Model)、...

    stax2-api-3.1.4.jar

    实现了特殊的XML验证,一般来说使用SAXParser来读入XML文件再进行验证,但是这里使 用了边写边验证的功能,如果是...是Stax2 API提供的功能 java转换json或xml,支持Java和Json格式的互转,同时也支持Java和XML的互转

    stax+jaxb进行xml解析

    在Java中,有多种方法可以解析XML,其中StAX(Streaming API for XML)和JAXB(Java Architecture for XML Binding)是两种常用的技术。本篇文章将详细探讨如何结合StAX和JAXB进行高效的XML解析。 StAX是一种事件...

    stax2-api-3.1.1.jar

    "stax2-api-3.1.1.jar"是一个Java库,主要用于XML解析,特别是采用了StAX 2.0规范的实现。这个jar包包含了StAX 2 API的接口和实现,使得开发人员能够利用其特性来读取和写入XML数据,而无需处理复杂的DOM树或SAX事件...

    stax2-api-3.1.1-sources.jar

    stax2-api-3.1.1-sources.jar文件,下载使用,用来解析XML文件的jar包。Streaming API for XML (StAX) 的基于事件迭代器 API 无论在性能还是在可用性上都有其他 XML 处理方法所不及的独到之处。

    stax2-api-4.2.1.jar

    用来解析XML文件的jar包。Streaming API for XML (StAX) 的基于事件迭代器 API 无论在性能还是在可用性上都有其他 XML 处理方法所不及的独到之处。使用前请先解压

    用Stax组装及解析XML

    ### 使用StAX组装与解析XML #### 一、引言 在处理XML文档时,Java提供了多种工具和技术,包括DOM、SAX以及本文将重点讨论的Streaming API for XML(简称StAX)。StAX是一种用于读取和写入XML数据的事件驱动型API,...

    java xml 4 种 解析xml 方法 sax jdom dom stAX

    为了处理XML文档,Java提供了多种解析方法,包括SAX(Simple API for XML)、JDOM(Java Document Object Model)、DOM(Document Object Model)以及stAX(Streaming API for XML)。下面将详细介绍这四种解析XML的...

    java使用stax技术操作XML文档.doc

    Streaming API for XML (StAX) 是Java中处理XML的一种高效且灵活的标准,相较于DOM和SAX,它在性能和易用性上有显著优势。StAX是JSR-173的一部分,于2004年3月发布,最终被纳入JAXP 1.4,也将在Java 6中得到支持。 ...

    有用的Java工具—XML解析工具StAx

    StAX是一种基于事件驱动的解析器,它允许程序员通过逐个处理XML事件(如开始元素、结束元素、文本等)来读取和写入XML文档,这种方式相比DOM(Document Object Model)更加轻量级和高效。 **StAX的优势** 1. **低...

Global site tag (gtag.js) - Google Analytics