XML 名前空間のサポート

Ant 1.6 は XML 名前空間のサポートを導入します。

歴史

Ant 1.6 以前のすべてのリリースは XML 名前空間をサポートしていません。 サポートしないということは、ここでは基本的に2つのことを意味します:

要素名にコロンを使うことは、過去の私の記憶が正確ならばおすすめしません。 また、"xml" で始まる属性を使うことは、将来の利用のためにそのような名前を予約している XML の仕様があるので本当に強くお勧めしません。

動機

ビルドファイル内で多くのカスタム及びサードパーティ製のタスクを使っていると、名前の衝突が簡単に起こります。 個別にタイプが定義されるときは、ビルドファイルを書く人が手動で名前空間のようなことを行うことができます(例えば、"deploy" の代わりに "tomcat-deploy" を使うように)。 しかし、<typedef> の 'resource' 属性を使ってライブラリ全体を定義したときは、 ビルドファイルを書く人は名前を上書きしたり、ライブラリから与えられる名前の前につけることさえ行う機会がありません。

名前空間の割当

<typedef> に 'prefix' 属性を追加することで十分かもしれませんが、 XML は名前空間のためのよく知られた方法を既にもっています。そのため、 'prefix' 属性を追加する代わりに <typedef> や <taskdef> タスクは 'uri' 属性を持っています。これは、型が関連している XML 名前空間の URI を格納します。

 <typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/>
 <my:task xmlns:my="http://example.org/tasks">
    ...
 </my:task>

上記の例が示しているように、名前空間 URI は少なくとも2度定義する必要があります: 1つめは 'uri' 属性の値として指定し、もう1つは 'xmlns' 属性を使うことによってその名前空間が提供する要素が現れたときに、実際に名前空間にマップします。このマッピングは、ビルドファイル中のあらゆる段階で現れます:

 <project name="test" xmlns:my="http://example.org/tasks"> 
   <typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/>
   <my:task>
     ...
   </my:task>
 </project>

名前空間を指定するプレフィックスの利用はもちろん任意です。そのため、 以下の例のようにすることもできます:

 <project name="test"> 
   <typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/>
   <task xmlns="http://example.org/tasks">
     ...
   </task>
 </project>

ここでは、名前空間を <task> 要素とそのすべての子孫用にデフォルトの名前空間として設定します。

デフォルトの名前空間

Ant によって使われるデフォルトの名前空間は、"antlib:org.apache.tools.ant" となります。

<typedef resource="org/example/tasks.properties" uri="antlib:org.apache.tools.ant"/>
<task>
      ....
</task>
    

名前空間とネストした要素

Ant 1.6 ではほとんど常に、ある名前空間内にある要素内にネストした要素は、 その親と同じ名前空間を持っています。そこで、もし上記の例で 'task' が ネストした 'config' 要素を認める場合、ビルドファイルの一部はこのようになるでしょう。

 <typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/>
 <my:task xmlns:my="http://example.org/tasks">
   <my:config a="foo" b="bar"/>
   ...
 </my:task>

要素が、多くのネストした要素を認めるか必要とする場合、(名前空間を指定する)プリフィックスは、 すべてのネストした要素で指定する必要があります。デフォルトの名前空間を指定することによって、 スクリプトの冗長さを削減することができます。

 <typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/>
          <task xmlns="http://example.org/tasks">
          <config a="foo" b="bar"/>
   ...
          </task>

名前空間と属性

属性は、以下の条件においてのみ、所属する要素を設定するために使います。

その他の属性は、単に無視します。

これは、次の両方を意味します:

 <my:task xmlns:my="http://example.org/tasks">
   <my:config a="foo" b="bar"/>
   ...
 </my:task>

 <my:task xmlns:my="http://example.org/tasks">
   <my:config my:a="foo" my:b="bar"/>
   ...
 </my:task>

結果、"a" と "b" のパラメタは、ネストした "config" 要素を構成するパラメタとして使われます。

これはまた、他の名前空間からの属性を RDF や XML-Schema のような余分なメタデータを、 ビルドファイルにマークアップすることができることを意味します(それが良かろうと悪かろうと)。 未知の名前空間からの要素について、同じことは成り立ちません。それはエラーとなります。

異なる名前空間からの要素の組み合わせ

難しい部分に来ています: 異なる名前空間からの要素は、ある状況下では互いに協調して動作することができます。 これは Ant 1.6 の タイプを追加するときのイントロスペクションルール が多く関係しています: Ant のタイプやタスクは、具象クラスがそのタスク/タイプが要求するインターフェイスを実装している場合に限り、 ネストした要素として任意の名前のタイプを自由に受け入れることができます。 この最も明白な例は、<condition> タスクです。このタスクは、様々なネストしたコンディションをサポートします。すべてのコンディションは、Condition インターフェイスを拡張したものです。 カスタムコンディションを Ant に統合するために、単にコンディションを <typedef> することができます。 その後、develop.html#nestedtypwhere のようにコンディションが認められるならどこでも使うことができます(一般的に add(Condition)addConfigured(Configured) メソッドを持つ要素に含まれていることを想定しています)。

 <typedef resource="org/example/conditions.properties" uri="http://example.org/conditions"/>
 <condition property="prop" xmlns="http://example.org/conditions">
   <and>
     <available file="bla.txt"/>
     <my:condition a="foo"/>
   </and>
 </condition>

Ant 1.6 では、この機能は私たちが望むすべてを同じように使用することができません: 多くのコードは、Ant 組み込みのコンディションやセレクタが 1.6 では本当の意味でのタイプではないように、 まだ新しいイントロスペクションルールや要素に対応していません。 これは、1.7 では変更されると思われます。

名前空間と Antlib

新しい AntLib 機能も Ant 1.6 の名前空間サポートに強く結びついています。基本的に、単に名前空間 URI として特別なスキーマ: antlib スキーマ を使うことによって Antlib を取り込むことができます。これは、特別な antlib.xml ファイルの位置するパッケージ名を予測します。


Copyright © 2003-2004 The Apache Software Foundation. All rights Reserved.

[訳注: これは浦本 和則が翻訳しました。日本語訳に対するコメントがあれば、 report@jajakarta.orgに送って下さい。]