Oracle® Fusion Middleware Oracle WebLogic Server XML プログラマーズ ガイド 11g リリース 1 (10.3.1) B55533-01 |
|
戻る |
注意 : WebLogic XML Streaming API は WebLogic Server リリース 9.0 の時点で非推奨となっています。代わりに、Java Community Process による標準仕様 Streaming API for XML (StAX) を使用してください。詳細については、「Streaming API for XML (StAX) の使い方」を参照してください。 |
以下の節では、WebLogic XML Streaming API により XML ドキュメントの解析と生成を行う方法について説明します。
WebLogic XML Streaming API は、XML ドキュメントを解析および生成するための簡単でわかりやすい手段を提供します。SAX API と似ていますが、XML ドキュメントに対する手続き的なストリーム ベースの処理が可能であり、SAX イベント ハンドラを作成する必要はありません。SAX イベント ハンドラで複雑な XML ドキュメントを扱うと、ハンドラ自体が複雑になる場合があります。つまり、Streaming API を利用すれば、SAX API よりきめ細かく解析を制御できます。
SAX を使用して XML ドキュメントを解析する場合、プログラムでは、イベント発生時に解析をリスンするイベント リスナを作成し、特定のイベントを請求するのではなくイベントに対して対応する必要があります。一方、Streaming API を使用する場合は、XML ドキュメントを手順の流れに沿って処理すること、特定のタイプのイベント (要素の開始など) を請求すること、要素の属性を繰り返し処理すること、ドキュメントの先頭をスキップすること、任意の時点で処理を停止すること、特定の要素の下位要素を取得すること、指定どおりに要素をフィルタ処理することができます。イベントに対応するのではなく、イベントを請求するので、Streaming API を使用する方法は、「プル解析」と呼ばれることもあります。
Streaming API により、オペレーティング システム上の XML ファイル、DOM ツリー、SAX イベントのセットなど、多くのタイプの XML ドキュメントを解析できます。これらの XML ドキュメントをイベントのストリーム、すなわち XMLInputStream
に変換し、このストリームを順に処理して、要素の開始、ドキュメントの終了などのイベントを必要に応じてスタックから取得します。
WebLogic Streaming API は、デフォルト パーサとして WebLogic FastParser を使用します。
Streaming API を使用した XML ドキュメント解析の詳細なサンプルについては、WL_HOME
\samples\server\examples\src\examples\xml\orderParser
ディレクトリを参照してください。WL_HOME
は、WebLogic Server の最上位ディレクトリです。
表 B-1 で、WebLogic Streaming API の主なインタフェースとクラスについて説明します。
表 B-1 XML Streaming API のインタフェースとクラス
インタフェースまたはクラス | 説明 |
---|---|
XMLInputStreamFactory |
XML ドキュメント解析用の |
XMLInputStream |
イベントの入力ストリームを入れるために使用されるインタフェース。 |
BufferedXMLInputStream |
|
XMLOutputStreamFactory |
XML ドキュメント生成用の |
XMLOutputStream |
イベントを書き込むために使用されるインタフェース。 |
ElementFactory |
この API で使用されるインタフェースのインスタンスを作成するためのユーティリティ。 |
XMLEvent |
要素の開始、要素の終了など、XML ドキュメントでのすべてのタイプのイベントのための基本インタフェース。 |
StartElement |
|
AttributeIterator |
要素の属性のセットを繰り返し処理するために使用されるオブジェクト。 |
属性 |
要素の特定の属性を記述するオブジェクト。 |
以下の Javadoc には、この章で説明した WebLogic XML Streaming API 機能に加え、詳しく説明されていない機能に関するリファレンスが掲載されています。
以下の手順は、WebLogic XML Streaming API により XML ドキュメントの解析と操作を行う一般的手順について説明したものです。
最初の 2 つの手順は必須です。その後の手順は、XML ファイルをどのように処理するかに応じて実行します。
weblogic.xml.stream.*
クラスをインポートします。
XML ファイル、DOM ツリー、または SAX イベントのセットからイベントの XML ストリームを取得します。XML ストリームをフィルタ処理することにより、特定のタイプのイベント、特定の要素の名前などのみを取得することもできます。「XML 入力ストリームの取得」を参照してください。
ストリームを繰り返し処理し、汎用 XMLEvent
タイプを返します。「ストリームの繰り返し処理」を参照してください。
汎用 XMLEvent
タイプのそれぞれについて、イベント タイプを判別します。イベント タイプには、XML ドキュメント、要素の終了、エンティティ参照などがあります。「特定の XMLEvent タイプの判別」を参照してください。
要素の属性を取得します。「要素の属性の取得」を参照してください。
イベント全体のスキップ、特定のイベントのスキップなどにより、ストリームを位置決めします。「ストリームの位置決め」を参照してください。
要素の子を取得します。「サブストリームの取得」を参照してください。
ストリームをクローズします。「入力ストリームのクローズ」を参照してください。
以下の節では、XML Streaming API により XML ドキュメントを解析する例を示します。
このプログラムは、XML ファイルを表す 1 つのパラメータを取り、そのファイルを XML 入力ストリームに変換します。次に、ストリームを繰り返し処理し、XML 要素の開始、XML ドキュメントの終了など、各イベントのタイプを判別します。開始要素、終了要素、および要素の本文を形成する文字データの 3 つのタイプのイベントについては、情報が出力されます。コメントや XML ドキュメントの開始など、その他のタイプのイベントについては、何も行われません。
注意 : 太字のコードについては、例の後の節で詳しく説明します。 |
package examples.xml.stream; import weblogic.xml.stream.Attribute; import weblogic.xml.stream.AttributeIterator; import weblogic.xml.stream.ChangePrefixMapping; import weblogic.xml.stream.CharacterData; import weblogic.xml.stream.Comment; import weblogic.xml.stream.XMLEvent; import weblogic.xml.stream.EndDocument; import weblogic.xml.stream.EndElement; import weblogic.xml.stream.EntityReference; import weblogic.xml.stream.ProcessingInstruction; import weblogic.xml.stream.Space; import weblogic.xml.stream.StartDocument; import weblogic.xml.stream.StartPrefixMapping; import weblogic.xml.stream.StartElement; import weblogic.xml.stream.EndPrefixMapping; import weblogic.xml.stream.XMLInputStream; import weblogic.xml.stream.XMLInputStreamFactory; import weblogic.xml.stream.XMLName; import weblogic.xml.stream.XMLStreamException; import java.io.FileInputStream; import java.io.FileNotFoundException; public class ComplexParse { /** * ストリームでハンドルを取得するためのヘルパー メソッド * 名前で取得し、ストリームを戻す。 この * メソッドは、InputStreamFactory を使用して、 * XMLInputStream のインスタンスを作成する * @param name 解析するファイル * @return XMLInputStream 解析するストリーム */ public XMLInputStream getStream(String name) throws XMLStreamException, FileNotFoundException { XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance(); XMLInputStream stream = factory.newInputStream(new FileInputStream(name)); return stream; } /** * イベントタイプを決まります。 * (要素の開始または終了など。)* イベントのタイプが START_ELEMENT、END_ELEMENT または * CHARACTER_DATA である場合、メソッドは該当する情報を * 出力する。そうでない場合、何もしない * @param event 解析された XML イベント */ public void parse(XMLEvent event) throws XMLStreamException { switch(event.getType()) { case XMLEvent.START_ELEMENT: StartElement startElement = (StartElement) event; System.out.print("<" + startElement.getName().getQualifiedName() ); AttributeIterator attributes = startElement.getAttributesAndNamespaces(); while(attributes.hasNext()){ Attribute attribute = attributes.next(); System.out.print(" " + attribute.getName().getQualifiedName() + "='" + attribute.getValue() + "'"); } System.out.print(">"); break; case XMLEvent.END_ELEMENT: System.out.print("</" + event.getName().getQualifiedName() +">"); break; case XMLEvent.SPACE: case XMLEvent.CHARACTER_DATA: CharacterData characterData = (CharacterData) event; System.out.print(characterData.getContent()); break; case XMLEvent.COMMENT: // コメントを出力 break; case XMLEvent.PROCESSING_INSTRUCTION: //ProcessingInstruction を出力 break; case XMLEvent.START_DOCUMENT: // StartDocument を出力 break; case XMLEvent.END_DOCUMENT: // EndDocument を出力 break; case XMLEvent.START_PREFIX_MAPPING: //StartPrefixMapping を出力 break; case XMLEvent.END_PREFIX_MAPPING: // EndPrefixMapping を出力 break; case XMLEvent.CHANGE_PREFIX_MAPPING: //ChangePrefixMapping を出力 break; case XMLEvent.ENTITY_REFERENCE: //EntityReference を出力 break; case XMLEvent.NULL_ELEMENT: throw new XMLStreamException("Attempt to write a null event."); default: throw new XMLStreamException("Attempt to write unknown event ["+event.getType()+"]"); } } /** * ストリーム全体を繰り返し処理するヘルパー メソッド * @param name 解析するファイル */ public void parse(XMLInputStream stream) throws XMLStreamException { while(stream.hasNext()) { XMLEvent event = stream.next(); parse(event); } stream.close(); } /** メイン メソッド。 XML 入力ストリームに変換される XML ファイルを * 表す 1 つの引数を取る */ public static void main(String args[]) throws Exception { ComplexParse complexParse= new ComplexParse(); complexParse.parse(complexParse.getStream(args[0])); } }
XML Streaming API により、XML ファイル DOM ツリー、SAX イベントなど、さまざまなオブジェクトをイベントのストリームに変換できます。
次の例で、XML ファイルからイベントのストリームを変換する方法を示します。
XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance(); XMLInputStream stream = factory.newInputStream(new FileInputStream(name));
まず、XMLInputStreamFactory
の新しいインスタンスを作成し、次に、このファクトリを使用して、name
変数で参照される XML ファイルから新しい XMLInputStream
を作成します。
次の例では、DOM ツリーからストリームを作成する方法を示します。
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new java.io.File(file)); XMLInputStream stream = XMLInputStreamFactory.newInstance().newInputStream(doc);
XMLInputStream
オブジェクトの繰り返し処理を終了した後は、このストリームに再度アクセスすることはできません。ただし再度ストリームを処理する必要がある場合、たとえば、ストリームを別のアプリケーションに送信したり、別の方法で再度繰り返し処理したりする場合は、XMlInputStream
オブジェクトではなく、BufferedXMLInputStream
オブジェクトを使用できます。
バッファされた XML 入力ストリームを作成するには、XMLInputStreamFactory
クラスの newBufferedInputStream()
メソッドを使用します。以下に例を示します。
XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance(); BufferedXMLInputStream bufstream = factory.newBufferedInputStream(factory.newInputStream(new FileInputStream(name)));
BufferedXMLInputStream
オブジェクトの mark()
メソッドと reset()
メソッドにより、ストリームの特定のスポットをマークし、ストリームの処理を続け、マークしたスポットに戻るようにストリームをリセットできます。「バッファされた XML 入力ストリームのマーキングとリセット」を参照してください。
XML ストリームのフィルタ処理とは、指定したタイプのオブジェクトのみの入ったストリームを作成することです。たとえば、開始要素、終了要素、および XML 要素の本文をマークアップする文字データのみの入ったストリームを作成できます。別の例では、指定した名前を持つ要素のみがストリームに出現するように XML ストリームをフィルタ処理することもできます。
XML ストリームをフィルタ処理するには、XMLInputStreamFactory.newInputStream()
メソッドの 2 番目のパラメータとしてフィルタ クラスを指定します。フィルタ クラスに対するパラメータとして XML ストリームに入れるイベントを指定します。次の例では、TypeFilter
クラスにより、結果の XML ストリームに XML の開始要素と終了要素、および文字データのみを入れるように指定する方法を示します。
import weblogic.xml.stream.util.TypeFilter; XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance(); XMLInputStream stream = factory.newInputStream(new FileInputStream(name), new TypeFilter(XMLEvent.START_ELEMENT | XMLEvent.END_ELEMENT | XMLEvent.CHARACTER_DATA));
表 B-2 で、WebLogic XML Streaming API に用意されているフィルタについて説明します。これらは、weblogic.xml.stream.util
パッケージの一部です。
表 B-2 WebLogic XML Streaming API に用意されているフィルタ
フィルタの名前 | 説明 | 使用例 |
---|---|---|
TypeFilter |
TypeFilter は、入力として整数ビットマスクを取る。例に示すとおり、このビットマスクを作成するには、値の OR (論理和) を取る。 |
new TypeFilter (XMLEvent.START_ELEMENT | XMLEvent.END_ELEMENT | XMLEvent.CHARACTER_DATA) |
NameFilter |
XML ドキュメント内の要素の名前に基づいて XML ストリームをフィルタ処理する。 |
new NameFilter ("Book") |
NameSpaceFilter |
指定されたネームスペース URI に基づいて XML ストリームをフィルタ処理する。 |
new NameSpaceFilter ("http://namespace.org") |
NamespaceTypeFilter |
指定されたイベント タイプとネームスペース URI に基づいて XML ストリームをフィルタ処理する。このフィルタは、 |
new NamespaceFilter ("http://namespace.org", XMLEvent.START_ELEMENT) この例は、すべての開始要素が指定されたネームスペースを持っているストリームを返す。 |
API に入っているフィルタがニーズに合わない場合は、独自のフィルタを作成することもできます。
ElementFilter
インタフェースを実装し、accept(XMLEvent)
というメソッドを持つクラスを作成します。このメソッドは、ストリームに特定のイベントを追加するかどうかを XMLInputStreamFactory.newInputStream()
メソッドに通知します。以下に例を示します。
package my.filters; import weblogic.xml.stream.XMLName; import weblogic.xml.stream.ElementFilter; import weblogic.xml.stream.events.NullEvent; public class SuperDooperFilter implements ElementFilter { protected String name; public SuperDooperFilter(String name) { this.name = name; } public boolean accept(XMLEvent e) { if (name.equals(e.getName().getLocalName())) return true; return false; } }
XML アプリケーションで、新しいフィルタ クラスをインポートしていることを確認します。
import my.filters.SuperDooperFilter
newInputStream()
メソッドの 2 番目のパラメータとしてフィルタを指定します。これは、XML ストリームに入れるイベントのタイプを、フィルタ クラスが必要とするフォーマットでフィルタ クラスに渡します。
XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance(); XMLInputStream stream = factory.newInputStream(new FileInputStream(name), new SuperDooperFilter(param));
イベントのストリームが完成したら、次に XMLInputStream.next()
メソッドと XMLInputStream.hasNext()
メソッドを使用して、イベントのストリームを手順に沿って処理します。以下に例を示します。
while(stream.hasNext()) { XMLEvent event = stream.next(); System.out.print(event); }
XMLInputStream.next()
メソッドは、XMLEvent
タイプのオブジェクトを返します。XMLEvent
には、このイベントが、XML ドキュメントの開始、要素の終了、エンティティ参照などのどれであるかをさらに分類するサブインタフェースがあります。XMLEvent
インタフェースには、対応するフィールド、すなわち定数、ならびに実際のイベントを識別するために使用できるメソッドのセットも入っています。図 B-1 では、XMLEvent
インタフェースとそのサブインタフェースの階層を示します。
表 B-3 に、XML ストリームの解析時に特定のイベントを識別するために使用できるXMLEvent
クラスのサブクラスとフィールドをリストします。
表 B-3 XMLEvent クラスのサブクラスとフィールド
XMLEvent サブクラス | サブクラスを識別するために使用される XMLEvent クラスのフィールド | サブクラスを識別するために使用されるメソッド | サブクラス イベントの説明 |
---|---|---|---|
ChangePrefixMapping |
CHANGE_PREFIX_MAPPING |
isChangePrefixMapping |
プレフィックス マッピングが古いネームスペースから新しいネームスペースに変更されたことを示す。 |
CharacterData |
CHARACTER_DATA |
isCharacterData |
返された |
Comment |
COMMENT |
isComment |
返された |
EndDocument |
END_DOCUMENT |
isEndDocument |
XML ドキュメントの終了を示す。 |
EndElement |
END_ELEMENT |
isEndElement |
XML ドキュメントの要素の終了を示す。 |
EndPrefixMapping |
END_PREFIX_MAPPING |
isEndPrefixMapping |
プレフィックス マッピングがスコープの範囲外になったことを示す。 |
EntityReference |
ENTITY_REFERENCE |
isEntityReference |
返された |
ProcessingInstruction |
PROCESSING_INSTRUCTION |
isProcessingInstruction |
返された |
Space |
SPACE |
isSpace |
返された |
StartDocument |
START_DOCUMENT |
isStartDocument |
XML ドキュメントの開始を示す。 |
StartElement |
START_ELEMENT |
isStartElement |
XML ドキュメントの要素の開始を示す。 |
StartPrefixMapping |
START_PREFIX_MAPPING |
isStartPrefixMapping |
プレフィックス マッピングがそのスコープを開始したことを示す。 |
次の例では、Java case
文を使用して、XMLInputStream.next()
メソッドにより返されたイベントのタイプを判別する方法を示します。簡単にするため、この例では、見つかったイベントをそのまま出力します。イベントをさらに処理する方法は、その後の節で示します。
switch(event.getType()) { case XMLEvent.START_ELEMENT: // 要素の開始 System.out.println ("Start Element\n"); break; case XMLEvent.END_ELEMENT: // 要素の終了 System.out.println ("End Element\n"); break; case XMLEvent.PROCESSING_INSTRUCTION: // 処理指示 System.out.println ("Processing instruction\n"); break; case XMLEvent.SPACE: // ホワイトスペース System.out.println ("White space\n"); break; case XMLEvent.CHARACTER_DATA: // 文字データ System.out.println ("Character data\n"); break; case XMLEvent.COMMENT: // コメント System.out.println ("Comment\n"); break; case XMLEvent.START_DOCUMENT: // XML ドキュメントの開始 System.out.println ("Start Document\n"); break; case XMLEvent.END_DOCUMENT: // XML ドキュメントの終了 System.out.println ("End Document\n"); break; case XMLEvent.START_PREFIX_MAPPING: // プレフィックス マッピング スコープの開始 System.out.println ("Start prefix mapping\n"); break; case XMLEvent.END_PREFIX_MAPPING: // プレフィックス マッピング スコープの終了 System.out.println ("End prefix mapping\n"); break; case XMLEvent.CHANGE_PREFIX_MAPPING: // プレフィックス マッピングがネームスペースを変更 System.out.println ("Change prefix mapping\n"); break; case XMLEvent.ENTITY_REFERENCE: // エンティティ参照 System.out.println ("Entity reference\n"); break; default: throw new XMLStreamException("Attempt to parse unknown event [" + event.getType() + "]"); }
XML ドキュメントの要素の属性を取得するには、まず、XMLInputStream.next()
メソッドにより返された XMLEvent
オブジェクトを StartElement
オブジェクトにキャストする必要があります。
要素に属性がいくつあるかが分からないため、まず、属性のリスト全体を入れる AttributeIterator
オブジェクトを作成してから、属性がなくなるまでリストを繰り返し処理します。次の例で、「ストリームの繰り返し処理」に示した switch
文の START_ELEMENT
case の一部としてこれを行う方法を示します。
case XMLEvent.START_ELEMENT: StartElement startElement = (StartElement) event; System.out.print("<" + startElement.getName().getQualifiedName() ); AttributeIterator attributes = startElement.getAttributesAndNamespaces(); while(attributes.hasNext()){ Attribute attribute = attributes.next(); System.out.print(" " + attribute.getName().getQualifiedName() + "='" + attribute.getValue() + "'"); } System.out.print(">"); break;
この例では、まず、返された XMLEvent
を StartElement
にキャストすることにより、StartElement
オブジェクトを作成します。次に、StartElement.getAttributesAndNamespaces()
メソッドを使用して AttributeIterator
オブジェクトを作成し、AttributeIterator.hasNext()
メソッドを使用して属性を繰り返し処理します。各 Attribute
について、Attributes.getName().getQualifiedName()
メソッドと Attribute.getValue()
メソッドを使用し、属性の名前と値を返します。
getNamespace()
メソッドや getAttributes()
メソッドを使用すると、ネームスペースや属性のみを返すこともできます。
表 B-4 で、ストリームの特定の位置までスキップするために使用できる XMLInputStream
インタフェースのメソッドについて説明します。
表 B-4 入力ストリームの位置決めのために使用されるメソッド
XMLInputStream のメソッド | 説明 |
---|---|
skip() |
入力ストリームを次のストリーム イベントに位置決めする。 注意 : 次のイベントは、XML ファイル内の実際の要素であるとは限らない。コメントやホワイトスペースの場合もある。 |
skip(int) |
入力ストリームをこのタイプの次のイベントに位置決めする。 イベント タイプの例としては、 |
skip(XMLName) |
入力ストリームをこの名前の次のイベントに位置決めする。 |
skip(XMLName, int) |
入力ストリームをこの名前とタイプの次のイベントに位置決めする。 |
skipElement() |
次の要素にスキップする (現在の要素の下位要素にはスキップしない)。 |
peek() |
ストリームから実際には読み込まずに、次のイベントをチェックする。 |
次の例では、入力ストリームを繰り返し処理する基本コードを修正し、XML 要素の本文の文字データをスキップする方法を示します。
while(stream.hasNext()) { XMLEvent peek = stream.peek(); if (peek.getType() == XMLEvent.CHARACTER_DATA ) { stream.skip(); continue; } XMLEvent event = stream.next(); parse(event); }
この例は、XMLInputStream.peek()
メソッドを使用してストリーム上の次のイベントを判別する方法を示しています。イベントのタイプが XMLEvent.CHARACTER_DATA
である場合、そのイベントはスキップされ、次のイベントに進みます。
すべての下位要素も含め、次の要素のコピーを取得するには、XMLInputStream.getSubStream()
メソッドを使用します。getSubstream()
メソッドは、XMLInputStream
オブジェクトを返します。親ストリーム (または getSubStream()
を呼び出したストリーム) での位置は移動しません。親ストリームでは、getSubStream()
で取得した要素をスキップする場合、skipElement()
メソッドを使用します。
getSubStream()
メソッドは、検出された START_ELEMENT
イベントと END_ELEMENT
イベントの数を記録し、その数が等しくなると (すなわち、完全な次の要素が見つかると) 停止して、結果のサブストリームを XMLInputStream
オブジェクトとして返します。
たとえば、XML Streaming API を使用して以下の XML ドキュメントを解析するとします。ただし、<content>
タグと </content>
タグに囲まれたサブストリームのみを対象にします。
<book> <title>The History of the World</title> <author>Juliet Shackell</author> <publisher>CrazyDays Publishing</publisher> <content> <chapter title='Just a Speck of Dust'> <synopsis>The world as a speck of dust</synopsis> <para>Once the world was just a speck of dust...</para> </chapter> <chapter title='Life Appears'> <synopsis>Move over dust, here comes life.</synopsis> <para>Happily, the dust got a companion: life...</para> </chapter> </content> </book>
次のコード (抜粋) は、<content>
開始要素タグにスキップし、サブストリームを取得し、独立した ComplexParse
オブジェクトを使用してそのサブストリームを解析する方法を示しています。
if (stream.skip( ElementFactory.createXMLName("content"))) { ComplexParse complexParse = new ComplexParse(); complexParse.parse(stream.getSubStream()); }
前の XML ドキュメントでこのメソッドを呼び出すと、以下の出力が得られます。
<content> <chapter title='Just a Speck of Dust'> <synopsis>The world as a speck of dust</synopsis> <para>Once the world was just a speck of dust...</para> </chapter> <chapter title='Life Appears'> <synopsis>Move over dust, here comes life.</synopsis> <para>Happily, the dust got a companion: life...</para> </chapter> </content>
BufferedXMLInputStream
オブジェクトを使用する場合、mark()
メソッドと reset()
メソッドにより、ストリームの特定のスポットをマークし、ストリームの処理を続けた後、マークしたスポットに戻るようにストリームをリセットできます。この 2 つのメソッドは、最初に繰り返し処理をした後で、ストリームをさらに操作したい場合に便利です。
注意 : バッファされたストリームをマーキングせずに読み取った場合、直前に読み取ったものにアクセスすることはできません。つまり、ストリームはバッファされるだけであり、自動的にストリームを再読み取りできることを意味するわけではありません。まずストリームをマークしておく必要があります。 |
次の例で、BufferedXMLInputStream
オブジェクトの一般的な使い方を示します。
XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance(); BufferedXMLInputStream bufstream = factory.newBufferedInputStream(factory.newInputStream(new FileInputStream(name))); // ストリームの開始をマーク bufstream.mark(); // ストリームをローカルに処理 bufferedParse.parse(bufstream); // ストリームをマークにリセット bufstream.reset(); //ストリームを別のアプリケーションに送信 ComplexParse complexParse = new ComplexParse(); complexParse.parse(bufstream);
プログラミング慣行として、XML 入力ストリームでの作業終了時に入力ストリームを明示的にクローズします。入力ストリームをクローズするには、XMLInputStream.close()
メソッドを使用します。以下に例を示します。
// 入力ストリームのクローズ input.close();
次の手順では、WebLogic XML Streaming API により新しい XML ドキュメントを生成する一般的手順について説明します。
最初の 2 つの手順は必須です。その後の手順は、XML ファイルをどのように生成するかに応じて実行します。
weblogic.xml.stream.*
クラスをインポートします。
XML ドキュメントを書き込むための XML 出力ストリームを作成します。「XML 出力ストリームの作成」を参照してください。
XML 出力ストリームにイベントを追加します。「出力ストリームへの要素の追加」を参照してください。
XML 出力ストリームに属性を追加します。「出力ストリームの要素への属性の追加」を参照してください。
出力ストリームに入力ストリームを追加します。「出力ストリームへの入力ストリームの追加」を参照してください。
出力ストリームを出力します。「出力ストリームの出力」を参照してください。
出力ストリームをクローズします。「出力ストリームのクローズ」を参照してください。
以下の節では、XML Streaming API により XML ドキュメントを生成する例を示します。
このプログラムでは、まず、PrintWriter
オブジェクトに基づいて出力ストリームを作成し、次に、その出力ストリームに要素を追加して、プログラムのコメントに説明されているように、単純な XML 発注書を作成します。また、別の XML ファイルに基づく入力ストリームを出力ストリームに追加する方法も示します。
注意 : サンプルの後の節に、さらに詳しい説明があります。 |
package examples.xml.stream; import weblogic.xml.stream.XMLInputStream; import weblogic.xml.stream.XMLOutputStream; import weblogic.xml.stream.XMLInputStreamFactory; import weblogic.xml.stream.XMLName; import weblogic.xml.stream.XMLEvent; import weblogic.xml.stream.StartElement; import weblogic.xml.stream.EndElement; import weblogic.xml.stream.Attribute; import weblogic.xml.stream.ElementFactory; import weblogic.xml.stream.XMLStreamException; import weblogic.xml.stream.XMLOutputStreamFactory; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.PrintWriter; /** * 次のような非常に単純な発注書を出力するプログラム * * * <purchase_order> * <name>Juliet Shackell</name> * <item id="1234" quantity="2">Fabulous Chair</item> * <!-- ここはコメント--> * <another_file> * 「another_file.xml」という別のファイルから取得 * </another_file> * </purchase_order> * * 上の XML ファイルで、<another_file> 要素は、実際には * 別の XML ファイルであり、そのファイルからプログラムに引数が渡され、 * XMLInputStream に変換された後、出力ストリームに追加される */ public class PrintPurchaseOrder { /** * ストリームでハンドルを取得するためのヘルパー メソッド * 名前で取得し、ストリームを戻す。この * メソッドは、InputStreamFactory を使用して、 * XMLInputStream のインスタンスを作成する * @param name 解析するファイル * @return XMLInputStream 解析するストリーム */ public XMLInputStream getInputStream(String name) throws XMLStreamException, FileNotFoundException { XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance(); XMLInputStream stream = factory.newInputStream(new FileInputStream(name)); return stream; } public static void main(String args[]) throws Exception { PrintPurchaseOrder printer = new PrintPurchaseOrder(); // // 出力ストリームを作成する // XMLOutputStreamFactory factory = XMLOutputStreamFactory.newInstance(); XMLOutputStream output = factory.newOutputStream(new PrintWriter(System.out,true)); // <purchase_order> ルート要素を追加する output.add(ElementFactory.createStartElement("purchase_order")); output.add(ElementFactory.createCharacterData("\n")); // <name> 要素を追加する output.add(ElementFactory.createStartElement("name")); output.add(ElementFactory.createCharacterData("Juliet Shackell")); output.add(ElementFactory.createEndElement("name")); output.add(ElementFactory.createCharacterData("\n")); // ID 属性および数量属性の入った <item> 要素を追加する output.add(ElementFactory.createStartElement("item")); output.add(ElementFactory.createAttribute("id","1234")); output.add(ElementFactory.createAttribute("quantity","2")); output.add(ElementFactory.createCharacterData("Fabulous Chair")); output.add(ElementFactory.createEndElement("item")); output.add(ElementFactory.createCharacterData("\n")); // コメントを入力する output.add("<!-- ここはコメント-->"); output.add(ElementFactory.createCharacterData("\n")); // 各 XML ファイル引数から入力ストリームを作成し、それを出力に追加する for (int i=0; i < args.length; i++) // // 入力ストリームを取得し、それを出力ストリームに追加する // output.add(printer.getInputStream(args[i])); // 最後に、"purchase_order" ルート要素を終了する output.add(ElementFactory.createEndElement("purchase_order")); output.add(ElementFactory.createCharacterData("\n")); // // 結果を画面に出力する // output.flush(); // 出力ストリームをクローズする output.close(); } }
上のプログラムは、次の出力を生成します。
<purchase_order> <name>Juliet Shackell</name> <item id="1234" quantity="2">Fabulous Chair</item> <!-- ここはコメント--> <another_file> 別のファイルから取得 </another_file> </purchase_order>
WebLogic XML Streaming API により XML ドキュメントを生成する最初の手順の 1 つは、構築されるドキュメントを入れるための出力ストリームを作成することです。XML 出力ストリームの作成方法は、入力ストリームの作成方法と似ています。まず、XMLOutputStreamFactory
のインスタンスを作成し、次に XMLOutputStreamFactory.newOutputStream()
メソッドで出力ストリームを作成します。以下に例を示します。
XMLOutputStreamFactory factory = XMLOutputStreamFactory.newInstance(); XMLOutputStream output = factory.newOutputStream(new PrintWriter(System.out,true));
次の例では、DOM ツリーに基づいて XMLOutputStream
を作成する方法を示します。
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().newDocument(); XMLOutputStream out = XMLOutputStreamFactory.newInstance().newOutputStream(doc);
XMLOutputStreamFactory.newOutputStream()
メソッドを使用して、以下の 4 つの Java オブジェクトに基づく出力ストリームを作成できます。オブジェクトは、XML ドキュメントの最終形式を何にするか (オペレーティング システム上のファイル、DOM ツリーなど) に応じて決定します。
java.io.OutputStream
java.io.Writer
org.xml.sax.ContentHandler
org.w3c.dom.Document
出力ストリームに要素を追加するには、XMLOutputStream.add(XMLEvent)
メソッドを使用します。特定の要素を作成するには、ElementFactory
を使用します。
ElementFactory
インタフェースには、各タイプの要素を作成するためのメソッドがあります。一般的なフォーマットは ElementFactory.create
XXX
()
です。XXX
は、createStartElement()
、createCharacterData()
などの特定の要素を表します。String
または XMLName
のような名前を渡すことにより、大部分の要素を作成できます。
ヒント : XMLOutputStream は XML を検証しません。 |
注意 : 開始要素を作成するたびに、終了要素もどこかに明示的に作成する必要があります。同じ規則が開始ドキュメントの作成にも適用されます。 |
たとえば、次のような小さな XML を作成するとします。
<name>Juliet Shackell</name>
出力ストリームにこの要素を追加する Java コードは次のようになります。
output.add(ElementFactory.createStartElement("name")); output.add(ElementFactory.createCharacterData("Juliet Shackell")); output.add(ElementFactory.createEndElement("name")); output.add(ElementFactory.createCharacterData("\n"));
最後の createCharacterData()
メソッドは、出力ストリームに改行文字を追加します。この指定は必須ではありませんが、読みやすい XML を作成するときに便利です。
作成した要素に属性を追加するには、XMLOutputStream.add(Attribute)
を使用します。特定の属性を作成するには、ElementFactory.createAttribute()
メソッドを使用します。
たとえば、次のような小さな XML を作成するとします。
<item id="1234" quantity="2">Fabulous Chair</item>
出力ストリームにこの要素を追加する Java コードは次のようになります。
output.add(ElementFactory.createStartElement("item")); output.add(ElementFactory.createAttribute("id","1234")); output.add(ElementFactory.createAttribute("quantity","2")); output.add(ElementFactory.createCharacterData("Fabulous Chair")); output.add(ElementFactory.createEndElement("item")); output.add(ElementFactory.createCharacterData("\n"));
注意 : 要素への属性の追加は、開始要素を作成した後、対応する終了要素を作成する前に行ってください。そうしない場合、コードは正常にコンパイルされますが、プログラム実行時にエラーが発生します。たとえば、次のコードでは、<item> 要素が明示的に終了した後に、この要素に属性が追加されているので、エラーが返されます。
output.add(ElementFactory.createStartElement("item")); output.add(ElementFactory.createEndElement("item")); output.add(ElementFactory.createAttribute("id","1234")); output.add(ElementFactory.createAttribute("quantity","2")); output.add(ElementFactory.createCharacterData("Fabulous Chair")); output.add(ElementFactory.createCharacterData("\n")); |
XML 出力ストリームを作成する際、XML ファイルや DOM ツリーのような既存の XML ドキュメントを出力ストリームに追加したいことがあります。これを行うには、まず、その XML ドキュメントを XML 入力ストリームに変換してから、XMLOutputStream.add(XMLInputStream)
メソッドを使用して出力ストリームに入力ストリームを追加します。
次の例では、まず、XML ファイルから XML 入力ストリームを作成する getInputStream() というメソッドを示し、その後、このメソッドを使用して作成された入力ストリームを出力プログラムに追加する方法を示します。
/** * ストリームでハンドルを取得するためのヘルパー メソッド * 名前で取得し、ストリームを戻す。この * メソッドは、InputStreamFactory を使用して、 * XMLInputStream のインスタンスを作成する * @param name 解析するファイル * @return XMLInputStream 解析するストリーム */ public XMLInputStream getInputStream(String name) throws XMLStreamException, FileNotFoundException { XMLInputStreamFactory factory = XMLInputStreamFactory.newInstance(); XMLInputStream stream = factory.newInputStream(new FileInputStream(name)); return stream; } .... // 各 XML ファイル引数から入力ストリームを作成し、それを出力に追加する for (int i=0; i < args.length; i++) // // 入力ストリームを取得し、それを出力ストリームに追加する // output.add(printer.getInputStream(args[i]));
XML 出力ストリームを作成元のオブジェクトに出力するには、XMLOutputStream.flush()
メソッドを使用します。たとえば、PrintWriter
オブジェクトから XML 出力ストリームを作成した場合、そのストリームは、flush()
メソッドにより標準出力に出力されます。
注意 : DOM ツリーに基づいて XMLOutputStream に書き込む場合、DOM を操作するには、その前にflush() メソッドを実行する必要があります。 |
次の例では、出力ストリームを出力する方法を示します。
// // 結果を画面に出力する // output.flush();
プログラミング慣行として、XML 出力ストリームでの作業終了時に出力ストリームを明示的にクローズします。出力ストリームをクローズするには、XMLOutputStream.close()
メソッドを使用します。以下に例を示します。
// 出力ストリームをクローズする output.close();