倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

XML ノード間の包含関係を理解する

前回は Node*1 のサブインターフェースの階層構造を見ました。 今回はそれらのインターフェース間の包含関係を見ていきましょう(一覧)。

♪包含関係♪


包含関係で重要な役割を果たすのは Branch インターフェースのサブインターフェース、 Document, Element です。 包含関係を分類すると、下図のようになります:
f:id:waman:20070919083850p:image

注意として、Document はただ1つの Element(ルート要素)のみを持てます。

Branch, Document, Element の各インターフェースには、それぞれの型のノードを追加、削除するためのメソッド add(), remove() が定義されています。

♪Node に定義されている包含関係に関するメソッド♪


XML 文書内のノードを実装する Node インターフェースに定義されている包含関係関連のメソッドを見てみましょう。 それは getParent(), detach() です*2

Element getParent()

ノードが親要素を持っていれば、それを返します。 持っていなければ null を返します。 「親要素を持っていない」場合というのは

  • 対象ノードが Document ノードである
  • 対象ノードが ルート要素(XML 文書内の最も外側の要素)である
  • どのノードにも包含(付加)されていないノード

等があります。

Node detach()

対象ノードが他の要素を親要素として持っていれば、そこから切り離します。 返り値の Node は detach() メソッドを呼び出されたノード自身です。 あるノードを他のノードに(add メソッドなどで)付加する際には親要素を持っていてはいけないので、事前にこのメソッドを呼び出さなければなりません:

// 要素 child を他の要素 parent に付加する
parent.add(child.detach());

♪Branch に定義されている包含関係に関するメソッド♪


Branch インターフェースに定義されているメソッドで包含関係に関連するメソッドとして、content(), setContent(List) というメソッドがあります。 content() では(Node の)List が返されますが、これには少し注意が必要です。 上図にも描きましたが、この List には、含まれないノードの型があります。

  • Document#content() で返される List には DocumentType は含まれません
  • Element#content() で返される List には Attribute は含まれません

Branch#nodeIterator() で返される Iterator にもこれらは含まれません。 また、これらを含んでいる List を引数にして setContent(List) を実行すると、キチンとセットされません*3

*1:org.dom4j パッケージに含まれるインターフェース、クラスはパッケージ名を省略します。

*2:getDocument() メソッドも包含関係関連のメソッドですが、実装が任意(optional)なので、ここでは触れません。

*3:デフォルト実装では toString() を呼び出した値を setText(String) によって呼び出しているようです