Transformations with DOM

If you're already familiar with using the DOM Level 2 interface to manipulate HTML, this next part should be familiar. Here's the basic approach:

Identify and obtain references to all title and link element pairs in the RSS document.

Pull the text out of each pair.

Create an XHTML link (<a>) with the specified title and URL text.

Replace the title element with the HTML link in the document.

The following code uses the DOM method getElementsByTagName to retrieve a collection of item element references in the XML document. The for loop that follows iterates over the collection and obtains references to the title and link element in each. Finally, the text of the link and title are extracted by first referencing the text node in each, then the nodeValue property of the node:

This provides the needed pieces to build an appropriate HTML link for each RSS item. A bit more code is needed to get everything working, however.

Dealing with Namespaces

The concept of XML namespaces became a W3C recommendation in 1999. They exist to allow XML elements from different schemas to be mixed without colliding. For example, XHTML has a title element, as does RSS. To keep an XML parser from confusing the two, a namespace is declared in the XML document's root element. The namespace consists of a prefix associated with a URI, and is used to distinguish elements and attributes imported from another XML specification.

The following markup fragment demonstrates how to import an XHTML img element into an RSS document:

The xmlns attribute associates the namespace prefix "xhtml" with the URI. In this way, an XML parser is made aware that the img element exists in a namespace outside the default one. (This is, of course, no guarantee that the parser will know what to do with the img, as not all XML parsers are necessarily browsers.)

When using the DOM interface with an XHTML document, it's assumed that all new elements created programmatically with createElement are in fact XHTML elements. The DOM Level 2 spec provides a different method for creating elements from different namespaces. The createElementNS method accepts two arguments: a string referencing the URI of the namespace and a string representing the element to be created:

Since my application is intended to be read by a browser, I can use createElementNS to import an XHTML <a> element into my RSS document. With the information gathered from the earlier DOM operation, I can assign an href attribute to the new <a> element, then create and insert a new text node. Since the href attribute, like the <a> element itself, is imported from XHTML, I need to use the setAttributeNS method. This method operates exactly as the DOM 2 setAttribute method does, and utilizes an additional argument declaring the namespace of the attribute.

Finally, I replace the RSS title element in this item with the XHTML <a> element, using the DOM 2 replaceChild method to do so. Mozilla should now allow the title of the item to behave as an XHTML link. Here's the full code of my node tranversal script:

Attaching the Script

To implement this, I need to associate the script with the RSS document so these DOM transformations can take place at runtime. At the time of this writing, I could not find an agreed-upon way to associate an external script file with an XML document (unlike xml-stylesheet, there seems to be no equivalent "xml-script" processing instruction, and it seems doubtful that the W3C will move forward with this approach). There is no "onload" method of an RSS document, so I'll need a different plan of attack.

Using an XML namespace declaration I can import an XHTML script element and insert it as the last element in the RSS document root. Placing the script call at the bottom ensures that the document is loaded into memory before the JavaScript is executed:

Loading the RSS file in Mozilla now produces the desired result: clickable title links. You can see a working example here, although you'll need Mozilla 1.0 or better to experience it.

An Alternate Approach: XLink

Mozilla supports basic linking via XLink as an alternative to importing XHTML. With XLink, there's no need to create a new element. Instead, the linking functionality comes from attaching XLink attributes to the element in question, thereby making any element a potential link.

To accomplish this, affix the proper XLink attributes to the item's title element with the setAttributeNS method. Here's a modified version of the JavaScript that incorporates XLink in place of XHTML:

Future Directions

It's been argued that Web developers might be better off sticking to valid HTML 4.01 until user agents are able to parse and render XML properly. Perhaps, though as I've demonstrated, some user agents are already well prepared to deal with XML. The power of CSS and DOM in transforming XML has led many to question why technologies like XSLT are even necessary. I don't make any such claims, but if the capabilities of Mozilla 1.0 are any indication, the future of XML on the Web is within reach, and looks bright indeed.

Further Reading and Resources:

XML in Mozilla: links to resources on the XML capabilities of Mozilla.