Here is an implementation of lookupPrefix which should work cross-browser.
Note that all Gecko-based browsers (including Firefox) support Node.lookupPrefix. This function is not necessary for Gecko-based browsers when used in XHTML.
function lookupPrefix (node, namespaceURI) {
var htmlMode = document.contentType; // Mozilla only
// Depends on private function _lookupNamespacePrefix() below and on https://developer.mozilla.org/En/Code_snippets/LookupNamespaceURI
// http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespacePrefix
// http://www.w3.org/TR/DOM-Level-3-Core/namespaces-algorithms.html#lookupNamespacePrefixAlgo
// (The above had a few apparent 'bugs' in the pseudo-code which were corrected here)
if (node.lookupPrefix && htmlMode !== 'text/html') { // Shouldn't use this in text/html for Mozilla as will return null
return node.lookupPrefix(namespaceURI);
}
if (namespaceURI === null || namespaceURI === '') {
return null;
}
switch (node.nodeType) {
case 1: // Node.ELEMENT_NODE
return _lookupNamespacePrefix(namespaceURI, node);
case 9: // Node.DOCUMENT_NODE
return _lookupNamespacePrefix(namespaceURI, node.documentElement);
case 6: // Node.ENTITY_NODE
case 12: // Node.NOTATION_NODE
case 11: // Node.DOCUMENT_FRAGMENT_NODE
case 10: // Node.DOCUMENT_TYPE_NODE
return null; // type is unknown
case 2: // Node.ATTRIBUTE_NODE
if (node.ownerElement) {
return _lookupNamespacePrefix(namespaceURI, node.ownerElement);
}
return null;
default:
if (node.parentNode) {
// EntityReferences may have to be skipped to get to it
return _lookupNamespacePrefix(namespaceURI, node.parentNode);
}
return null;
}
}
// Private function for lookupPrefix only
function _lookupNamespacePrefix (namespaceURI, originalElement) {
var xmlnsPattern = /^xmlns:(.*)$/;
if (originalElement.namespaceURI && originalElement.namespaceURI === namespaceURI &&
originalElement.prefix && originalElement.lookupNamespaceURI(originalElement.prefix) === namespaceURI) {
return originalElement.prefix;
}
if (originalElement.attributes && originalElement.attributes.length) {
for (var i=0; i < originalElement.attributes.length; i++) {
var att = originalElement.attributes[i];
xmlnsPattern.lastIndex = 0;
var localName = att.localName || att.name.substr(att.name.indexOf(':')+1); // latter test for IE which doesn't support localName
if (localName.indexOf(':') !== -1) { // For Firefox when in HTML mode
localName = localName.substr(att.name.indexOf(':')+1);
}
if (
xmlnsPattern.test(att.name) &&
att.value === namespaceURI &&
lookupNamespaceURI(originalElement, localName) === namespaceURI
) {
return localName;
}
}
}
if (originalElement.parentNode) {
// EntityReferences may have to be skipped to get to it
return _lookupNamespacePrefix(namespaceURI, originalElement.parentNode);
}
return null;
}
