倭マン's BLOG

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

NamespaceContext の実装を考える (1) : 抽象メソッド

javax.xml.namespace パッケージに定義されている NamespaceContext インターフェース(簡単にはこちらを参照)は、標準 API 内に実装クラスもファクトリ・クラスも提供されていません。 したがって、自分でインスタンスを作成したい場合には、自作クラスを定義しなければなりません。

今回以降、何回かにわたって NamespaceContext インターフェースの実装例を考えてみたいと思います(一覧)。 ただし、ここでは DOM や dom4j のように、XML ノードがメモリー上に展開されている様なものに対しての実装のみを考えることにします。

javax.xml.namespace.NamespaceContext インターフェース


NamespaceContext インターフェースの型定義は以下のようになっています:

package javax.xml.namespace.NamespaceContext;

import java.util.Iterator;

public interface NamespaceContext{
    String getNamespaceURI(String prefix) ;
    String getPrefix(String uri);
    Iterator<?> getPrefixes(String uri);
}

実装しなければならないメソッドは3つです。 これらは大まかに言って、次の2種類に分けられます:

  • 「接頭辞」から「名前空間 URI」を解決するメソッド getNamespaceURI()
  • 名前空間 URI」から「接頭辞」を解決するメソッド getPrefix(), getPrefixes()

あまり標準 API に文句を言っても仕方ありませんが、

  • getPrefix(), getPrefixes() メソッドは、あまり使わない割に実装が面倒
  • Java SE 6 から標準 API になったんだから、getPrefixes() の返り値を Generics に対応した Iterator にして欲しい
  • そもそも getPrefixs() の返り値を List の様にコレクションクラスにして欲しい

と思うんですが。 まぁ、「互換性」やら「StAX 起源の API 」やらのせいで仕方ないんでしょうけど。

抽象メソッド


DOM や dom4j のような、メモリー上に展開された XML ツリーを対象にすることにしたので、それらの実装に固定されないように、抽象メソッドを定義します。 実装するメソッドは次の通り:

メソッド名 引数 返り値 説明
getParentContext() NamespaceContext - 親ノードの NamespaceContext を返します。
getNamespaceURIonCurrentNode(String) 接頭辞:String 名前空間 URI :String 対象ノード内でのみ引数の接頭辞に対応する名前空間宣言を探し、その名前空間 URI を返します。
getPrefixOnCurrentNode(String) 名前空間 URI :String 接頭辞のリスト:List 対象ノード内でのみ引数の名前空間 URIに対応する名前空間宣言を探し、その接頭辞を返します。

抽象メソッドの設計方針は、「対象ノードのみで行う処理」と「親ノードへ委譲する処理」とを分けることです。

実際のクラス定義はこんな感じ:

import javax.xml.namespace.NamespaceContext;
import java.util.List;

/**
 * @author waman
 */
public abstract class AbstractNamespaceContext implements NamespaceContext{
    
    /**
     * 親ノードの NamespaceContext を返します。
     */
    protected abstract NamespaceContext getParentContext();

    /**
     * 引数の文字列で指定される接頭辞に対応する名前空間 URI を返します。
     * 祖先要素には遡りません。
     * 該当する名前空間 URI が見つからなかった場合、null を返します。
     */
    protected abstract String getNamespaceURIonCurrentNode(String prefix);

    /**
     * 引数で指定される名前空間 URI に対応する接頭辞のリストを返します。
     * 祖先要素には遡りません。
     * 該当する接頭辞が見つからなかった場合、空リストを返します。
     */
    protected abstract List<String> getPrefixesOnCurrentNode(String uri);
}

インターフェースに定義されているメソッドの実装は次回以降に。