LookupPrefix

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;
}