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

 

 

 

分享到:
评论

相关推荐

    JDK 6.2.3文文档.rar

    StAX Compiler API 轻量级 Http Server API 插入式注解处理API(Pluggable Annotation Processing API) 用Console开发控制台程序 对脚本语言的支持(如:ruby,groovy,javascript) Common Annotations ————...

    jackson-jar

    本文主要内容译自JacksonInFiveMinutes,增加了部分示例,转载请注明出处。 受java平台上各种处理xml的类库(StAX, JAXB等)启发,Jackson提供一种处理json的java类库。Jackson的目标是为开发者提供快速、准确、轻...

    Matlab环境下决策分类树的构建、优化与应用

    内容概要:本文详细介绍了如何利用Matlab构建、优化和应用决策分类树。首先,讲解了数据准备阶段,将数据与程序分离,确保灵活性。接着,通过具体实例展示了如何使用Matlab内置函数如fitctree快速构建决策树模型,并通过可视化工具直观呈现决策树结构。针对可能出现的过拟合问题,提出了基于成本复杂度的剪枝方法,以提高模型的泛化能力。此外,还分享了一些实用技巧,如处理连续特征、保存模型、并行计算等,帮助用户更好地理解和应用决策树。 适合人群:具有一定编程基础的数据分析师、机器学习爱好者及科研工作者。 使用场景及目标:适用于需要进行数据分类任务的场景,特别是当需要解释性强的模型时。主要目标是教会读者如何在Matlab环境中高效地构建和优化决策分类树,从而应用于实际项目中。 其他说明:文中不仅提供了完整的代码示例,还强调了代码模块化的重要性,便于后续维护和扩展。同时,对于初学者来说,建议从简单的鸢尾花数据集开始练习,逐步掌握决策树的各项技能。

    《营销调研》第7章-探索性调研数据采集.pptx

    《营销调研》第7章-探索性调研数据采集.pptx

    Assignment1_search_final(1).ipynb

    Assignment1_search_final(1).ipynb

    美团外卖优惠券小程序 美团优惠券微信小程序 自带流量主模式 带教程.zip

    美团优惠券小程序带举牌小人带菜谱+流量主模式,挺多外卖小程序的,但是都没有搭建教程 搭建: 1、下载源码,去微信公众平台注册自己的账号 2、解压到桌面 3、打开微信开发者工具添加小程序-把解压的源码添加进去-appid改成自己小程序的 4、在pages/index/index.js文件搜流量主广告改成自己的广告ID 5、到微信公众平台登陆自己的小程序-开发管理-开发设置-服务器域名修改成

    《计算机录入技术》第十八章-常用外文输入法.pptx

    《计算机录入技术》第十八章-常用外文输入法.pptx

    基于Andorid的跨屏拖动应用设计.zip

    基于Andorid的跨屏拖动应用设计实现源码,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。

    《网站建设与维护》项目4-在线购物商城用户管理功能.pptx

    《网站建设与维护》项目4-在线购物商城用户管理功能.pptx

    区块链_房屋转租系统_去中心化存储_数据防篡改_智能合约_S_1744435730.zip

    区块链_房屋转租系统_去中心化存储_数据防篡改_智能合约_S_1744435730

    《计算机应用基础实训指导》实训五-Word-2010的文字编辑操作.pptx

    《计算机应用基础实训指导》实训五-Word-2010的文字编辑操作.pptx

    《移动通信(第4版)》第5章-组网技术.ppt

    《移动通信(第4版)》第5章-组网技术.ppt

    ABB机器人基础.pdf

    ABB机器人基础.pdf

    《综合布线施工技术》第9章-综合布线实训指导.ppt

    《综合布线施工技术》第9章-综合布线实训指导.ppt

    最新修复版万能镜像系统源码-最终版站群利器持续更新升级

    很不错的一套站群系统源码,后台配置采集节点,输入目标站地址即可全自动智能转换自动全站采集!支持 https、支持 POST 获取、支持搜索、支持 cookie、支持代理、支持破解防盗链、支持破解防采集 全自动分析,内外链接自动转换、图片地址、css、js,自动分析 CSS 内的图片使得页面风格不丢失: 广告标签,方便在规则里直接替换广告代码 支持自定义标签,标签可自定义内容、自由截取、内容正则截取。可以放在模板里,也可以在规则里替换 支持自定义模板,可使用标签 diy 个性模板,真正做到内容上移花接木 调试模式,可观察采集性能,便于发现和解决各种错误 多条采集规则一键切换,支持导入导出 内置强大替换和过滤功能,标签过滤、站内外过滤、字符串替换、等等 IP 屏蔽功能,屏蔽想要屏蔽 IP 地址让它无法访问 ****高级功能*****· url 过滤功能,可过滤屏蔽不采集指定链接· 伪原创,近义词替换有利于 seo· 伪静态,url 伪静态化,有利于 seo· 自动缓存自动更新,可设置缓存时间达到自动更新,css 缓存· 支持演示有阿三源码简繁体互转· 代理 IP、伪造 IP、随机 IP、伪造 user-agent、伪造 referer 来路、自定义 cookie,以便应对防采集措施· url 地址加密转换,个性化 url,让你的 url 地址与众不同· 关键词内链功能· 还有更多功能等你发现…… 程序使用非常简单,仅需在后台输入一个域名即可建站,不限子域名,站群利器,无授权,无绑定限制,使用后台功能可对页面进行自定义修改,在程序后台开启生 成功能,只要访问页面就会生成一个本地文件。当用户再次访问的时候就直接访问网站本地的页面,所以目标站点无法访问了也没关系,我们的站点依然可以访问, 支持伪静态、伪原创、生成静态文件、自定义替换、广告管理、友情链接管理、自动下载 CSS 内的图。

    《Approaching(Almost)any machine learning problem》中文版第11章

    【自然语言处理】文本分类方法综述:从基础模型到深度学习的情感分析系统设计

    基于Andorid的下拉浏览应用设计.zip

    基于Andorid的下拉浏览应用设计实现源码,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。

    P2插电式混合动力系统Simulink模型:基于逻辑门限值控制策略的混动汽车仿真

    内容概要:本文详细介绍了一个原创的P2插电式混合动力系统Simulink模型,该模型基于逻辑门限值控制策略,涵盖了多个关键模块如工况输入、驾驶员模型、发动机模型、电机模型、制动能量回收模型、转矩分配模型、运行模式切换模型、档位切换模型以及纵向动力学模型。模型支持多种标准工况(WLTC、UDDS、EUDC、NEDC)和自定义工况,并展示了丰富的仿真结果,包括发动机和电机转矩变化、工作模式切换、档位变化、电池SOC变化、燃油消耗量、速度跟随和最大爬坡度等。此外,文章还深入探讨了逻辑门限值控制策略的具体实现及其效果,提供了详细的代码示例和技术细节。 适合人群:汽车工程专业学生、研究人员、混动汽车开发者及爱好者。 使用场景及目标:①用于教学和科研,帮助理解和掌握P2混动系统的原理和控制策略;②作为开发工具,辅助设计和优化混动汽车控制系统;③提供仿真平台,评估不同工况下的混动系统性能。 其他说明:文中不仅介绍了模型的整体架构和各模块的功能,还分享了许多实用的调试技巧和优化方法,使读者能够更好地理解和应用该模型。

    电力系统分布式调度中ADMM算法的MATLAB实现及其应用

    内容概要:本文详细介绍了基于ADMM(交替方向乘子法)算法在电力系统分布式调度中的应用,特别是并行(Jacobi)和串行(Gauss-Seidel)两种不同更新模式的实现。文中通过MATLAB代码展示了这两种模式的具体实现方法,并比较了它们的优劣。并行模式适用于多核计算环境,能够充分利用硬件资源,尽管迭代次数较多,但总体计算时间较短;串行模式则由于“接力式”更新机制,通常收敛更快,但在计算资源有限的情况下可能会形成瓶颈。此外,文章还讨论了惩罚系数rho的自适应调整策略以及在电-气耦合系统优化中的应用实例。 适合人群:从事电力系统优化、分布式计算研究的专业人士,尤其是有一定MATLAB编程基础的研究人员和技术人员。 使用场景及目标:①理解和实现ADMM算法在电力系统分布式调度中的应用;②评估并行和串行模式在不同应用场景下的性能表现;③掌握惩罚系数rho的自适应调整技巧,提高算法收敛速度和稳定性。 其他说明:文章提供了详细的MATLAB代码示例,帮助读者更好地理解和实践ADMM算法。同时,强调了在实际工程应用中需要注意的关键技术和优化策略。

Global site tag (gtag.js) - Google Analytics