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; };
namespaceName
null
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
.
prefix
null
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.
DOMException
INVALID_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); };
createElementNS
namespaceName |
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 |
DOMException
INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
createAttributeNS
namespaceName |
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 |
DOMException
INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
getElementsByTagNameNS
NodeList
of all the
Element
s 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 Element
s.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); };
getAttributeNS
namespaceName |
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.setAttributeNS
Attr
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. |
DOMException
INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
removeAttributeNS
namespaceName |
The namespace name of the attribute to remove. | |
localName |
The local name of the attribute to remove. |
DOMException
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
getAttributeNodeNS
Attr
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.setAttributeNodeNS
newAttr |
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.DOMException
WRONG_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.
getElementsByTagNameNS
NodeList
of all the
Element
s 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 Element
s.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; };
universalName
namespaceName
null
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.
prefix
null
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.
DOMException
INVALID_CHARACTER_ERR: Raised if the specified prefix contains an invalid character.
localName
The following methods of the Document
interface are
changed.
createElement
universalName |
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 |
DOMException
INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
createAttribute
Attr
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 |
DOMException
INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
getElementsByTagName
NodeList
of all the
Element
s 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 Element
s.The following methods of the Element
interface are
changed.
getAttribute
universalName |
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.setAttribute
Attr
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. |
DOMException
INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
removeAttribute
universalName |
The universal name of the attribute to remove. |
DOMException
NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
getAttributeNode
Attr
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.setAttributeNode
newAttr |
The |
newAttr
attribute replaces
an existing attribute with the same universal name, the
previously existing Attr
node is returned, otherwise
null
is returned.DOMException
WRONG_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.
getElementsByTagName
NodeList
of all the
Element
s 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 Element
s.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
?