この章の内容は以下のとおりです。
Java Community ProcessのJSR-173 (http://www.jcp.org/en/jsr/detail?id=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の基本機能は、できる限り簡単かつ効率的にXMLを解析および生成できるようにするためのものです。StAXの2つのAPIのうち、ほとんどのプログラマが使用すると思われるのは、こちらの方です。
カーソルAPIは、開始要素、コメント、属性などの一連のイベントを、発生していないものも含めて繰返し処理します。カーソルAPIには、XML解析用のXMLStreamReader
とXML生成用のXMLStreamWriter
という2つの主要なインタフェースがあります。
カーソルAPIは、XMLStreamReader
インタフェースを使用して仮想カーソルをXMLドキュメント上に移動し、hasNext()
、next()
、getEventType()
、およびgetText()
などのメソッドを呼び出してデータおよび基底の状態にアクセスできるようにします。XMLStreamReader
インタフェースでは、XMLに対して読取り専用の前方アクセスのみが可能です。
XMLStreamReader
の新しいインスタンスを作成するには、XMLInputFactory
クラスを使用します。新しいリーダー を取得すると、様々なプロパティを設定できます。詳細は、「XMLInputFactoryインタフェース用に定義されたプロパティ」を参照してください
XMLStreamReader
インタフェースのnext()
メソッドを使用してXMLを解析すると、リーダーは次の解析イベントを取得し、読み込んだイベントの種類を識別する整数を返します。解析イベントは、XML宣言、開始要素タグ、終了要素タグ、ホワイトスペース、コメント、処理手順などのXMLドキュメントの各セクションに対応します。XMLStreamConstant
インタフェースは、next()
メソッドによって返された整数に対応するイベントを指定します。XMLStreamReader
のgetEventType()
メソッドを使用して、イベントの種類を判別することもできます。
XMLStreamReader
インタフェースには、XMLドキュメントの特定のデータを取得するための様々なメソッドがあります。そのメソッドの一部を次に示します。
getLocalName()
- 現在のイベントのローカル名を返します。
getPrefix()
- 現在のイベントの接頭辞を返します。
getAttributeXXX()
- 現在の属性イベントに関する情報を返す一連のメソッドです。
getNamespaceXXX()
- 現在のネームスペース・イベントに関する情報を返す一連のメソッドです。
getTextXXX()
- 現在のテキスト・イベントに関する情報を返す一連のメソッドです。
getPIData()
- 現在の処理手順イベントのデータ・セクションを返します。
有効なメソッドは、イベントの種類ごとに決まっています。無効なイベントの種類でメソッドを呼び出そうとすると、StAXプロセッサからjava.lang.IllegalStateException
が送出されます。たとえば、ネームスペース・イベントでgetAttributeXXX()
メソッドを呼び出すとエラーになります。イベントの完全なリストとそのイベントで有効なXMLStreamReader
メソッドについては、http://www.jcp.org/en/jsr/detail?id=173
にあるStAX仕様を参照してください。
カーソルAPIは、XMLStreamWriter
インタフェースを使用して、XMLの生成方法を指定します。
XMLStreamWriter
の新しいインスタンスを作成するには、XMLOutputFactory
クラスを使用します。新しいライターを取得すると、ネームスペースおよび接頭辞を修正するためのプロパティを設定できます。詳細は、「XMLOutputFactoryインタフェース用に定義されたプロパティ」を参照してください
XMLStreamWriter
インタフェースには、XMLドキュメントの標準的な部分に書込みを行う一連のwriteXXX()
メソッドが定義されています。以下に、そのメソッドを示します。
writeStartElement()
writeEndDocument()
writeAttribute()
writeNamespace()
writeCData()
属性とネームスペースを含むXMLドキュメントの各部分は、これらのメソッドによって明示的に書き込まれます。
キャッシュされたデータを出力に書き込むにはflush()
メソッド、ライターを閉じてリソースを解放するにはclose()
メソッドを使用します。
XMLStreamWriter
は、XMLの生成時に、生成されたドキュメントが整形式かどうかをチェックしません。整形式のXMLドキュメントを作成するのは、プログラマの役目です。特殊文字&
、<
、および>
を出力するには、writeCharacters()
メソッドを使用します。
イベント・イテレータAPIは、カーソルAPIのすぐ上のレイヤーです。パイプライニングの拡張および促進を簡単に行うことができます。パイプライニングとは、複数のXML間の変換のことです。イベント・イテレータAPIを使用すると、パイプラインの各ステージでXMLをデシリアライズおよびシリアライズする必要はなくなり、パイプラインの両端でのみnextEvent()
などのAPIメソッドを使用して中間ステージで通信します。イベント・イテレータAPIには、XML解析用のXMLEventReader
とXML生成用のXMLEventWriter
という2つの主要なインタフェースがあります。
カーソルAPIがStAXで最も頻繁に使用されるAPIなので、このセクションではイベント・イテレータAPIの詳細な使い方については例を挙げる他には説明しません。このAPIの詳細な使い方については、StAX仕様(http://www.jcp.org/en/jsr/detail?id=173
)を参照してください。
次の例では、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; /** * A simple example to iterate over events * * @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+"]"); } } }
表4-1で、Streaming API for XMLの主なインタフェースとクラスについて説明します。
表4-1 Streaming API for XMLの主なインタフェースとクラス
インタフェースまたはクラス | カーソルAPI用/イベント・イテレータAPI用 | 説明 |
---|---|---|
XMLInputFactory class |
両方 |
|
XMLOutputFactory class |
両方 |
|
XMLEventFactory class |
イベント・イテレータ |
|
XMLStreamReader interface |
カーソル |
XMLドキュメントの解析に使用するインタフェース。次のイベントを参照および取得し、それ以降のイベントがあるかどうかをチェックできます。 |
XMLStreamWriter interface |
カーソル |
XMLドキュメントの生成に使用するインタフェース。開始要素や属性など、XMLドキュメントの特定の部分を生成する一連の |
XMLEventReader interface |
イベント・イテレータ |
XMLイベントの解析に使用するインタフェース。次のイベントを参照および取得し、それ以降のイベントがあるかどうかをチェックできます。 |
XMLEventWriter interface |
イベント・イテレータ |
XMLの生成に使用するインタフェース。 |
XMLEvent |
イベント・イテレータ |
イベントを処理する基本インタフェース。 |
XMLStreamException exception |
両方 |
整形式のXMLドキュメント構造の欠陥など、予期しない処理エラーに関する基底の例外。 |
以下の手順は、StAXカーソルAPIのXMLStreamReader
インタフェースによりXMLドキュメントの解析を行う一般的手順について説明したものです。この手順では、「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; /** * This is a simple parsing example that illustrates * the XMLStreamReader class. * * @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); } // // Get an input factory // XMLInputFactory xmlif = XMLInputFactory.newInstance(); System.out.println("FACTORY: " + xmlif); // // Instantiate a reader // XMLStreamReader xmlr = xmlif.createXMLStreamReader(new FileReader(filename)); System.out.println("READER: " + xmlr + "\n"); // // Parse the XML // while(xmlr.hasNext()){ printEvent(xmlr); xmlr.next(); } // // Close the reader // 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+"'"); } }
次のコードの抜粋で示すように、XMLInputFactory.createXMLStreamReader()
メソッドを使用し、XMLドキュメントに基づいてXMLStreamReader
オブジェクトをインスタンス化します。
XMLStreamReader xmlr = xmlif.createXMLStreamReader(new FileReader(filename));
この例では、xmlif
がXMLInputFactory
インスタンスに当たります。
createXMLStreamReader()
メソッドの様々なシグネチャにより、以下のXMLドキュメント・フォーマットをパラメータとして扱うことができます。
java.io.InputStream
java.io.Reader
(例で示します)
javax.xml.transform.Source
(JAXP API http://docs.oracle.com/javase/7/docs/technotes/guides/xml/index.html
で指定)
XMLドキュメントの解析中に特定のイベント・タイプを判別するには、XMLStreamReader.next()
メソッドまたはXMLStreamReader.getEventType()
メソッドを使用します。next()
メソッドは、次のイベントを読み込んで、そのイベント・タイプを示す整数を返し、getEventType()
メソッドは、現在のイベント・タイプを示す整数を単純に返します。XMLStreamReader
のXMLStreamConstants
上位インタフェースには、以下のリストに示すイベント・タイプ定数が定義されています。
XMLStreamConstants.ATTRIBUTE
XMLStreamConstants.CDATA
XMLStreamConstants.CHARACTERS
XMLStreamConstants.COMMENT
XMLStreamConstants.DTD
XMLStreamConstants.END_DOCUMENT
XMLStreamConstants.END_ELEMENT
XMLStreamConstants.ENTITY_DECLARATION
XMLStreamConstants.ENTITY_REFERENCE
XMLStreamConstants.NAMESPACE
XMLStreamConstants.NOTATION_DECLARATION
XMLStreamConstants.PROCESSING_INSTRUCTION
XMLStreamConstants.SPACE
XMLStreamConstants.START_DOCUMENT
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()
メソッドについては、別の節で説明します。
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()+"] ");
以下の手順は、StAXカーソルAPIのXMLStreamWriter
インタフェースにより、新しいXMLドキュメントの生成を行う一般的手順について説明したものです。
次の例では、StAXのXMLStreamWriter
インタフェースを使用してXMLドキュメントを生成する単純なプログラムを示します。
このサンプル・プログラムではまず、カレント・ディレクトリにあるoutFile.xml
ファイルに出力が書き込まれるように指定して、XMLStreamWriter
のインスタンスを作成します。次に、様々なwriteXXX()
メソッドを使用して、次のようなXMLファイルをビルドします。
<?xml version='1.0' encoding='utf-8'?> <!--this is a comment--> <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; /** * This is a simple example that illustrates how to use the * the XMLStreamWriter class to generate XML. * * The generated XML file looks like this: * * <?xml version='1.0' encoding='utf-8'?> * * <!--this is a comment--> * <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 { // // Get an output factory // XMLOutputFactory xmlof = XMLOutputFactory.newInstance(); System.out.println("FACTORY: " + xmlof); // // Instantiate a writer // XMLStreamWriter xmlw = xmlof.createXMLStreamWriter(new FileOutputStream ("outFile.xml")); System.out.println("READER: " + xmlw + "\n"); // // Generate the XML // // Write the default XML declaration xmlw.writeStartDocument(); xmlw.writeCharacters("\n"); xmlw.writeCharacters("\n"); // Write a comment xmlw.writeComment("this is a comment"); xmlw.writeCharacters("\n"); // Write the root element "person" with a single attribute "gender" xmlw.writeStartElement("person"); xmlw.writeNamespace("one", "http://namespaceOne"); xmlw.writeAttribute("gender","f"); xmlw.writeCharacters("\n"); // Write the "name" element with some content and two attributes xmlw.writeCharacters(" "); xmlw.writeStartElement("one", "name", "http://namespaceOne"); xmlw.writeAttribute("hair","pigtails"); xmlw.writeAttribute("freckles","yes"); xmlw.writeCharacters("Pippi Longstocking"); // End the "name" element xmlw.writeEndElement(); xmlw.writeCharacters("\n"); // End the "person" element xmlw.writeEndElement(); // End the XML document xmlw.writeEndDocument(); // Close the XMLStreamWriter to free up resources xmlw.close(); } }
次のコードの抜粋で示すように、XMLOutputFactory.createXMLStreamWriter()
メソッドを使用し、XMLドキュメントに基づいてXMLStreamWriter
オブジェクトをインスタンス化します。
XMLStreamWriter xmlw = xmlof.createXMLStreamWriter(new FileOutputStream ("outFile.xml"));
この例では、xmlof
がXMLOutputFactory
インスタンスに当たります。
createXMLStreamWriter()
メソッドの様々なシグネチャにより、以下のXMLドキュメント・フォーマットをパラメータとして扱うことができます。
java.io.OutputStream
(例で示します)
java.io.Writer
javax.xml.transform.Result
(JAXP API http://docs.oracle.com/javase/7/docs/technotes/guides/xml/index.html
で指定)
次のコードの抜粋で示すように、XMLStreamWriter.writeStartDocument()
メソッドを使用し、XMLドキュメントの1行目としてXML宣言を追加します。
xmlw.writeStartDocument();
引数を指定しない場合、このメソッドは次のデフォルトXML宣言を記述します。
<?xml version='1.0' encoding='utf-8'?>
別のエンコーディングまたはXMLバージョンを指定する場合は、引数を次のように指定したwriteStartDocument()
メソッドを使用します。
writeStartDocument(java.lang.String version)
writeStartDocument(java.lang.String encoding, java.lang.String version)
writeStartDocument()
メソッドでエンコーディングを設定しても、基底の出力の実際のエンコーディングは設定されません。このエンコーディング設定用の引数は、XML宣言のencoding
属性に対してどの値が書き込まれるかを指定するものです。出力のエンコーディングを実際に設定するには、対応するXMLOutputFactory.createXMLStreamWriter()
メソッドでXMLStreamWriter
のインスタンスを作成する際にencoding
パラメータを指定する必要があります。
XMLStreamWriter.write
XXX
()
XXX
メソッドを使用すると、開始要素、終了要素、コメント、CDATA、エンティティ参照などの標準的なXMLイベントを出力ストリームに追加できます。writeStartElement()
, writeEndElement()
, writeComment()
, writeCData()
などの特定のイベントを指します。テキスト・データまたは名前をString
として渡すことにより、大部分の要素を作成できます。
XMLStreamWriter
インタフェースでは、データの検証や、ドキュメントが整形式かどうかのチェックは行われません。各開始要素と終了要素が対応しているかどうかなどの確認は、プログラマの役目です。また、開始要素と終了要素のイベントが正しくネストされているかどうかを確認することも、プログラマに任されています。テキスト・ファイルへの書込み時に出力XMLを読みやすくするには、writeCharacters("\n")
メソッドを使用して、適切な場所に新しい行を追加します。
たとえば、次のような小さなXMLを作成するとします。
<!-- This is a comment --> <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コードは次のとおりです。
// Write the root element "person" with a single attribute "gender" xmlw.writeStartElement("person"); xmlw.writeNamespace("one", "http://namespaceOne"); xmlw.writeAttribute("gender","f"); xmlw.writeCharacters("\n"); // Write the "name" element with some content and two attributes xmlw.writeCharacters(" "); xmlw.writeStartElement("one", "name", "http://namespaceOne"); xmlw.writeAttribute("hair","pigtails"); xmlw.writeAttribute("freckles","yes"); xmlw.writeCharacters("Pippi Longstocking"); // End the "name" element xmlw.writeEndElement(); xmlw.writeCharacters("\n"); // End the "person" element xmlw.writeEndElement();
表4-2では、XMLInputFactory
を使用してXMLStreamReader
オブジェクトまたはXMLEventReader
オブジェクトを生成する際に設定可能な標準プロパティを示します。
表4-2のプロパティにはjavax.xml.stream.isValidating
のように、いずれも先頭にjavax.xml.stream
が付きます。
表4-2 Standard 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 |
表4-3では、XMLOutputFactory
を使用してXMLStreamWriter
オブジェクトまたはXMLEventWriter
オブジェクトを生成する際に設定可能な標準プロパティを示します。
表4-3のプロパティにはjavax.xml.stream.isValidating
のように、いずれも先頭にjavax.xml.stream
が付きます。
表4-3 XMLOutputFactoryの標準プロパティ
プロパティ | 説明 | 戻り値の型 | デフォルト値 |
---|---|---|---|
isRepairingNamespaces |
ライターがデフォルト・ネームスペース接頭辞宣言を使用するかどうかを指定します。 XMLの生成時にStAXプロセッサがネームスペースと接頭辞を修正する方法には、いくつかの厳密なルールがあります。詳細は、StAX仕様( |
Boolean |
False |