倭マン's BLOG

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

NamespaceContext の実装を考える (2) : メソッド getNamespaceURI()

今回は、指定された接頭辞から、それに対応する名前空間 URI を返すメソッド NamespaceContext#getNamespaceURI(String) を考えます(一覧)。

NamespaceContext#getNamespaceURI(String) の返り値


Java SE 6 の API ドキュメントを見ると、返り値は以下のように定義されています:

引数の接頭辞 返り値
空文字列 デフォルト名前空間 URI(デフォルト名前空間の宣言が無ければ、空文字列)が返されます。
xml http://www.w3.org/XML/1998/namespace
xmlns http://www.w3.org/2000/xmlns/
null IllegalArgumentException が投げられる
対応する名前空間宣言がある場合 対応する名前空間 URI
対応する名前空間宣言がない場合 空文字列

空文字列が引数の場合、対応する名前空間宣言がある場合、ない場合と同じ処理をすれば良さそうです。

名前空間 URI の解決手順


名前空間 URI の解決手順は以下の通り:

  1. 引数の接頭辞が null, "xml", "xmlns" の場合は、対応する名前空間 URI を返す(もしくは例外を投げる)
  2. 指定された接頭辞に対応する名前空間宣言が対象ノード上にあれば、その名前空間 URI を返す
  3. 親ノードがあれば、その NamespaceContext を用いて接頭辞を解決する
  4. 親ノードがなければ、空文字列を返す

「対応する名前空間宣言がない場合」は、「親ノードがなければ、空文字列を返す」場合に帰着します。

実装


実装は概ね次の様になります:

/** @author waman */
public abstract class AbstractNamespaceContext
        implements NamespaceContext{

    protected abstract NamespaceContext getParentContext();
    protected abstract String getNamespaceURIonCurrentNode(String prefix);

    public String getNamespaceURI(String prefix) {
        if(prefix == null) 
            throw new IllegalArgumentException("Namespace prefix cannot be null !");
        if("xml".equals(prefix))  
            return "http://www.w3.org/XML/1998/namespace";
        if("xmlns".equals(prefix)) 
            return "http://www.w3.org/2000/xmlns/";

        String uri = getNamespaceURIonCurrentNode(prefix);
        // 対象ノード上に名前空間宣言がある場合
        if(uri != null) return uri;

        NamespaceContext parent = getParentContext();
        // 親ノードがある場合
        if(parent != null) return parent.getNamespaceURI(prefix);

        // 親ノードがない場合
        return NULL_NS_URI;
    }
}