QUIS
LEGET
HAEC?

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.

Made in Holland, 100% JavaScriptRobbert Broersma