fc2ブログ
ホーム   »  Java  »  名前空間付き XML

名前空間付き XML

XML の名前空間 (Namespace) を使用することでひとつの XML ドキュメント内に複数のスキーマを混在させることができる。詳細な説明は省略するが、たとえばこれをうまく使うと一つの設定ファイルにさまざまなチーム固有のスキーマを混在させたり、プラグイン的に動作するモジュールが任意のドキュメント内で自分の処理対象の見つけ出し加工するような使い方ができる。

ただし Java ではデフォルトでオフになっているため使い始めで少々躓くかもしれない。

DOM

Java で使用する XML はデフォルトで名前空間がオフになっているので注意が必要 (過去との互換性のためらしい)。getElementsByTagNameNS() などを使用して特定の名前空間を持つ要素を検索する場合には、そのドキュメントが setNamespaceAware(true) としたファクトリから構築されていなければならない。

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
Document doc = factory.newDocumentBuilder().parse(file);
NodeList nl = doc.getElementsByTagName("http://lab.moyo.biz/ns/foo", "foo");

たとえば上記のように名前空間 http://lab.moyo.biz/ns/foo を持つローカル名 foo の要素を検索した場合、下記のドキュメントに対して <x:foo value="mynamespace" /> の要素のみが一致する。

<?xml version="1.0"?>
<mydocument xmlns:x="http://lab.moyo.biz/ns/foo"
    xmlns:y="http://www.mars.dti.ne.jp/ns/bar" >
  <x:foo value="mynamespace" />
  <foo value="othernamespace" />
  <y:foo value="othernamespace" />
</mydocument>

XPath

名前空間の付けられている XML ドキュメントに対して XPath でノードを検索する場合も、デフォルトでは名前空間を持たないノードのみしか検索対象にしていないため注意が必要。しかも DOM の場合はフラグひとつ設定するだけで済んだのだが、XPath の場合はプレフィクスと名前空間をマップするクラスを作成した上でプレフィクス付きで XPath を指定しなければならない。

XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContext(){
  @Override
  public String getNamespaceURI(String prefix) {
    if(prefix.equals("myprefix")){
      return "http://lab.moyo.biz/ns/foo";
    }
    if(prefix.equals(XMLConstants.XML_NS_PREFIX)){
      return XMLConstants.XML_NS_URI;
    }
    return XMLConstants.NULL_NS_URI;
  }
  @Override
  public String getPrefix(String namespaceURI) {
    if(namespaceURI.equals(uri)){
      return prefix;
    }
    if(namespaceURI.equals(XMLConstants.XML_NS_URI)){
      return XMLConstants.XML_NS_PREFIX;
    }
    return XMLConstants.DEFAULT_NS_PREFIX;
  }
  @Override
  public Iterator<String> getPrefixes(String namespaceURI) {
    // 略…
  }
});
NodeList nl = (NodeList)xpath.evaluate(
  "/mydocument/myprefix:foo", doc, XPathConstants.NODESET);

XPath 側では名前空間 URI さえ一致していればドキュメント側のプレフィクスと一致させる必要はない。

わざわざユーザ側に実装させなくてもプレフィクスと URI をマッピングする実装済みユーティリティクラスくらい用意してくれていればかなりの手間が省けるはずなのだが。このトントンチキは JCP の仕業なのか W3C 仕業なのか。どちらもやりそうだから困ったものだ。

コメント
トラックバック
トラックバック URL
コメントの投稿
管理者にだけ表示を許可する
Profile
Takami Torao
Takami Torao
C/C++ 使いだった 1996年、運命の Java と出会い現在に至る。のらアーキテクト。
Yah, this is image so I don't wanna eat spam, sorry!
Search

Google
MOYO Laboratory
Web

カテゴリー
最近の記事
最近のコメント
最近のトラックバック
月別アーカイブ
ブロとも申請フォーム
RSSフィード
リンク