| |
Elements, and particularly attributes, might be more conveniently
used in multiple contexts.
An attribute, title, might refer to a book's title.
Or it might refer to a job title, or the title of a person's name (Mr., Mrs., etc).
As a solution, title could be assigned a prefix, for a unique namespace,
so that any processing, any XSLT transform, could differentiate
between 'meanings' of the same attribute named, title.
For the same reason, there's even a more obvious use for namespaces, as well.
They can be used by a transform engine, like XSLT, to identify not
just elements/tokens but that these indicate particular processing commands.
A new namespace is declared as an attribute of some element.
That's just how the committee devised it.
Everything under that element, inside its 'scope', can be part
of that namespace if the same prefix is then used on those elements or attributes.
The declaration attribute for a namespace looks like:
|
<element-name xmlns:prefix="uri">
|
The "xmlns:" is the specific name you must use, for this declaration attribute/'command'.
The prefix is what the namespace is called.
It's that prefix which you use to explicitly assign some element or attribute
to that particular namespace.
The XSLT engine, or processor, however, will associate the URI with
the element or attribute.
So the XSLT 'code' uses the prefix.
And XSLT processor uses the URI.
So in this case, since no prefix was used on the element, itself ("element-name", in this example), the element
is not part of any declared namespace, unless a default was declared.
In msxml, "xml" is itself a reserved namespace, which doesn't have to be explicitly declared.
It has a default uri of - http://www.w3.org/XML/1998/namespace - and provides
a couple of readily available functions that you could call.
However, one can explictly define a default namespace by simply declaring a uri without using
any prefix.
This will be the current default, or 'non-prefixed', namespace:
|
<element-name xmlns="uri">
|
Elements under this declaration which use no prefix, are
automatically included in this non-prefix namespace.
Attributes are different. Otherwise, they are associated with the element in which they are
used.
However, for purposes of namespaces, unless a specific namespace prefix is used with an attribute, an attribute
itself is not even part of the default namespace.
It has a null namespace, none.
Or, more properly, it just simply has no namespace.
(Using the default namespace can be dicey with XPath version 1, as explained there.)
The uri, itself, might point to a validation schema.
But this uri really, at this point in the development of XML, etc., can be thought
of as just a meaningless string. You can put anything there.
Some are predefined, built-in.
You use such for XSLT, for example, or for XSD schema,
so that certain elements are treated as processor commands.
But, otherwise, the uri is just a made-up string.
You have to put something there.
Technically, it is this URI, as such, that is associated with each element and prefixed attribute.
Here's an example:
<names xmlns:user="namespace1">
<subnames xmlns:user2="namespace2">
<user2:person>Andy Taylor</user2:person>
<occupation xmlns:user3="namespace3">sheriff</occupation>
</subnames>
<user:subnames episode="#204">
<person>Gomer Pyle</person>
<occupation>door-to-door salesmen</occupation>
</user:subnames>
</names>
|
In addition to the reserved namespace, xml, three namespaces are explicitly declared, here - making
it a total of four.
There is no non-prefix, default declared, in this example (default namespaces,
again, can pose problems for XPath version 1).
Starting with the root node, names, the first new namespace, namespace1,
is declared.
Since the user prefix isn't used on the names element, that element
is not part of the namespace1 namespace.
That element is not part of any namespace.
It would be included in a default namespace, if one had been declared.
The very next sub-element, subnames, itself has a new namespace declaration, namespace2.
Again, no prefix is used for the element.
However, one could specify either user or user2 since both are declared
in the same or superior elements and so can be 'seen' by that first subnames element.
At occupation, yet another namespace is declared.
Again no prefix.
However, the user2 prefix is specified for the person element, just above.
That element is then part of the namespace2 namespace.
The user prefix is used with the second subnames, here. That puts that
element in the namespace1 namespace.
So, to repeat, the first subnames, for example, could have been included in the same
namespace2 namespace which was declared in its own attribute:
|
<user2:subnames xmlns:user2="namespace2">
|
So that subnames element is part of the namespace2 namespace.
The 'scope', or whether an element can 'see' a namespace declaration,
is if that namespace is declared as an attribute of that element, or declared
as an attribute of a superior element.
In the case of the occupation element, above, where the
namespace is declared with the uri namespace3 and the user3 prefix,
the allowable namespaces for
that occupation element would simply be all FOUR namespaces, with the prefixes - xml, user, user1, user2.
For the person node under the first subnames, the 'Andy Taylor' element,
three namespaces could be allowed
for that element, identified by prefix: xml, user, and user2.
For 'Gomer Pyle', it would only be user and the reserved, xml, since
no default namespace was declared. And so on.
To see if an element is actually assigned to a particular namespace, however,
the built-in XPath function, namespace-uri(), is used on the element, itself.
XPath and XSLT are covered, elsewhere.
But this would be an example of the use of the namespace-uri() function.
The "stylesheet" is the XSLT program/transform.
The stuff in "match", "select" and "test" is the XPath 'query' language.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="//*">
element: <xsl:value-of select="name()"/>  
uri:
<xsl:choose>
<xsl:when test="namespace-uri()">
<xsl:value-of select="namespace-uri()"/>
</xsl:when>
<xsl:otherwise>NULL</xsl:otherwise>
</xsl:choose><br/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Which reports:
element: names, uri: NULL
element: subnames, uri: NULL
element: user2:person, uri: namespace2
element: occupation, uri: NULL
element: user:subnames, uri: namespace1
element: person, uri: NULL
element: occupation, uri: NULL
|
Change things around, run the same XSLT transform, and you might get:
<user:names
xmlns:user="namespace1"
xmlns="namespace3">
<subnames
xmlns:user2="namespace2">
<user2:person>Andy Taylor</user2:person>
<occupation>sheriff</occupation>
</subnames>
<subnames episode="#204"
xmlns="namespace4">
<user:person>Gomer Pyle</user:person>
<person>Boss</person>
<user2:occupation
xmlns:user2="namespace5">
door-to-door salesmen
</user2:occupation>
</subnames>
</user:names>
element: user:names, uri: namespace1
element: subnames, uri: namespace3 (non-prefix default)
element: user2:person, uri: namespace2
element: occupation, uri: namespace3 (non-prefix default)
element: subnames, uri: namespace4 (non-prefix default)
element: user:person, uri: namespace1
element: person, uri: namespace4 (non-prefix default)
element: user2:occupation, uri: namespace5
|
You can position the cursor over the namespace declaration, above,
and all elements that are included in that namespace will be highlighted.
You can see that the default was re-declared from namespace3 to namespace4 down
in the second subnames element.
Similarly, while not 'seen' by either one, the user2 prefix is used twice, for different namespaces.
The top names element is prefixed with user, so it becomes part of that namespace.
The first subnames has no prefix, so is assigned to the default namespace3.
And so on.
|