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()で取得する