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 // https://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespacePrefix // https://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; }