Attr (W3C DOM Core object)

Spec
Version Depr. Parent
DOM1 No Node
Browser support (more…)
IE5.5+ FF1.5+ SA3+ OP9+
Buggy Buggy Full Buggy

Example

<link rel="stylesheet" type="text/css" href="default.css" />

The example above contains three attribute nodes: a rel attribute with the value stylesheet, a type attribute with the value text/css, and an href attribute with the value default.css.

Description

The Attr interface inherits from Node and represents a single attribute of an Element node.

However the Attr interface is a special case in terms of inheritance — attribute nodes are not child nodes of the element they belong to, and have no parent or sibling nodes, so although inherited Node properties such as parentNode and nextSibling are available, they always return null. Attributes are considered by the DOM to be properties of elements, rather than objects in their own right.

: Attributes as properties of elements

This is intended by the standard to make it easier to implement the DOM as an API layer on top of existing, legacy object models. And this is exactly what we see with HTML, in the way that known attributes are generally available as dot-properties of the element object they belong to.

However this intention, while good, is also a major reason why attribute implementations are such a mess across browsers!

An attribute may have an explicit or implicit value. An explicit value is one that's actually set by the author. An implicit value is where no explicit value is set but the document type has a default for that attribute; the default might be a specific value (such as the type attribute of an <input>, which defaults to text), or it might be empty (every HTML element has a default id and class attribute with an empty string as its value; in a DTD this corresponds with the #IMPLIED token).

However, empty default attributes do not appear in the DOM tree — only those attributes which have an actual value (either a specific default value in the DTD, or an explicit value) appear in the DOM; this is referred to as having an effective value.

The value can be both retrieved and set using the value property of the Attr node, or the nodeValue property of Node, or using methods of the owning Element such as getAttribute and setAttribute. An Attr node itself can be retrieved with getAttributeNode and added with setAttributeNode. When setting a value, the value is not parsed, so any entity references or other markup will be treated as literal text. To create an attribute containing entities the specification suggests to create an Attr node with appropriate Text and EntityReference nodes as children, then add it to an element using setAttributeNode, however in practise this rarely works (see the Compatibility notes below for details).

Similarly, the content of an Attr node may be considered child nodes, or it may be considered a simple string, and this varies by implementation (see the Compatibility notes below for details). Either way, the value and nodeValue properties return a string representation of this content.

The range of values a particular attribute is allowed to have is usually defined in the DTD.

Attribute types in Internet Explorer

In Internet Explorer in HTML, attributes retrieved using getAttribute are not actually mapped to element attributes at all, they're mapped to DOM properties. This has several significant (and annoying) implications:

  • Values are not all returned as strings: a style attribute returns a style object, an event-handling attribute such as onclick returns the contents of the event handler wrapped in an anonymous function, an attribute which evaluates to a boolean (such as disabled or checked) returns a boolean, and an attribute which evaluates to a number (such as tabindex) returns a number.
  • Some attributes can only be retrieved using the camel-cased name they use for their DOM property equivalent. The most notable examples are className (for class) and htmlFor (for for); other examples are tabIndex and accessKey.
  • The href of an <a> element and the src of an <img> element are both returned as fully-qualified URIs instead of the literal attribute value.

See getAttribute for a thorough rundown!

Namespaces on attributes

Unlike Element nodes, Attr nodes do not inherit a namespace from the element they're attached to — if an attribute does not have an explicitly defined namespace then it simply has no namespace.

The DOM consider that It would be redundant to require the use of a namespace prefix on every attribute that belongs to a specific element, so rather than this:

<html:a html:href="…">

We can simply put this:

<html:a href="…">

The href attribute is effectively a property of the <a> element - it has no namespace of its own, but it doesn't need one because it belongs to an element that does. The side-effect of this is that a namespaced attribute method such as getAttributeNS won't retrieve that attribute using the namespace of its owning element. The following example will not match the attribute above, because it isn't in the XHTML namespace, it's in no namespace:

element.getAttributeNS('http://www.w3.org/1999/xhtml',
        'href');

If we set an attribute called html:href on that same element, then we will in fact have created a second attribute — even though it has the same local name as the href attribute, it has a different namespace, hence it's a different attribute according to the DOM:

element.setAttributeNS('http://www.w3.org/1999/xhtml',
        'html:href', '/home/');

Having said that, some implementations will consider it to be the same attribute in some circumstances (see setAttributeNS for details). Such consideration cannot be really be called a bug, because the DOM does not define attribute associations (that job is handled by a DTD); it's more like a convenience feature, though admittedly a very confusing one!

The more simple case of attribute namespacing is where an attribute has an explicit prefix. This example will match an attribute called xml:lang in the XML namespace:

element.getAttributeNS('http://www.w3.org/XML/1998/namespace',
        'lang');

Compatibility

Internet Explorer Firefox Safari Opera
5.5 6.0 7.0 1.5 2.0 3.0 1.3 2.0 3.0 9.0 9.5
Buggy Buggy Buggy Buggy Buggy Buggy Buggy Buggy Full Buggy Buggy

In Internet Explorer empty default attributes do appear in the DOM, and can be retrieved from the attributes collection.

Internet Explorer 5.5 in HTML cannot retrieve attribute nodes, only attribute values, which means that the majority of this interface is untestable in that browser. However attribute values retrieved through the attributes collection do expose the specified property, and inherit the nodeName and nodeValue properties of Node.

Internet Explorer 6 and 7 don't implement the ownerElement property; and don't inherit the normalize method from Node. These browsers also have a myriad of bugs and quirks relating to the retrieval, setting and changing of attribute values, most of which are down to the way that attributes are mapped to DOM properties (as noted above). More details can be found in the documentation for each attribute method individually (such as getAttribute).

Internet Explorer in HTML, Firefox and Opera do not support the creation of attribute values by appending Text or EntityReference nodes to an Attr node, they only support setting the value or nodeValue property.

: Attribute values may, or may not, be child nodes of the attribute

Internet Explorer in HTML, Safari 1.3 and 2 and Opera do not consider the value of an attribute to be a child Text node of the Attr node: in Internet Explorer in HTML childNodes is null; in Safari 1.3 and 2 and Opera it's a collection with zero members. However the specification contradicts itself on which is the correct behavior1, therefore neither behavior is considered a bug.

In Internet Explorer in HTML and Firefox the specified property of an attribute that's been created but not yet added to an element returns false (should be true).

In Safari 1.3 and 2 the value property of an attribute node is readonly (i.e. it can't be used to set the value, only retrieve it).

In Opera 9.0 in HTML mode2 the name of an attribute is often returned in uppercase; a consistent pattern for when this does/doesn't occur could not be established, but appears to be related to whether that attribute has already been referred to in lower case (in which case its name is returned in lowercase, otherwise uppercase). Also Opera 9.0 in pure XML (but not XHTML mode3) parses entities when setting the value of an attribute (via any of the attribute methods, or the attributes collection), contrary to the specification.

In this Section

Footnotes

1 In the Attr interface specification it says that "In XML, where the value of an attribute can contain entity references, the child nodes of the Attr node may be either Text or EntityReference nodes...", which implies that attribute values are considered child nodes only in XML, but could also be interpreted to mean that attribute values can only contain entities in XML. However it then goes on to say that "Because the DOM Core is not aware of attribute types, it treats all attribute values as simple strings...", implying that an attribute never has child nodes. Later, in the Element interface specification it says "In XML, where an attribute value may contain entity references, an Attr object should be retrieved to examine the possibly fairly complex sub-tree representing the attribute value. On the other hand, in HTML, where all attributes have simple string values..."; this re-inforces the original inference that attribute values are considered child nodes only in XML. However in the setAttribute specification it says that "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 sub-tree, and use setAttributeNode to assign it as the value of the attribute...", without mentioning any caveat for document types. The overall inference is that attribute values in HTML are always simple strings, and attribute values in XML may be simple strings or child nodes, however the specification is not sufficiently clear on this point to be able to say absolutely that one or the other is correct.

2 On XHTML or HTML pages served as text/html.

3 On XHTML pages served as application/xhtml+xml.

User-contributed notes

Related Products