Friday, February 5, 2010

Fixing the XPath problem in Firefox 3.6

In Greasemonkey development, it is a common practice to use GM_xmlhttpRequest + DOM Document Wrapper + XPath to process cross-origin content. However in Firefox 3.6, the XPath query stop working. Here is the fix:

Firefox 3.5 code

var doc = document.implementation.createDocument("", "", null);
div.innerHTML = html;
doc.appendChild(div);
var res = doc.evaluate("//p[@class='content']/span", div, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
// res is null

Firefox 3.6 code

var isFF36up = false;
if (navigator.userAgent) {
var ffver = navigator.userAgent.match(/Firefox\/3\.(\d+)/);
isFF36up = ffver && parseInt(ffver[1], 10) >= 6;
}

var nsResolver = {
lookupNamespaceURI:function (prefix) {
if (isFF36up && prefix == "ns") {
return "http://www.w3.org/1999/xhtml";
}
else {
return "";
}
}
};

var doc = document.implementation.createDocument("", "", null);
div.innerHTML = html;
doc.appendChild(div);
var res = doc.evaluate("//ns:p[@class='content']/ns:span", div, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

2 comments:

Kejjo said...

Aye! It actually works. Thanks a lot. Could you also explain what is the problem, or did you find the solution elsewhere?

programy@zagrosze.com said...

var pulled = document.createElement('div');
pulled.innerHTML = responseDetails.responseText;

var pulleddoc = document.implementation.createDocument("", "", null);
pulleddoc.appendChild(pulled);

ex = "//ns:p[@class="error"]';
err = pulleddoc.evaluate(ex,pulled,nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;
GM_log(pulled.innerHTML);
alert(err.innerHTML);

not working :( what i'm doing wrong ?
(ofc both functions are defined)