XML 名前空間のサポート

Apache Ant 1.6 では、XML 名前空間のサポートが導入されました。

履歴

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

過去には、要素名でのコロンの使用は推奨されておらず、xmlで始まる属性の使用は、将来の使用のために名前を予約するために、XML仕様によって強く推奨されていません。

動機

多くのカスタムタスクやサードパーティ製タスクを使用するビルドファイルでは、名前の衝突が発生しやすくなります。個々のタイプが定義されている場合、ビルドファイルの作成者は手動で名前空間をいくつか作成できます(たとえば、単にdeployの代わりにtomcat-deployを使用するなど)。しかし、<typedef> resource属性を使用してタイプのライブラリ全体を定義する場合、ビルドファイルの作成者はライブラリによって提供される名前をオーバーライドしたり、プレフィックスを付けたりする機会はありません。

名前空間の割り当て

<typedef>prefix属性を追加するだけで十分だったかもしれませんが、XMLにはすでに名前空間を作成するためのよく知られた方法があります。したがって、prefix属性を追加する代わりに、<typedef>および<taskdef>タスクは、タイプの関連付けに使用するXML名前空間のURIを格納する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>

Ant 1.6.2以降、名前空間付き要素内にネストされた要素もAntのデフォルトの名前空間に属することができます。これは、次のことが許可されるようになったことを意味します。

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

名前空間と属性

属性は、次の場合にのみ、所属する要素を設定するために使用されます。

Ant 1.9.1以降、2つの属性名前空間ant:ifant:unlessが利用可能になり、条件付きで要素を挿入できるようになりました。

その他の属性は単に無視されます。

これは、両方の

<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>

の結果、ネストされたconfig要素を設定するためのパラメーターとしてaおよびbが使用されることを意味します。

また、他の名前空間の属性を使用して、RDFやXMLスキーマなどの追加のメタデータでビルドファイルをマークアップできることも意味します(それが良いことかどうかはともかく)。不明な名前空間の要素では同じことは当てはまりません。エラーが発生します。

異なる名前空間の要素の混合

ここからが難しい部分です。異なる名前空間の要素は、特定の状況下で一緒に織り込むことができます。これは、Ant 1.6のタイプのイントロスペクションルールの追加と密接に関係しています。Antのタイプとタスクは、具体的なタイプがタスク/タイプで期待されるインターフェースを実装している限り、ネストされた要素として任意の名前付きタイプを自由に受け入れることができるようになりました。この最も明白な例は、Conditionインターフェースを拡張するさまざまなネストされた条件をサポートする<condition>タスクです。Antにカスタム条件を統合するには、条件を<typedef>して、ネストされた条件が許可されている場所ならどこでも使用できます(包含する要素に一般的なadd(Condition)またはaddConfigured(Condition)メソッドがあることを前提としています)。

<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では実際にはタイプではありません。これはAnt 1.7で変更される予定です。

名前空間とAntlib

新しいAntLib機能も、Ant 1.6の名前空間サポートと非常に密接に統合されています。基本的に、名前空間URIに特別なスキームを使用するだけでAntlibを「インポート」できます。これは、特別なantlib.xmlファイルがあるパッケージ名を期待するantlibスキームです。