|
- <!DOCTYPE html>
- <!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
- <html lang="en">
- <head>
- <link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
- <title>XmlNamespaceSupport</title>
- </head>
- <body>
- <h2 id="namespace">XML Namespace Support</h2>
- Apache Ant 1.6 introduces support for XML namespaces.
- <h3>History</h3>
-
- <p>
- All releases of Ant prior to Ant 1.6 do not support XML namespaces. No support basically
- implies two things here:
- </p>
- <ul>
- <li>Element names correspond to the "qname" of the tags, which is usually the same as the
- local name. But if the build file writer uses colons in names of defined tasks/types,
- those become part of the element name. Turning on namespace support gives
- colon-separated prefixes in tag names a special meaning, and thus build files using
- colons in user-defined tasks and types will break.
- </li>
- <li>Attributes with the names <q>xmlns</q> and <q>xmlns:<em>prefix</em></q> are not
- treated specially, which means that custom tasks and types have actually been able to
- use such attributes as parameter names. Again, such tasks/types are going to break when
- namespace support is enabled on the parser.
- </li>
- </ul>
- <p>Use of colons in element names has been discouraged in the past, and using any attribute
- starting with <q>xml</q> is actually strongly discouraged by the XML spec to reserve such
- names for future use.
- </p>
-
- <h3>Motivation</h3>
- <p>In build files using a lot of custom and third-party tasks, it is easy to get into name
- conflicts. When individual types are defined, the build file writer can do some
- namespacing manually (for example, using <q>tomcat-deploy</q> instead of
- just <q>deploy</q>). But when defining whole libraries of types using
- the <code><typedef></code> <var>resource</var> attribute, the build file writer has
- no chance to override or even prefix the names supplied by the library.</p>
-
- <h3>Assigning Namespaces</h3>
- <p>
- Adding a <var>prefix</var> attribute to <code><typedef></code> might have been
- enough, but XML already has a well-known method for namespacing. Thus, instead of adding
- a <var>prefix</var> attribute, the <code><typedef></code>
- and <code><taskdef></code> tasks get a <var>uri</var> attribute, which stores the
- URI of the XML namespace with which the type should be associated:
- </p>
- <pre>
- <typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/>
- <my:task xmlns:my="http://example.org/tasks">
- ...
- </my:task></pre>
- <p>As the above example demonstrates, the namespace URI needs to be specified at least
- twice: one time as the value of the <var>uri</var> attribute, and another time to actually
- map the namespace to occurrences of elements from that namespace, by using
- the <var>xmlns</var> attribute. This mapping can happen at any level in the build file:
- </p>
- <pre>
- <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></pre>
- <p>
- Use of a namespace prefix is of course optional. Therefore the example could also look
- like this:
- </p>
- <pre>
- <project name="test">
- <typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/>
- <task xmlns="http://example.org/tasks">
- ...
- </task>
- </project></pre>
- <p>
- Here, the namespace is set as the default namespace for the <code><task></code>
- element and all its descendants.
- </p>
-
- <h3>Default Namespace</h3>
- <p>
- The default namespace used by Ant is <code>antlib:org.apache.tools.ant</code>.
- </p>
- <pre>
- <typedef resource="org/example/tasks.properties" uri="antlib:org.apache.tools.ant"/>
- <task>
- ...
- </task></pre>
-
- <h3>Namespaces and Nested Elements</h3>
- <p>
- Almost always in Ant 1.6, elements nested inside a namespaced element have the same
- namespace as their parent. So if <code>task</code> in the example above allowed a
- nested <code>config</code> element, the build file snippet would look like this:
- </p>
- <pre>
- <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></pre>
- <p>If the element allows or requires a lot of nested elements, the prefix needs to be used
- for every nested element. Making the namespace the default can reduce the verbosity of the
- script:
- </p>
- <pre>
- <typedef resource="org/example/tasks.properties" uri="http://example.org/tasks"/>
- <task xmlns="http://example.org/tasks">
- <config a="foo" b="bar"/>
- ...
- </task></pre>
- <p>
- <em>Since Ant 1.6.2</em>, elements nested inside a namespaced element may also be in Ant's
- default namespace. This means that the following is now allowed:
- </p>
- <pre>
- <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></pre>
-
- <h3>Namespaces and Attributes</h3>
- <p>
- Attributes are only used to configure the element they belong to if:
- </p>
- <ul>
- <li>they have no namespace (note that the default namespace does <strong>not</strong> apply to attributes)</li>
- <li>they are in the same namespace as the element they belong to</li>
- </ul>
- <p>
- <em>Since Ant 1.9.1</em> two attribute namespaces <code>ant:if</code>
- and <code>ant:unless</code> are available to allow you to insert elements conditionally.
- </p>
- <p>
- Other attributes are simply ignored.
- </p>
- <p>
- This means that both:
- </p>
- <p>
- </p>
- <pre>
- <my:task xmlns:my="http://example.org/tasks">
- <my:config a="foo" b="bar"/>
- ...
- </my:task></pre>
- <p>
- and
- </p>
- <pre>
- <my:task xmlns:my="http://example.org/tasks">
- <my:config my:a="foo" my:b="bar"/>
- ...
- </my:task></pre>
- <p>
- result in the parameters <var>a</var> and <var>b</var> being used as parameters to
- configure the nested <code>config</code> element.
- </p>
- <p>
- It also means that you can use attributes from other namespaces to markup the build file
- with extra metadata, such as RDF and XML-Schema (whether that's a good thing or not). The
- same is not true for elements from unknown namespaces, which result in a error.
- </p>
- <h3>Mixing Elements from Different Namespaces</h3>
-
- <p>
- Now comes the difficult part: elements from different namespaces can be woven together under
- certain circumstances. This has a lot to do with the Ant
- 1.6 <a href="../develop.html#nestedtype">add type introspection rules</a>: Ant types and tasks
- are now free to accept arbitrary named types as nested elements, as long as the concrete type
- implements the interface expected by the task/type. The most obvious example for this is
- the <code><condition></code> task, which supports various nested conditions, all of
- which extend the interface <code class="code">Condition</code>. To integrate a custom
- condition in Ant, you can now simply <code><typedef></code> the condition, and then use
- it anywhere nested conditions are allowed (assuming the containing element has a
- generic <code class="code">add(Condition)</code>
- or <code class="code">addConfigured(Condition)</code> method):
- </p>
- <pre>
- <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></pre>
- <p>
- In Ant 1.6, this feature cannot be used as much as we'd all like to: a lot of code has not
- yet been adapted to the new introspection rules, and elements like Ant's built-in
- conditions and selectors are not really types in 1.6. This is expected to change in Ant
- 1.7.
- </p>
- <h3>Namespaces and Antlib</h3>
-
- <p>
- The new <a href="antlib.html">AntLib</a> feature is also very much integrated with the
- namespace support in Ant 1.6. Basically, you can "import" Antlibs simply by using a
- special scheme for the namespace URI: the <code>antlib</code> scheme, which expects the
- package name in which a special <samp>antlib.xml</samp> file is located.
- </p>
-
- </body>
- </html>
|