Handling Attributes and Namespaces

XML namespaces and attributes are similar in some respects but different in others. Attributes are name-value pairs that are typically used to hold metadata related to the element. Namespaces are considerably more complex in purpose. They serve to distinguish elements and attributes from different sources that have identical names but different meanings. They are also used to group related attributes and elements so that a processing application can easily recognize them. Namespaces are declared in a manner similar to the way attributes are, but with an xmlns:prefix name assigned a value that is a URI, for example:

<employee xmlns:emp="http://www.acme.com/defs/empl.html"/>

This construction maps the prefix to a unique URI identifier; thereafter the prefix can be used to identify the namespace of an attribute or element (for example, “<emp:title></emp:title>”). Default, prefix-less namespaces can also be declared that affect all current and descendent elements and attributes past the point of declaration, unless they are overridden by another namespace.

Although the purposes of attributes and namespaces are different, they are conceptually similar. They cannot be children of an element node, but they are always closely associated with one. Indeed the associated element is their parent. Even though they are NSXML nodes—NSXMLNode objects of kinds NSXMLAttributeKind and NSXMLNamespaceKind—they cannot have children and cannot be children of any node. (Namespaces, however, can qualify the attributes of an element as well as the element itself.) Namespace and attribute nodes are not encountered during document traversal.

The programmatic interface of NSXMLElement reflects this architectural affinity. It offers similar sets of methods for namespace nodes and attribute nodes. This articles explains how to use these methods and then discusses a unique feature of the namespace API: resolving namespaces.

Methods for Manipulating Attributes and Namespaces

The NSXMLElement class defines methods for manipulating and accessing an element’s attributes that are nearly identical in form to another set of methods for manipulating and accessing namespace nodes. Table 1 lists these complementary sets of methods.

Table 1  Attribute and namespace node manipulation methods

Attribute methods

Namespace methods

addAttribute:

addNamespace:

setAttributes:setAttributesAsDictionary:

setNamespaces:

removeAttributeForName:

removeNamespaceForPrefix:

attributes

namespaces

attributeForName:attributeForLocalName:URI:

namespaceForPrefix:

The names of these methods clearly indicate what you use them for, but some comments about each category of method are warranted:

Once you have accessed a specific namespace or attribute node, you can get or set its string or object value (see “Changing the Values of Nodes” for details). Bear in mind that the value of a namespace node is the URI of the namespace; if you want to set the URI as an object value, make it an NSURL object.

Resolving Namespaces

If your application knows (or suspects) that it might be dealing with XML from different sources or authored in different XML vocabularies, such as XSLT and RDF, it has to deal with namespaces. At any point of processing it might have to know the namespace to which an element or attribute is bound in order to handle that element or attribute appropriately. A case in point is the set element, which is defined by both SVG and MathML for different purposes. Before you can determine the meaning of a set element in a document containing both SVG and MathGL markup, you have to find out which namespace it belongs to. To find out the namespace affiliation of an element you must resolve it.

For namespace resolution, NSXMLElement declares two methods beyond the ones discussed in “Methods for Manipulating Attributes and Namespaces.”

The first method takes the qualified or local name of an element and returns the namespace node representing the namespace to which the element belongs. Your application can get the URI from the node (its string value) and compare it to a list of known or expected URIs to determine namespace affiliation. If there is no associated namespace, the resolveNamespaceForName: method returns nil.

The second namespace-resolution method, resolvePrefixForNamespaceURI:, works in the opposite direction. You pass in a URI and get back the prefix bound to that URI. You can use this method, for example, when you are adding elements to a document and need to know the prefixes of their qualified names.