WebLogic XML プログラマーズ ガイド

     前  次    新しいウィンドウで目次を開く     
ここから内容の開始

Streaming API for XML (StAX) の使い方

以下の節では、Streaming API for XML により XML ドキュメントの解析と生成を行う方法について説明します。

 


Streaming API for XML の概要

Java Community Process の JSR-173 で定義されている Streaming API for XML (StAX) を使用すると、XML ドキュメントを簡単かつ直感的に解析および生成できます。SAX API と似ていますが、XML ドキュメントに対する手続き的なストリーム ベースの処理が可能であり、SAX イベント ハンドラを作成する必要はありません。SAX イベント ハンドラで複雑な XML ドキュメントを扱うと、ハンドラ自体が複雑になる場合があります。つまり、StAX を利用すれば、SAX よりきめ細かく解析を制御できます。

SAX を使用して XML ドキュメントを解析する場合、プログラムでは、イベント発生時に解析をリスンするイベント リスナを作成し、特定のイベントを請求するのではなくイベントに対して対応する必要があります。一方、StAX を使用する場合は、XML ドキュメントを手順の流れに沿って処理すること、特定のタイプのイベント (要素の開始など) を請求すること、要素の属性を繰り返し処理すること、ドキュメントの先頭をスキップすること、任意の時点で処理を停止すること、特定の要素の下位要素を取得すること、指定どおりに要素をフィルタ処理することができます。イベントに対応するのではなく、イベントを請求するので、StAX を使用する方法は、「プル解析」と呼ばれることもあります。

StAX には、カーソル API とイベント イテレータ API という 2 つの API があり、どちらでも XML を読み書きできます。以下の節では、各 API およびそれぞれの利点について説明します。

カーソル API の説明

カーソル API の基本機能は、できる限り簡単かつ効率的に XML を解析および生成できるようにするためのものです。StAX の 2 つの API のうち、ほとんどのプログラマが使用すると思われるのは、こちらの方です。

カーソル API は、開始要素、コメント、属性などの一連のイベントを、発生していないものも含めて繰り返し処理します。カーソル API には、XML 解析用の XMLStreamReader と XML 生成用の XMLStreamWriter という 2 つの主要なインタフェースがあります。

XMLStreamReader インタフェース

カーソル API は、XMLStreamReader インタフェースを使用して仮想カーソルを XML ドキュメント上に移動し、hasNext()next()getEventType()、および getText() などのメソッドを呼び出してデータおよび基底の状態にアクセスできるようにします。XMLStreamReader インタフェースでは、XML に対して読み込み専用の前方アクセスのみが可能です。

XMLStreamReader の新しいインスタンスを作成するには、XMLInputFactory クラスを使用します。新しいリーダーを取得すると、さまざまなプロパティを設定できます。詳細については、「XMLInputFactory インタフェース用に定義されたプロパティ」を参照してください。

XMLStreamReader インタフェースの next() メソッドを使用して XML を解析すると、リーダーは次の解析イベントを取得し、読み込んだイベントの種類を識別する整数を返します。解析イベントは、XML 宣言、開始要素タグ、終了要素タグ、ホワイトスペース、コメント、処理手順などの XML ドキュメントの各セクションに対応します。XMLStreamConstant インタフェースは、next() メソッドによって返された整数に対応するイベントを指定します。XMLStreamReadergetEventType() メソッドを使用して、イベントの種類を判別することもできます。

XMLStreamReader インタフェースには、XML ドキュメントの特定のデータを取得するためのさまざまなメソッドがあります。そのメソッドの一部を次に示します。

有効なメソッドは、イベントの種類ごとに決まっています。無効なイベントの種類でメソッドを呼び出そうとすると、StAX プロセッサから java.lang.IllegalStateException が送出されます。たとえば、ネームスペース イベントで getAttributeXXX() メソッドを呼び出すとエラーになります。イベントの詳細なリストとそのイベントで有効な XMLStreamReader メソッドについては、StAX 仕様を参照してください。

XMLStreamWriter インタフェース

カーソル API は、XMLStreamWriter インタフェースを使用して、XML の生成方法を指定します。

XMLStreamWriter の新しいインスタンスを作成するには、XMLOutputFactory クラスを使用します。新しいライターを取得すると、ネームスペースおよびプレフィックスを修正するためのプロパティを設定できます。詳細については、「XMLOutputFactory インタフェース用に定義されたプロパティ」を参照してください。

XMLStreamWriter インタフェースには、XML ドキュメントの標準的な部分に書き込みを行う一連の writeXXX() メソッドが定義されています。以下に、そのメソッドを示します。

属性とネームスペースを含む XML ドキュメントの各部分は、これらのメソッドによって明示的に書き込まれます。

キャッシュされたデータを出力に書き込むには flush() メソッド、ライターを閉じてリソースを解放するには close() メソッドを使用します。

XMLStreamWriter は、XML の生成時に、生成されたドキュメントが整形式かどうかをチェックしません。整形式の XML ドキュメントを作成するのは、プログラマの役目です。特殊文字 &<、および > を出力するには、writeCharacters() メソッドを使用します。

イベント イテレータ API の説明

イベント イテレータ API は、カーソル API のすぐ上のレイヤです。パイプライニングの拡張および促進を簡単に行うことができます。パイプライニングとは、複数の XML 間の変換のことです。イベント イテレータ API を使用すると、パイプラインの各ステージで XML をデシリアライズおよびシリアライズする必要はなくなり、パイプラインの両端でのみ nextEvent() などの API メソッドを使用して中間ステージで通信します。イベント イテレータ API には、XML 解析用の XMLEventReader と XML 生成用の XMLEventWriter という 2 つの主要なインタフェースがあります。

カーソル API が StAX で最も頻繁に使用される API なので、このセクションではイベント イテレータ API の詳細な使い方については例を挙げる他には説明しません。この API の詳細な使い方については、StAX 仕様を参照してください。

次の例では、StAX の XMLEventReader インタフェースを使用して XML ドキュメントを解析する単純なプログラムを示します。このプログラムは、XML ファイルを表す 1 つのパラメータを取り、それを使用して 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;
/**
 * イベントを反復処理する単純なサンプル プログラム
 *
 * @author Copyright (c) 2002 by BEA Systems.All Rights Reserved.
 */
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 のメイン インタフェースとクラス

次の表で、Streaming API for XML の主なインタフェースとクラスについて説明します。

表 4-1 Streaming API for XML の主なインタフェースとクラス
インタフェースまたはクラス
カーソル API 用/イベント イテレータ API 用
説明
XMLInputFactory クラス
両方
XMLStreamReader または XMLEventReader インスタンスの作成に使用するファクトリ クラス。
XMLOutputFactory クラス
両方
XMLStreamWriter または XMLEventWriter インスタンスの作成に使用するファクトリ クラス。
XMLEventFactory クラス
イベント イテレータ
XMLEvent インスタンスの作成に使用するファクトリ クラス。
XMLStreamReader インタフェース
カーソル
XML ドキュメントの解析に使用するインタフェース。次のイベントを参照および取得し、それ以降のイベントがあるかどうかをチェックできる。
XMLStreamWriter インタフェース
カーソル
XML ドキュメントの生成に使用するインタフェース。開始要素や属性など、XML ドキュメントの特定の部分を生成する一連の writeXXX() メソッドを利用できる。
XMLEventReader インタフェース
イベント イテレータ
XML イベントの解析に使用するインタフェース。次のイベントを参照および取得し、それ以降のイベントがあるかどうかをチェックできる。
XMLEventWriter インタフェース
イベント イテレータ
XML の生成に使用するインタフェース。add() メソッドを使用して出力ストリームに XMLEvents を追加する。
XMLEvent
イベント イテレータ
イベントを処理する基本インタフェース。StartElementAttribute など、XMLEvent から拡張された特定の全 XML イベント。
XMLStreamException 例外
両方
整形式の XML ドキュメント構造の欠陥など、予期しない処理エラーに関する基底の例外。

 


XMLStreamReader インタフェースによる XML の解析 : 一般的な手順

以下の手順は、StAX カーソル API の XMLStreamReader インタフェースにより XML ドキュメントの解析を行う一般的手順について説明したものです。この手順では、「StAX を使用した XML 解析の例」で示すサンプル コードを用います。

  1. javax.xml.stream.* クラスをインポートします。
  2. 次のコードの抜粋で示すように、XMLInputFactory.newInstance() メソッドを使用して XMLInputFactory をインスタンス化します。
  3. XMLInputFactory xmlif = XMLInputFactory.newInstance();

    設定可能なプロパティのリストについては、「XMLInputFactory インタフェース用に定義されたプロパティ」を参照してください。

  4. XML ドキュメントを基に、XMLInputFactory.createXMLStreamReader() メソッドを使用して XMLStreamReader オブジェクトをインスタンス化します。
  5. 詳細については、「XMLStreamReader オブジェクトの取得」を参照してください。

  6. 次のコードの抜粋で示すように、hasNext() メソッドと next() メソッドで各 XML イベントを順番に処理して XML ドキュメントを解析します。
  7. while(xmlr.hasNext()){
    printEvent(xmlr);
    xmlr.next();

    この例では、xmlrXMLStreamReader インスタンスに当たり、ローカル メソッド printEvent() (StAX API の一部ではありません) が、次の手順に示すように特定のイベント タイプを判別します。

  8. XML ドキュメントの解析中に、現在の特定のイベント タイプを判別し、それに対応した処理を行います。イベント タイプには、XML ドキュメントの開始と終了、XML 要素の開始と終了、コメント、エンティティ参照などがあります。
  9. 特定の XML イベント タイプの判別」を参照してください。

  10. 現在のイベント タイプが開始要素または終了要素の場合、必要に応じてその属性を取得します。
  11. 要素の属性の取得」を参照してください。

  12. 現在のイベント タイプが開始要素または終了要素の場合、必要に応じてそのネームスペースを取得します。
  13. 要素のネームスペースの取得」を参照してください。

  14. 現在のイベント タイプに CDATA やコメントなどのテキスト データが含まれる場合、必要に応じて実際のデータを取得します。
  15. テキスト データの取得」を参照してください。

  16. 必要に応じて、行番号や列番号など、現在のイベントの場所の情報を取得します。
  17. 場所の情報の取得」を参照してください。

  18. ストリームをクローズします。
  19. 入力ストリームのクローズ」を参照してください。

StAX を使用した XML 解析の例

次の例では、StAX の XMLStreamReader インタフェースを使用して XML ドキュメントを解析する単純なプログラムを示します。

このプログラムは、XML ファイルを表す 1 つのパラメータを取り、それを使用して XMLStreamReader オブジェクトを作成します。次に、リーダーを使用してイベントのストリームを繰り返し処理し、XML 要素の開始、要素の属性のリスト、処理手順など、各イベントのタイプを判別します。このサンプル プログラムは、内部メソッドを使用して、適切な場合は属性およびネームスペースのリストを出力し、これらのイベントに関する情報を出力します。

太字のコードは、以降の節で説明します。

package examples.basic;
import java.io.FileReader;
import java.util.Iterator;
import javax.xml.stream.*;
import javax.xml.namespace.QName;
/**
 * これは、XMLStreamReader クラスを示す
 * 単純な解析例
 *
 * @author Copyright (c) 2003 by BEA Systems. All Rights Reserved.
 */
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));

この例では、xmlifXMLInputFactory インスタンスに当たります。

createXMLStreamReader() メソッドのさまざまなシグネチャにより、以下の XML ドキュメント フォーマットをパラメータとして扱うことができます。

特定の XML イベント タイプの判別

XML ドキュメントの解析中に特定のイベント タイプを判別するには、XMLStreamReader.next() メソッドまたは XMLStreamReader.getEventType() メソッドを使用します。next() メソッドは、次のイベントを読み込んで、そのイベント タイプを示す整数を返し、getEventType() メソッドは、現在のイベント タイプを示す整数を単純に返します。XMLStreamReaderXMLStreamConstants 上位インタフェースには、以下のリストに示すイベント タイプ定数が定義されています。

次の例では、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() メソッドについては、別の節で説明します。

2 つの 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 インタフェースには、コメントや CDATA などのイベントからテキスト データを取得するためのさまざまな getTextXXX() メソッドが用意されています。

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 ドキュメントの生成を行う一般的手順について説明したものです。

  1. javax.xml.stream.* クラスをインポートします。
  2. XMLOutputFactory.newInstance() メソッドを使用して XMLOutputFactory をインスタンス化します。次に例を示します。
  3. XMLOutputFactory xmlof = XMLOutputFactory.newInstance();

    設定可能なプロパティのリストについては、「XMLOutputFactory インタフェース用に定義されたプロパティ」を参照してください。

  4. XMLOutputFactory.createXMLStreamWriter() メソッドを使用して、XML を含むファイルまたはオブジェクトの名前を渡し、XMLStreamWriter オブジェクトをインスタンス化します。
  5. 詳細については、「XMLStreamWriter オブジェクトの取得」を参照してください。

  6. XML 宣言を出力に追加します。「出力ストリームへの XML 宣言の追加」を参照してください。
  7. 開始要素、コメント、文字などの標準 XML オブジェクトを出力に追加します。「出力ストリームへの標準 XML イベントの追加」を参照してください。
  8. 属性とネームスペース宣言を開始要素に追加します。「属性とネームスペース宣言の開始要素への追加」を参照してください。
  9. 出力ストリームをクローズします。「出力ストリームのクローズ」を参照してください。

StAX を使用した XML 生成の例

次の例では、StAX の XMLStreamWriter インタフェースを使用して XML ドキュメントを生成する単純なプログラムを示します。

このサンプル プログラムではまず、カレント ディレクトリにある outFile.xml ファイルに出力が書き込まれるように指定して、XMLStreamWriter のインスタンスを作成します。次に、さまざまな 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>
 *
 *
 * @author Copyright (c) 2003 by BEA Systems. All Rights Reserved.
 */
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");
    // 内容と 2 つの属性を持つ「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"));

この例では、xmlofXMLOutputFactory インスタンスに当たります。

createXMLStreamWriter() メソッドのさまざまなシグネチャにより、以下の XML ドキュメント フォーマットをパラメータとして扱うことができます。

出力ストリームへの XML 宣言の追加

次のコードの抜粋で示すように、XMLStreamWriter.writeStartDocument() メソッドを使用し、XML ドキュメントの 1 行目として XML 宣言を追加します。

xmlw.writeStartDocument();

引数を指定しない場合、このメソッドは次のデフォルト XML 宣言を記述します。

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

別のエンコーディングまたは XML バージョンを指定する場合は、引数を次のように指定した writeStartDocument() メソッドを使用します。

writeStartDocument() メソッドでエンコーディングを設定しても、基底の出力の実際のエンコーディングは設定されません。このエンコーディング設定用の引数は、XML 宣言の encoding 属性に対してどの値が書き込まれるかを指定するものです。出力のエンコーディングを実際に設定するには、対応する XMLOutputFactory.createXMLStreamWriter() メソッドで XMLStreamWriter のインスタンスを作成する際に encoding パラメータを指定する必要があります。

出力ストリームへの標準 XML イベントの追加

XMLStreamWriter.writeXXX() メソッドを使用すると、開始要素、終了要素、コメント、CDATA、エンティティ参照などの標準的な XML イベントを出力ストリームに追加できます。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 が送出されます。イベントのプレフィックスやそのバインド対象となる URI を指定するには、それに応じた形式の writeXXX() メソッドを使用します。

たとえば、次の 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");
    // 内容と 2 つの属性を持つ「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 を明示的にクローズしてリソースを解放します。ライターをクローズするには、XMLStreamWriter.close() メソッドを使用します。以下に例を示します。

    // XMLStreamWriter をクローズしてリソースを解放する
xmlw.close();

 


XMLInputFactory インタフェース用に定義されたプロパティ

以下の表では、XMLInputFactory を使用して XMLStreamReader オブジェクトまたは XMLEventReader オブジェクトを生成する際に設定可能な標準プロパティを示します。

注意 : 以下の表のプロパティには、たとえば javax.xml.stream.isValidating のように、いずれも先頭に javax.xml.stream が付きます。
表 4-2 XMLInputFactory の標準プロパティ
プロパティ
説明
戻り値の型
デフォルト値
isValidating
実装固有の DTD 検証を有効にするか無効にするかを指定する。
Boolean
False
isNamespaceAware
ネームスペース処理を有効にするか無効にするかを指定する。XML 1.0 がサポートされている場合に使用。
Boolean
True
isCoalescing
隣接する文字データをまとめるかどうかを指定する。
Boolean
False
isReplacingEntityReferences
内部エンティティ参照を置換テキストに置き換え、文字として報告するかどうかを指定する。
Boolean
True
isSupportingExternalEntities
解析対象の外部エンティティを解決するかどうかを指定する。
Boolean
False
supportDTD
使用するプロセッサが 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.isValidating のように、いずれも先頭に javax.xml.stream が付きます。
表 4-3 XMLOutputFactory の標準プロパティ
プロパティ
説明
戻り値の型
デフォルト値
isRepairingNamespaces
ライターがデフォルト ネームスペース プレフィックス宣言を使用するかどうかを指定する。
XML の生成時に StAX プロセッサがネームスペースとプレフィックスを修正する方法には、いくつかの厳密なルールがある。詳細については、StAX 仕様を参照。
Boolean
False

ページの先頭       前  次