This section defines two possible solutions to support XML namespaces. The first option consists in augmenting the interfaces defined in the Core section, leaving the semantics of DOM Level 1 as it is. The second option, on the contrary, consists in changing the semantics of DOM Level 1 and only augmenting existing interfaces where strictly necessary.
In any case, support for namespaces is mandatory.
The Node interface is extended to include a set
of attributes to access the namespace prefix and namespace name of
a node, and the local part of its qualified name (also called
"local name" in this document).
interface NodeNS {
readonly attribute DOMString namespaceName;
attribute DOMString prefix;
// raises(DOMException) on setting
readonly attribute DOMString localName;
};
namespaceNamenull if it is unspecified.This is not a computed value that is the result of a namespace lookup based on an examination of the namespace declarations in scope. It is merely the namespace name given at creation time.
For nodes created with a DOM Level 1 method, such as
Document.createElement, this is
null.
prefixnull if
it is unspecified.
For nodes created with a DOM Level 1 method, such as
Document.createElement, this is
null.
Note that setting this attribute changes the
nodeName attribute, which holds the qualified name,
as well as the Element.tagName and
Attr.name attributes when applicable.
DOMExceptionINVALID_CHARACTER_ERR: Raised if the specified prefix contains an invalid character.
localName
For nodes created with a DOM Level 1 method, such as
Document.createElement, this is the same as
Node.nodeName.
The Document interface provides two new methods
for creating XML elements and attributes with a namespace prefix
and namespace name.
interface DocumentNS {
Element createElementNS(in DOMString namespaceName,
in DOMString qualifiedName)
raises(DOMException);
Attr createAttributeNS(in DOMString namespaceName,
in DOMString qualifiedName)
raises(DOMException);
NodeList getElementsByTagNameNS(in DOMString namespaceName,
in DOMString localName);
};
createElementNSnamespaceName |
The namespace name of the element to create. | |
qualifiedName |
The qualified name of the element type to instantiate. This can contain a namespace prefix. |
Element object with the following
attributes:| Attribute | Value |
|---|---|
Node.nodeName | qualifiedName |
Node.namespaceName | namespaceName |
Node.prefix | prefix, extracted from qualifiedName, or null if there is no prefix |
Node.localName | local part, extracted from qualifiedName |
Element.tagName | qualifiedName |
DOMExceptionINVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
createAttributeNSnamespaceName |
The namespace name of the attribute to create. | |
qualifiedName |
The qualified name of the attribute to instantiate. This can contain a namespace prefix. |
Attr object with the following
attributes:| Attribute | Value |
|---|---|
Node.nodeName | qualifiedName |
Node.namespaceName | namespaceName |
Node.prefix | prefix, extracted from qualifiedName, or null if there is no prefix |
Node.localName | local part, extracted from qualifiedName |
Attr.name | qualifiedName |
DOMExceptionINVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
getElementsByTagNameNSNodeList of all the
Elements with a given local name and namespace name
in the order in which they would be encountered in a preorder
traversal of the Document tree.
namespaceName |
The namespace name of the elements to match on. The special value "*" matches all namespaces. | |
localName |
The local name of the elements to match on. The special value "*" matches all local names. |
NodeList object containing
all the matched Elements.The Element interface is extended to provides a
set of methods to manipulate attributes with namespaces. Note: Both the tagName attribute from the
Element interface and the nodeName
attribute from the Node interface return the
qualified name.
interface ElementNS {
DOMString getAttributeNS(in DOMString namespaceName,
in DOMString localName);
void setAttributeNS(in DOMString namespaceName,
in DOMString localName,
in DOMString value)
raises(DOMException);
void removeAttributeNS(in DOMString namespaceName,
in DOMString localName)
raises(DOMException);
Attr getAttributeNodeNS(in DOMString namespaceName,
in DOMString localName);
Attr setAttributeNodeNS(in Attr newAttr)
raises(DOMException);
NodeList getElementsByTagNameNS(in DOMString namespaceName,
in DOMString localName);
};
getAttributeNSnamespaceName |
The namespace name of the attribute to retrieve. | |
localName |
The local name of the attribute to retrieve. |
Attr value as a string, or an empty
string if that attribute does not have a specified or default
value.setAttributeNSAttr node plus any Text and
EntityReference nodes, build the appropriate
subtree, and use setAttributeNodeNS or
setAttributeNode to assign it as the value of an
attribute.
namespaceName |
The namespace name of the attribute to create or alter. | |
localName |
The local name of the attribute to create or alter. | |
value |
The value to set in string form. |
DOMExceptionINVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
removeAttributeNSnamespaceName |
The namespace name of the attribute to remove. | |
localName |
The local name of the attribute to remove. |
DOMExceptionNO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
getAttributeNodeNSAttr node by name and
namespace name.
namespaceName |
The namespace name of the attribute to retreive. | |
localName |
The local name of the attribute to retrieve. |
Attr node with the specified
attribute local name and namespace name or null
if there is no such attribute.setAttributeNodeNSnewAttr |
The |
newAttr attribute replaces
an existing attribute with the same local name and namespace
name, the previously existing Attr node is
returned, otherwise null is returned.DOMExceptionWRONG_DOCUMENT_ERR: Raised if newAttr
was created from a different document than the one that
created the element.
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
INUSE_ATTRIBUTE_ERR: Raised if newAttr is
already an attribute of another ElementNS
object. The DOM user must explicitly clone
Attr nodes to re-use them in other
elements.
getElementsByTagNameNSNodeList of all the
Elements with a given local name and namespace name
in the order in which they would be encountered in a preorder
traversal of the Document tree, starting from this
node.
namespaceName |
The namespace name of the elements to match on. The special value "*" matches all namespaces. | |
localName |
The local name of the elements to match on. The special value "*" matches all local names. |
NodeList object containing
all the matched Elements.Special attributes used for declaring XML namespaces are exposed through the DOM and can be manipulated just like any other attribute. Moving a node within a document, using the DOM, in no case results in a change of its namespace prefix or namespace name. Similarly, creating a node with a namespace prefix and namespace name, or changing the namespace prefix of a node, does not result in any addition, removal, or modification of any special attributes for declaring the appropriate XML namespaces. Applications are therefore responsible for declaring every namespace in use when saving a document into XML.
Elements and attributes can still be created using the
createElement and createAttribute methods from
the Document interface. However, they do not have any
namespace prefix or namespace name then.
This option garantees full backwards compatibility with DOM Level 1,
however, it introduces a whole set of new interfaces and obsoletes a
large swath of the Level 1 API which simply cannot be used by a namespace
aware application.
The solution described in this section is based on the use of "universal names". Universal names are made of the namespace name and the local name. Although there isn't currently any standard syntax for such names the following has been proposed: {namespaceName}localName. Assuming such names exist, supporting Namespaces can then simply be achieved by changing the DOM Level 1 semantics so that wherever an element or attribute name is taken in argument, if it is a universal name, namespace special handling is thrown into gear.
The Node interface is extended to include a set
of attributes to access the namespace prefix and namespace name of
a node, and the local part of its qualified name (also called
"local name" in this document).
universalName attribute.)
interface NodeNS {
readonly attribute DOMString universalName;
readonly attribute DOMString namespaceName;
attribute DOMString prefix;
// raises(DOMException) on setting
readonly attribute DOMString localName;
};
universalNamenamespaceNamenull if it is unspecified.This is not a computed value that is the result of a namespace lookup based on an examination of the namespace declarations in scope. It is merely the namespace name given at creation time.
prefixnull if it is unspecified.
Note that setting this attribute changes the
nodeName attribute, which holds the qualified name,
as well as the Element.tagName and
Attr.name attributes when applicable.
DOMExceptionINVALID_CHARACTER_ERR: Raised if the specified prefix contains an invalid character.
localNameThe following methods of the Document interface are
changed.
createElementuniversalName |
The universal name of the element type to
instantiate. For XML, this is case-sensitive. For HTML, the
|
Element object with the following
attributes:| Attribute | Value |
|---|---|
Node.nodeName | qualified name, initialized with the local part extracted from universalName |
Node.namespaceName | namespaceName, extracted from universalName |
Node.prefix | null |
Node.localName | local part, extracted from universalName |
Element.tagName | qualified name, initialized with the local part extracted from universalName |
DOMExceptionINVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
createAttributeAttr of the given name.
The returned object implements the Attr interface as
well as the Node interface. It can then be set on an
Element using the setAttributeNode
method. This does not set the prefix which may be
defined later through the Node.prefix attribute.
universalName |
The universal name of the attribute. For HTML, this is simply the attribute name. |
Attr object with the following
attributes:| Attribute | Value |
|---|---|
Node.nodeName | qualified name, initialized with the local part extracted from universalName |
Node.namespaceName | namespaceName, extracted from universalName |
Node.prefix | null |
Node.localName | local part, extracted from universalName |
Attr.name | qualified name, initialized with the local part extracted from universalName |
DOMExceptionINVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
getElementsByTagNameNodeList of all the
Elements with a given universal name in
the order in which they would be encountered in a preorder
traversal of the Document tree.
universalName |
The universal name of the elements to match on. The special value "*" can be used to match all namespaces and/or local names. |
NodeList object containing
all the matched Elements.The following methods of the Element interface are
changed.
getAttributeuniversalName |
The universal name of the attribute to retrieve. |
Attr value as a string, or the empty
string if that attribute does not have a specified or default
value.setAttributeAttr node plus any Text and
EntityReference nodes, build the appropriate subtree, and
use setAttributeNode to assign it as the value of an
attribute.
universalName |
The universal name of the attribute to create or alter. | |
value |
Value to set in string form. |
DOMExceptionINVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
removeAttributeuniversalName |
The universal name of the attribute to remove. |
DOMExceptionNO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
getAttributeNodeAttr node by universal name.
universalName |
The universal name of the attribute to retrieve. |
Attr node with the specified attribute
universal name or null if there is no such
attribute.setAttributeNodenewAttr |
The |
newAttr attribute replaces
an existing attribute with the same universal name, the
previously existing Attr node is returned, otherwise
null is returned.DOMExceptionWRONG_DOCUMENT_ERR: Raised if newAttr was
created from a different document than the one that created the
element.
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
INUSE_ATTRIBUTE_ERR: Raised if newAttr is already
an attribute of another Element object. The
DOM user must explicitly clone Attr
nodes to re-use them in other elements.
getElementsByTagNameNodeList of all the
Elements with a given universal name in
the order in which they would be encountered in a preorder
traversal of the Document tree, starting from this
node.
universalName |
The universal name of the elements to match on. The special value "*" can be used to match all namespaces and/or local names. |
NodeList object containing
all the matched Elements.The model is the same as in Option #1, the difference only lies in the
way we define access to the namespace information. The Option #2 has the
obvious advantage of requiring only one new interface and very little
change to make an application namespace aware. However, this is
done at the cost of introducing some backwards incompatibility. Namely
what is considered to be an error in DOM Level 1, now simply throw into
gear some special handling of namespaces. In particular, while a DOM
Level 1 implementation raises an INVALID_CHARACTER_ERR
DOMException when "{myuri}foo" is passed to
Document.createElement, a DOM Level 2 implementation would
not. A DOM Level 1 application relying on this exception to be raised
would therefore fail on a DOM Level 2 implementation.
Here is a specific scenario where changing the behavior of the Level 1 DOM would adversely impact an application.
Consider an editor application authored using the Level 1 DOM that allows a
user to construct XML documents. One function of the editor allows the user
to create elements in the DOM tree. The user enters the tag name through a
UI that accepts the name of the tag, then calls Document.createElement to
create an element node and then inserts the node into the tree using
additional DOM methods (specifics are not req'd here). The editor allows the
user to save the document to disk through a menu item in the editor. The
save function is implemented using the Level 1 DOM. Basically, the save
function walks the tree writing out the XML. For each element, it uses
either the Node.nodeName or Element.tagName property to get the name of
the element to output.
Now, consider the same editor running under a Level 2 DOM implementation
(note that the editor has not been re-authored for Level 2 DOM). The user
agains begin creating elements in the DOM tree, however the user enters a
valid universal name into the editor which in turn calls
Document.createElement(). Since createElement() now accepts a universal
name in Level 2, this succeeds whereas it would have failed in Level 1. The
problems arises when the user tells the editor to save the document. As the
save function walks the tree to output the XML, data loss occurs because in
Level 1 there was no concept of namespaces. Therefore, Node.nodeName or
Element.tagName return only the localName without the namespace.
A code example for the scenario is:
function buildElement(tagName,parent)
{
parent.appendChild(document.createElement(tagName));
}
function saveTree(root)
{
switch (root.nodeType)
{
case Element:
print("<" + root.nodeName + ">");
for (i = 0 ; i < root.childNodes.length ; i++)
saveTree(root.childNodes.item(i));
print("</" + root.nodeName + ">");
break;
// add more processing for other node types
...
}
}
// foo entered by user
buildElement("foo",document.root);
saveTree(document.root);
<root> <foo></foo> </root>
// universal name entered by user
buildElement("{http://somedomain/foonamespace}foo",document.root);
saveTree(document.root);
<root> <foo></foo> </root>
getElementsByTagname is a misnommer when used with
namespaces, should we use another name?!! If yes, which one?
getElementsByName?