僕のStAX(Java)

自分用の備忘録
StAXではXMLの読み込みにXMLStreamReaderとXMLEventReaderのどちらかを使う。
今回はXMLStreamReaderを使用。


##そもそものSAX,StAX,DOMの使い分けというか違い
[こちら](https://www.javainthebox.net/laboratory/JavaSE6/stax/stax.html)が参考になります。
[こっち](https://engineer-club.jp/java-xml-read#-StAXXMLXMLStreamReader)も参考になった。

##今回使用するサンプルのXML
[こちら](http://www.sotechsha.co.jp/xml/sample.xml)のサイトにあった和歌のXMLを拝借させていただきます。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<万葉集>
 <巻 no="1">
	<歌>
		<歌番号>8</歌番号>
		<原文>熟田津尓 船乗世武登 月待者 潮毛可奈比沼 今者許藝乞菜</原文>
		<作者>額田王(ぬかたのおおきみ)</作者>
		<読み>熟田津(にきたつ)に、船(ふな)乗りせむと、月待てば、潮もかなひぬ、今は漕(こ)ぎ出(い)でな</読み>
		<イメージ>image/m0008.jpg</イメージ>
		<意味>熟田津(にきたつ)で、船を出そうと月を待っていると、いよいよ潮の流れも良くなってきた。さあ、いまこそ船出するのです。</意味>
	</歌>
	<歌>
		<歌番号>20</歌番号>
		<原文>茜草指 武良前野逝 標野行 野守者不見哉 君之袖布流</原文>
		<作者>額田王(ぬかたのおおきみ)</作者>
		<読み>茜(あかね)さす、紫野行き標野(しめの)行き、野守(のもり)は見ずや、君が袖振る</読み>
		<イメージ>image/m0020.jpg</イメージ>
		<意味>（茜色の光に満ちている）紫野、天智天皇御領地の野で、あぁ、あなたはそんなに袖を振ってらして、野守が見るかもしれませんよ。</意味>
	</歌>
	<歌>
		<歌番号>23</歌番号>
		<原文>打麻乎 麻續王 白水郎有哉 射等篭荷四間乃 珠藻苅麻須</原文>
		<作者>作者不明</作者>
		<読み>打ち麻(そ)を、麻続(をみの)の王(おほきみ)、海人(あま)なれや、伊良虞(いらご)の島の、玉藻(たまも)刈ります</読み>
		<イメージ>image/m0023.jpg</イメージ>
		<意味>麻続(をみの)の王(おほきみ)さまは海人(あま)なのでしょうか、(いいえ、そうではいらっしゃらないのに、)伊良虞の島の藻をとっていらっしゃる・・・・・ </意味>
	</歌>
	<歌>
		<歌番号>24</歌番号>
		<原文>空蝉之 命乎惜美 浪尓所濕 伊良虞能嶋之 玉藻苅食</原文>
		<作者>作者不明</作者>
		<読み>うつせみの、命を惜しみ、波に濡れ、伊良虞(いらご)の島の、玉藻(たまも)刈(か)り食(は)む</読み>
		<イメージ>image/m0024.jpg</イメージ>
		<意味>命惜しさに、波に濡れながら、伊良虞(いらご)の島の藻をとって食べるのです・・・麻続(をみの)の王(おほきみ)が伊良虞の島に流された時、島の人がこれを哀しんで詠んだ歌を聞いて詠んだ歌ということです。</意味>
	</歌>
	<歌>
		<歌番号>28</歌番号>
		<原文>春過而 夏来良之 白妙能 衣乾有 天之香来山</原文>
		<作者>持統天皇(じとうてんのう)</作者>
		<読み>春過ぎて 夏来たるらし 白妙(しろたえ)の 衣干したり 天(あめ)の香具山(かぐやま)</読み>
		<イメージ>image/m0028.jpg</イメージ>
		<意味>春が過ぎて、夏が来たらしい。白妙(しろたえ)の衣が香久山(かぐやま)の方に見える。 </意味>
	</歌>
	<歌>
		<歌番号>37</歌番号>
		<原文>雖見飽奴 吉野乃河之 常滑乃 絶事無久 復還見牟</原文>
		<作者>柿本人麻呂(かきのもとのひとまろ)</作者>
		<読み>見れど飽かぬ、吉野の川の、常滑(とこなめ)の、絶ゆることなく、またかへり見む</読み>
		<イメージ>image/m0037.jpg</イメージ>
		<意味>何度見ても飽きることの無い吉野の川の常滑(とこなめ)のように、絶えること無く何度も何度も見にきましょう。</意味>
	</歌>
 </巻>
</万葉集>


```

##コード全文

```java
import java.nio.file.Paths;
import java.io.FileInputStream;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamConstants;

public class StAXSample{
    public static void main(String args[]) throws Exception {
        XMLStreamReader reader = null;
    
        try{
            XMLInputFactory factory = XMLInputFactory.newInstance();
            reader = factory.createXMLStreamReader(new FileInputStream(Paths.get("waka.xml").toFile()));

            String tagName = null;
            String content = null;

            while(reader.hasNext()){
                int eventType = reader.next();

                switch(eventType){
                    case XMLStreamConstants.START_ELEMENT:
                        tagName = reader.getName().getLocalPart();
                        break;

                    case XMLStreamConstants.CHARACTERS:
                        content = reader.getText();
                        break;
                        
                    case XMLStreamConstants.END_ELEMENT:
                        if(reader.getName().getLocalPart().equals("歌")){
                        break;        
                        }else if(reader.getName().getLocalPart().equals("巻")){
                        break;        
                        }else if(reader.getName().getLocalPart().equals("万葉集")){
                        break;        
                        }
                        System.out.println(tagName + " : " + content);
                        if (reader.getName().getLocalPart().equals("意味")){
                            System.out.println("==================================================");
                        break;
                        }
                    default:
                        break;
                }
            }
        }finally{
            if(reader != null){
                reader.close();
            }
        }
    }
}
```

##出力結果

```
歌番号 : 8
原文 : 熟田津尓 船乗世武登 月待者 潮毛可奈比沼 今者許藝乞菜
作者 : 額田王(ぬかたのおおきみ)
読み : 熟田津(にきたつ)に、船(ふな)乗りせむと、月待てば、潮もかなひぬ、今は漕(こ)ぎ出(い)でな
イメージ : image/m0008.jpg
意味 : 熟田津(にきたつ)で、船を出そうと月を待っていると、いよいよ潮の流れも良くなってきた。さあ、いまこそ船出するのです。
==================================================
歌番号 : 20
原文 : 茜草指 武良前野逝 標野行 野守者不見哉 君之袖布流
作者 : 額田王(ぬかたのおおきみ)
読み : 茜(あかね)さす、紫野行き標野(しめの)行き、野守(のもり)は見ずや、君が袖振る
イメージ : image/m0020.jpg
意味 : （茜色の光に満ちている）紫野、天智天皇御領地の野で、あぁ、あなたはそんなに袖を振ってらして、野守が見るかもしれませんよ 。
==================================================
歌番号 : 23
原文 : 打麻乎 麻續王 白水郎有哉 射等篭荷四間乃 珠藻苅麻須
作者 : 作者不明
読み : 打ち麻(そ)を、麻続(をみの)の王(おほきみ)、海人(あま)なれや、伊良虞(いらご)の島の、玉藻(たまも)刈ります
イメージ : image/m0023.jpg
意味 : 麻続(をみの)の王(おほきみ)さまは海人(あま)なのでしょうか、(いいえ、そうではいらっしゃらないのに、)伊良虞の島の藻をとっ ていらっしゃる・・・・・
==================================================
歌番号 : 24
原文 : 空蝉之 命乎惜美 浪尓所濕 伊良虞能嶋之 玉藻苅食
作者 : 作者不明
読み : うつせみの、命を惜しみ、波に濡れ、伊良虞(いらご)の島の、玉藻(たまも)刈(か)り食(は)む
イメージ : image/m0024.jpg
意味 : 命惜しさに、波に濡れながら、伊良虞(いらご)の島の藻をとって食べるのです・・・麻続(をみの)の王(おほきみ)が伊良虞の島に流 された時、島の人がこれを哀しんで詠んだ歌を聞いて詠んだ歌ということです。
==================================================
歌番号 : 28
原文 : 春過而 夏来良之 白妙能 衣乾有 天之香来山
作者 : 持統天皇(じとうてんのう)
読み : 春過ぎて 夏来たるらし 白妙(しろたえ)の 衣干したり 天(あめ)の香具山(かぐやま)
イメージ : image/m0028.jpg
意味 : 春が過ぎて、夏が来たらしい。白妙(しろたえ)の衣が香久山(かぐやま)の方に見える。
==================================================
歌番号 : 37
原文 : 雖見飽奴 吉野乃河之 常滑乃 絶事無久 復還見牟
作者 : 柿本人麻呂(かきのもとのひとまろ)
読み : 見れど飽かぬ、吉野の川の、常滑(とこなめ)の、絶ゆることなく、またかへり見む
イメージ : image/m0037.jpg
意味 : 何度見ても飽きることの無い吉野の川の常滑(とこなめ)のように、絶えること無く何度も何度も見にきましょう。
==================================================
```

##部分的に解説
####ライブラリインポート

```java
import java.nio.file.Paths;
import java.io.FileInputStream;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamConstants;
```


####XMLファイルの読み込み
```java
public class StAXSample{
    public static void main(String args[]) throws Exception {
        XMLStreamReader reader = null;

        try{
            //XMLInputFactoryを生成
            XMLInputFactory factory = XMLInputFactory.newInstance();
            //XMLStreamReaderにファイルの内容を取得
            reader = factory.createXMLStreamReader(new FileInputStream(Paths.get("waka.xml").toFile()));
            //print用変数
            String tagName = null;
            String content = null;
```
`reader = factory.createXMLStreamReader(new FileInputStream(Paths.get("file.xml").toFile())));`はこの一連の手続きでお決まりの１セットみたいな感じ。
軽く説明すると
・`Paths.get([filena_name).toFile())`で読み込むファイルを指定。PathsとFileの互換性。
・`FileInputStream`でストリームに 
・`createXMLStreamReader`はXMLStreamReaderのインスタンスをつくんだけど、引数はストリームである必要がある。

####イベントの種類と条件分岐

```java
            //次のイベントがあれば
            while(reader.hasNext()){
                //次のイベントのタイプを取得
                int eventType = reader.next();
                //イベントごとのケース式
                switch(eventType){
                    //スタートのタグだったら
                    case XMLStreamConstants.START_ELEMENT:
                        tagName = reader.getName().getLocalPart();
                        break;
                    //テキストだったら
                    case XMLStreamConstants.CHARACTERS:
                        content = reader.getText();
                        break;
                    //終了タグだったら
                    case XMLStreamConstants.END_ELEMENT:
                        //要素名で条件分岐
                        if(reader.getName().getLocalPart().equals("歌")){
                        break;        
                        }else if(reader.getName().getLocalPart().equals("巻")){
                        break;        
                        }else if(reader.getName().getLocalPart().equals("万葉集")){
                        break;        
                        }
                        System.out.println(tagName + " : " + content);
                        if (reader.getName().getLocalPart().equals("意味")){
                            System.out.println("==================================================");
                        break;
                        }
                    default:
                        break;
                }
            }
```

基本的にXMLInputStreamReaderオブジェクトの`hasNext`メソッドで次のイベントがあるかを判定して、
あれば`next`メソッド`で次のイベントを読み込むってな流れ。


####XMLInputStreamReaderを閉じる

```java
}finally{
            if(reader != null){
                reader.close();
            }
        }
    }
}
```