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.
