February 6th, 2012
by Robbert Broersma
QName in JavaScript
XSLT uses attributes with a QName value quite a lot. If you don't know it: it is like an HTML class name, but it can have a prefix that points to a namespace. For example: sort, foo:sort and bar:sort are QNames, but the catch is: foo:sort are bar:sort are equal when they point to the same namespace. Just like with node names.
One use case is the method attribute for xsl:output. While most of you will only use output="xml" and output="html", there are custom methods that use these prefixes.
My JavaScript code looked something like this:
if (output.method === "html") { // Add <meta> element, custom DOCTYPE for "about:legacy-compat" } else if (output.method === "xml") { // Add prolog, etc. }
While I wanted to support these namespaced output methods as well, I didn't feel like cluttering existing code with namespace checks like this:
var method = new QName(output.method); if (method.namespaceURI === null && method.name === "html") { // .. } else if (method.namespaceURI === null && method.name === "xml") { // ... }
So here's what I did:
QName.prototype.valueOf = function () { return this.prefix ? "{" + this.namespaceURI + "}" + this.name : this.name; };
Now I can do both! First, === operators need to be replaced with == operators, but the existing code stays concise as it was:
var method = new QName(output.method); if (method == "html") { // ... } else if (method == "xml") { // ... } else if (method.namespaceURI === "http://saxon.sf.net/") { if (method.name === "base64Binary") { // ... } }
The full code of QName can be found in QName.js.