僕のDOM(Java)

自分用の備忘録

##DOMライブラリは何に使うの？
XMLを解析するためのライブラリ

##今回使用するサンプルの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</イメージ>
		<意味>命惜しさに、波に濡れながら、伊良虞(いらご)の島の藻をとって食べるのです・・・ <br />麻続(をみの)の王(おほきみ)が伊良虞の島に流された時、島の人がこれを哀しんで詠んだ歌を聞いて詠んだ歌ということです。 </意味>
	</歌>

	<歌>
		<歌番号>28</歌番号>
		<原文>春過而 夏来良之 白妙能 衣乾有 天之香来山</原文>
		<作者>持統天皇(じとうてんのう)</作者>
		<読み>

			春過ぎて 夏来たるらし 白妙(しろたえ)の 衣干したり 天(あめ)の香具山(かぐやま)

		</読み>

		<イメージ>image/m0028.jpg</イメージ>

		<意味>春が過ぎて、夏が来たらしい。白妙(しろたえ)の衣が香久山(かぐやま)の方に見える。 </意味>

	</歌>

	<歌>
		<歌番号>37</歌番号>
		<原文>雖見飽奴 吉野乃河之 常滑乃 絶事無久 復還見牟</原文>
		<作者>柿本人麻呂(かきのもとのひとまろ)</作者>
		<読み>
			見れど飽かぬ、吉野の川の、常滑(とこなめ)の、絶ゆることなく、またかへり見む
		</読み>
		<イメージ>image/m0037.jpg</イメージ>
		<意味>何度見ても飽きることの無い吉野の川の常滑(とこなめ)のように、絶えること無く何度も何度も見にきましょう。</意味>
	</歌>
 </巻>
</万葉集>

```

##コードサンプル

###全文
```java

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class DOMSample{
    public static void main(String[] args) throws Exception {

        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.parse("waka.xml");
        
        Element root = document.getDocumentElement();
        System.out.println("Root element is "+root.getNodeName());
    

        NodeList childNodeList = root.getChildNodes();
        for(int child_i = 0; child_i < childNodeList.getLength(); child_i++){
            Node childNode = childNodeList.item(child_i);
            
            if(childNode.getNodeType() == Node.ELEMENT_NODE){
                System.out.println("Its child element is "+childNode.getNodeName());
                System.out.println("");
                
                NodeList grandchildNodeList = childNode.getChildNodes();
                for(int grachild_i = 0; grachild_i < grandchildNodeList.getLength(); grachild_i++){
                    if(grandchildNodeList.item(grachild_i).getNodeType() == Node.ELEMENT_NODE){

                        NodeList gre_grandchildNodeList = grandchildNodeList.item(grachild_i).getChildNodes();
                        for(int gre_grachild_i = 0; gre_grachild_i < gre_grandchildNodeList.getLength(); gre_grachild_i++){
                            Node node = gre_grandchildNodeList.item(gre_grachild_i);
                            if(node.getNodeType() == Node.ELEMENT_NODE){
                                System.out.println(node.getNodeName() + " : " + node.getTextContent());
                            }
                        }
                        System.out.println("--------------------------------------------------------");
                        
                    }
                }
            }
            
        }

    }
}
```

出力結果

```
Root element is 万葉集
Its child element is 巻

歌番号 : 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 javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
//ドキュメント操作のためのライブラリ
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
```

####ドキュメントの読み込み

```java
public class DOMSample{
    public static void main(String[] args) throws Exception{
        //ドキュメント読み込み
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.parse("waka.xml")

```
ここはお決まりの文って感じ

####ルート要素の取得

```java
        //ルート要素取得
        Element root = document.getDocumentElement();
        //ルートノードのノード名を表示
        System.out.println(root.getNodeName());
```

`getDocumentElement`メソッドで現在の位置から最上層の要素を取得できるらしい。
で、`getNodeName`メソッドで取得したノードの要素名を取得。

ちなみに`getAttribute()`メソッドで属性値も取得できる。

####子要素の取得

```java
        //子ノードの取得
        NodeList childNodeList = root.getChildNodes();
        //取得した子ノードでループをかける
        for(int child_i = 0; child_i < childNodeList.getLength(); child_i++){
            Node childNode = childNodeList.item(child_i);
            
            //子ノードが要素ノードだったら
            if(childNode.getNodeType() == Node.ELEMENT_NODE){
                //子ノードのノード名を取得
                System.out.println("Its child element is "+childNode.getNodeName());
                System.out.println("");
```
`getChildNodes`メソッドでその要素の子要素を取得する。
`getNodeType`でそのノードのタイプを判定
ノードのタイプについては[こちら](https://www.techscore.com/tech/Java/JavaSE/DOM/2-3/)を参照


####孫要素と曾孫要素の取得

```java
            //孫ノードを取得
            NodeList grandchildNodeList = childNode.getChildNodes();
                //孫ノードの中でループ
                for(int grachild_i = 0; grachild_i < grandchildNodeList.getLength(); grachild_i++){
                    //孫ノードが要素ノードだったら
                    if(grandchildNodeList.item(grachild_i).getNodeType()==Node.ELEMENT_NODE){
                        //孫ノードから曾孫ノードを取得
                        NodeList gre_grandchildNodeList = grandchildNodeList.item(grachild_i).getChildNodes();

                        //曾孫ノードでループ
                        for(int gre_grachild_i = 0; gre_grachild_i < gre_grandchildNodeList.getLength(); gre_grachild_i++){
                            
                            Node node = gre_grandchildNodeList.item(gre_grachild_i);
                            //そのノードが要素ノードだったらノード名と内容を表示
                            if(node.getNodeType() == Node.ELEMENT_NODE){
                                System.out.println(node.getNodeName() + " : " + node.getTextContent());
                            }
                        }
                        System.out.println("--------------------------------------------------------");


```
`getTextContent`メソッドでその要素の内容を表示できる。