2.3. Node
DOMで文書を読む場合、XMLの「要素」や「属性」などのデータは木構造の「節」にあたります。DOMには節の部分を操作する「Node」インタフェースが用意されています。DOMの全てのAPIはこのNodeインタフェースを継承したものになります。
Nodeインタフェースのメソッドには、以下のようなものがあります。
| メソッド | 内容 |
|---|---|
| public String getNodeName() | ノードの名前(要素名や属性名など)を取得する。 |
| public String getNodeValue() | ノードの値(属性値など)を取得する |
| public short getNodeType() | ノードのタイプを取得する。 |
| public Node getParentNode() | 親ノードを取得する |
| public NodeList getChildNodes() | 子供ノードを取得する。 |
| public Node getFirstChild() | このノードの1番最初の子供ノードを取得する。子ノードがない場合は、nullを返す。 |
| public Node getLastChild() | このノードの1番最後の子供ノードを取得する。子ノードがない場合は、nullを返す。 |
| public Node getPreviousSibling() | このNodeの直前に記述されているノードを取得する。そのようなノードがない場合、nullを返す。 |
| public Node getNextSibling() | このNodeの直後に記述されているノードを取得する。そのようなノードがない場合、nullを返す。 |
| public NamedNodeMap getAttributes() | このノードが要素で合った場合、属性の一覧を取得する。要素でない場合は、nullを返す。 |
また、Nodeには、以下の種類があります。以下のインタフェースは全て、Nodeインタフェースを継承したものになります。ノードがどの種類なのかはgetNodeType()メソッドで取得することができます。前節で紹介した「Document」もNodeの一つです。
| Type | 内容 | getNodeType()の戻り値 |
|---|---|---|
| Document | 文書 | Node.DOCUMENT_NODE |
| DocumentFragment | 最小の文書オブジェクト | Node.DOCUMENT_FRAGMENT_NODE |
| DocumentType | ドキュメントタイプ("DTD"で定義される) | Node.DOCUMENT_TYPE_NODE |
| EntitiyReference | 実体参照 | Node.ENTITY_REFERENCE_NODE |
| Element | 要素 | Node.ELEMENT_NODE |
| Attr | 属性 | Node.ATTRIBUTE_NODE |
| ProcessingInstruction | 処理命令 | Node.PROCESSING_INSTRUCTION_NODE |
| Comment | コメント | Node.COMMENT_NODE |
| Text | テキスト | Node.TEXT_NODE |
| CDATASection | CDATAセクション | Node.CDATA_SECTION_NODE |
| Entity | 実体 | Node.ENTITY_NODE |
| Notation | 記法 | Node.ENTITY_NODE |
以下に例を示します。
1 import java.io.*;
2 import org.w3c.dom.Document;
3 import org.w3c.dom.Node;
4 import javax.xml.parsers.*;
5
6 public class NodeSample{
7
8 public static void main(String args[]) throws Exception{
9
10 Document document= DocumentBuilderFactory
11 .newInstance()
12 .newDocumentBuilder()
13 .parse(new File("employees.xml"));
14
15 Node node=document.getDocumentElement();
16
17 Node childNode=node.getFirstChild();
18 int i=1;
19 while(childNode!=null){
20 short type=childNode.getNodeType();
21 String typeStr="";
22 switch( type){
23 case Node.ATTRIBUTE_NODE:
24 typeStr +="属性";
25 break;
26 case Node.CDATA_SECTION_NODE :
27 typeStr +="CDATAセクション";
28 break;
29 case Node.COMMENT_NODE :
30 typeStr +="コメント";
31 break;
32 case Node.DOCUMENT_FRAGMENT_NODE :
33 typeStr +="最小の文書のオブジェクト";
34 break;
35 case Node.DOCUMENT_NODE :
36 typeStr +="文書";
37 break;
38 case Node.DOCUMENT_TYPE_NODE :
39 typeStr +="文書型";
40 break;
41 case Node.ELEMENT_NODE :
42 typeStr +="要素";
43 break;
44 case Node.ENTITY_NODE:
45 typeStr +="実体";
46 break;
47 case Node.ENTITY_REFERENCE_NODE :
48 typeStr +="実体参照";
49 break;
50 case Node.NOTATION_NODE :
51 typeStr +="記法";
52 break;
53 case Node.PROCESSING_INSTRUCTION_NODE :
54 typeStr +="処理命令";
55 break;
56 case Node.TEXT_NODE:
57 typeStr +="テキスト";
58 break;
59 }
60
61 System.out.println((i++)+"番目の子ノードは"+typeStr+"です。");
62 childNode=childNode.getNextSibling();
63
64 }
65
66
67
68 }
69
70 }
これは、employees.xmlのルート要素の子ノードがどのタイプのノードなのか、表示するプログラムです。まず、10-14行目でDocumentノードを取得しています。15行目でルート要素を取得しています。17行目で、"getFirstChild()"メソッドを使用して、ルート要素の最初の子ノードを取得しています。もし、ルート要素に子ノードが存在した場合、子ノードのタイプを判別し、コンソールに表示しています(19-61行目)。最後に、62行目で、getNextSibling()メソッドを使用して次のノードを取得しています。これを繰り返し、ルート要素の全ての子ノードに対して、「何番目の子ノードで、ノードタイプは何か」を表示していきます。
employees.xmlの内容が以下であったとします。
<?xml version="1.0" encoding="UTF-16" standalone="yes"?> <employees> <employee> <name>山田 太郎</name> <office>東京</office> </employee> <employee> <name>川島 次郎</name> <office>東京</office> </employee> </employees>
NodeSampleを実行すると、以下のように表示されます。
$java NodeSample 1番目の子ノードはテキストです。 2番目の子ノードは要素です。 3番目の子ノードはテキストです。 4番目の子ノードは要素です。 5番目の子ノードはテキストです。
employess.xmlのルート要素は”employees”です。employeesの子ノードは"employee"要素が二つだけ、のように見えます。しかし、NodeSampleを実行すると、employeesの子ノードは、テキストノード3つ、要素ノード2つの計5つと解釈されています。これは、どういうことでしょう。XMLでは、「空白」や「改行」などの文字も無視せず、そのままデータとして扱います。employees.xmlでは、人間が見やすいように、2行目"<employees>"と3行目"<employee>"の間に、改行文字と空白文字が記述されています。DOMでは、このデータを「最初の子ノード」「テキストノード」と解釈しているわけです。同様に、6行目"</employee>"と7行目"<employee>"の間の改行・空白文字は、「3番目の子ノード」、10行目"</employee>"と11行目"</employees>"の間の改行文字は「5番目の子ノード」と認識されます。XMLのインデント、空白、改行などには、充分注意する必要があります。
(実習課題1)
XMLファイルを読み込み、ルート要素の名前、および文書タイプの名前を表示するプログラムを作成しなさい。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
...
</webapp>
(実習課題2)
employees.xmlファイルを読み込み、従業員の名前(employee要素の子要素nameの内容)の一覧を表示しなさい。
ここでは、DocumentおよびNodeのみを使用してプログラムを書くこと
・要素の名前はgetNodeName()で取得する
・テキストの内容はgetNodeValue()で取得する

