WD-DOM-Level-2-19990719


2. Document Object Model Namespaces

Editors
Arnaud Le Hors, W3C

Table of contents


2.1. Introduction

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.

(ED: Eventually only one of these two options will remain. But which one is still to be decided.)
(ED: This section defines a set of new interfaces but their methods and attributes are actually meant to be added to the corresponding DOM Level 1 interface. The next version of this specification will make that clear.)

2.2. The Namespaces related Interfaces Option #1

Interface NodeNS

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

IDL Definition

interface NodeNS {
  readonly attribute DOMString        namespaceName;
           attribute DOMString        prefix;
                                        // raises(DOMException) on setting

  readonly attribute DOMString        localName;
};

Attributes
namespaceName
Returns the namespace name of this node or 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
The namespace prefix of this node or 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.

Exceptions on setting
DOMException

INVALID_CHARACTER_ERR: Raised if the specified prefix contains an invalid character.

localName
Returns the local part of the qualified name of this node.

For nodes created with a DOM Level 1 method, such as Document.createElement, this is the same as Node.nodeName.

Interface DocumentNS

The Document interface provides two new methods for creating XML elements and attributes with a namespace prefix and namespace name.

IDL Definition

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);
};

Methods
createElementNS
Creates an element of the given qualified name and namespace name.
Parameters
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.

Return Value
A new Element object with the following attributes:
AttributeValue
Node.nodeNamequalifiedName
Node.namespaceNamenamespaceName
Node.prefixprefix, extracted from qualifiedName, or null if there is no prefix
Node.localNamelocal part, extracted from qualifiedName
Element.tagNamequalifiedName
Exceptions
DOMException

INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.


createAttributeNS
Creates an attribute of the given qualified name and namespace name.
Parameters
namespaceName

The namespace name of the attribute to create.

qualifiedName

The qualified name of the attribute to instantiate. This can contain a namespace prefix.

Return Value
A new Attr object with the following attributes:
AttributeValue
Node.nodeNamequalifiedName
Node.namespaceNamenamespaceName
Node.prefixprefix, extracted from qualifiedName, or null if there is no prefix
Node.localNamelocal part, extracted from qualifiedName
Attr.namequalifiedName
Exceptions
DOMException

INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.


getElementsByTagNameNS
Returns a NodeList 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.
Parameters
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.

Return Value
A new NodeList object containing all the matched Elements.

This method raises no exceptions.
Interface ElementNS

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.

IDL Definition

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);
};

Methods
getAttributeNS
Retrieves an attribute value by name and namespace name.
Parameters
namespaceName

The namespace name of the attribute to retrieve.

localName

The local name of the attribute to retrieve.

Return Value
The Attr value as a string, or an empty string if that attribute does not have a specified or default value.

This method raises no exceptions.
setAttributeNS
Adds a new attribute. If an attribute with that local name and namespace name is already present in the element, its value is changed to be that of the value parameter. This value is a simple string, it is not parsed as it is being set. So any markup (such as syntax to be recognized as an entity reference) is treated as literal text, and needs to be appropriately escaped by the implementation when it is written out. In order to assign an attribute value that contains entity references, the user must create an 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.
Parameters
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.

Exceptions
DOMException

INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.

NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.


This method returns nothing.
removeAttributeNS
Removes an attribute by local name and namespace name. If the removed attribute has a default value it is immediately replaced.
Parameters
namespaceName

The namespace name of the attribute to remove.

localName

The local name of the attribute to remove.

Exceptions
DOMException

NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.


This method returns nothing.
getAttributeNodeNS
Retrieves an Attr node by name and namespace name.
Parameters
namespaceName

The namespace name of the attribute to retreive.

localName

The local name of the attribute to retrieve.

Return Value
The Attr node with the specified attribute local name and namespace name or null if there is no such attribute.

This method raises no exceptions.
setAttributeNodeNS
Adds a new attribute. If an attribute with that local name and namespace name is already present in the element, it is replaced by the new one.
Parameters
newAttr

The Attr node to add to the attribute list.

Return Value
If 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.
Exceptions
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
Returns a NodeList 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.
Parameters
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.

Return Value
A new NodeList object containing all the matched Elements.

This method raises no exceptions.

2.3. Further Considerations about Namespaces and Option #1

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.

2.4. The Namespaces Support Option #2

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.

Interface NodeNS

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

(ED: This is the same as in Option #1 with the additional universalName attribute.)
IDL Definition

interface NodeNS {
  readonly attribute DOMString        universalName;
  readonly attribute DOMString        namespaceName;
           attribute DOMString        prefix;
                                        // raises(DOMException) on setting

  readonly attribute DOMString        localName;
};

Attributes
universalName
Returns the universal name of this node.
namespaceName
Returns the namespace name of this node or 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
The namespace prefix of this node or 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.

Exceptions on setting
DOMException

INVALID_CHARACTER_ERR: Raised if the specified prefix contains an invalid character.

localName
Returns the local part of the qualified name of this node.
Definition group Document changes

The following methods of the Document interface are changed.

Methods
createElement
Creates an element of the type specified.
Parameters
universalName

The universal name of the element type to instantiate. For XML, this is case-sensitive. For HTML, the universalName parameter is simply the tagName and it may be provided in any case, but it must be mapped to the canonical uppercase form by the DOM implementation. This does not set the prefix which may be defined later through the Node.prefix attribute.

Return Value
A new Element object with the following attributes:
AttributeValue
Node.nodeNamequalified name, initialized with the local part extracted from universalName
Node.namespaceNamenamespaceName, extracted from universalName
Node.prefixnull
Node.localNamelocal part, extracted from universalName
Element.tagNamequalified name, initialized with the local part extracted from universalName
Exceptions
DOMException

INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.


createAttribute
Creates an 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.
Parameters
universalName

The universal name of the attribute. For HTML, this is simply the attribute name.

Return Value
A new Attr object with the following attributes:
AttributeValue
Node.nodeNamequalified name, initialized with the local part extracted from universalName
Node.namespaceNamenamespaceName, extracted from universalName
Node.prefixnull
Node.localNamelocal part, extracted from universalName
Attr.namequalified name, initialized with the local part extracted from universalName
Exceptions
DOMException

INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.


getElementsByTagName
Returns a NodeList 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.
Parameters
universalName

The universal name of the elements to match on. The special value "*" can be used to match all namespaces and/or local names.

Return Value
A new NodeList object containing all the matched Elements.

This method raises no exceptions.
Definition group Element changes

The following methods of the Element interface are changed.

Methods
getAttribute
Retrieves an attribute value by universal name.
Parameters
universalName

The universal name of the attribute to retrieve.

Return Value
The Attr value as a string, or the empty string if that attribute does not have a specified or default value.

This method raises no exceptions.
setAttribute
Adds a new attribute. If an attribute with that universal name is already present in the element, its value is changed to be that of the value parameter. This value is a simple string, it is not parsed as it is being set. So any markup (such as syntax to be recognized as an entity reference) is treated as literal text, and needs to be appropriately escaped by the implementation when it is written out. In order to assign an attribute value that contains entity references, the user must create an Attr node plus any Text and EntityReference nodes, build the appropriate subtree, and use setAttributeNode to assign it as the value of an attribute.
Parameters
universalName

The universal name of the attribute to create or alter.

value

Value to set in string form.

Exceptions
DOMException

INVALID_CHARACTER_ERR: Raised if the specified name contains an invalid character.

NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.


This method returns nothing.
removeAttribute
Removes an attribute by universal name. If the removed attribute has a default value it is immediately replaced.
Parameters
universalName

The universal name of the attribute to remove.

Exceptions
DOMException

NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.


This method returns nothing.
getAttributeNode
Retrieves an Attr node by universal name.
Parameters
universalName

The universal name of the attribute to retrieve.

Return Value
The Attr node with the specified attribute universal name or null if there is no such attribute.

This method raises no exceptions.
setAttributeNode
Adds a new attribute. If an attribute with that universal name is already present in the element, it is replaced by the new one.
Parameters
newAttr

The Attr node to add to the attribute list.

Return Value
If the newAttr attribute replaces an existing attribute with the same universal name, the previously existing Attr node is returned, otherwise null is returned.
Exceptions
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
Returns a NodeList 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.
Parameters
universalName

The universal name of the elements to match on. The special value "*" can be used to match all namespaces and/or local names.

Return Value
A new NodeList object containing all the matched Elements.

This method raises no exceptions.

2.5. Further Considerations about Option #2

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
      ...
  }
}
The call sequence for Level 1 DOM would be:

  // foo entered by user
  buildElement("foo",document.root);
  saveTree(document.root);
The result would be:

<root>
   <foo></foo>
</root>
The call sequence for Level 2 DOM would be:

  // universal name entered by user
  buildElement("{http://somedomain/foonamespace}foo",document.root);
  saveTree(document.root);
The result would be:

<root>
  <foo></foo>
</root>
which is not the desired result.

2.6. Open Issues

  1. Which option do we choose?!!
  2. Is the name "localName" ok? The namespaces spec uses "localPart" but it doesn't seem descriptive enough. We could make it "localPartName". We need to sync with XSL.
  3. getElementsByTagname is a misnommer when used with namespaces, should we use another name?!! If yes, which one? getElementsByName?