While working with the Chrome Developer Tool I’ve discovered that you can retrieve the XPath of a selected node. It’ll return something like: //*[@id=”top”]/div[1]/div[1].

Lately I’ve been working on Chrome extension CHash Thunder. Its aim is to update parts of the CloudHashing.com interface to provide the use with more information. Chrome’s XPath feature is very handy, because it allows me to just store a bunch of JavaScript variables with XPath references to the user interface. If they’ll every change the UI, I’ll update those variables.

var TOP_MENU = '//*[@id="header"]/div/div/div[2]/div/div[1]/ul';
var INVESTMENT_BOX = '//*[@id="content"]/div/div[1]/div[3]/div[2]';
var LAST_ROUND = '//*[@id="content"]/div/table/tbody/tr[1]/td[1]';
var LAST_ROUND_DATE = '//*[@id="content"]/div/table/tbody/tr[1]/td[3]';
var BTC_BALANCE = '//*[@id="header"]/div/div/div[2]/div/div[1]/ul/li[3]';

The $x function can be used to get the element node.

var element = $x(TOP_MENU);

But… it only work in Chrome. So what about other browsers? What about jQuery? What about querying documents that resulted from an AJAX request?

To solve these problems I’ve created a simple parser that will convert the XPath into a jQuery selector using regex parsing:

function $xp(xPath, $scope) {
    var selector = convertXPath(xPath);
    return $(selector, $scope);
}

function convertXPath(x) {

    //parse //*
    x = replace(x, '//\\*', '');

    //parse id
    x = replace(x, '\\[@id="([^"]*)"\\]', '#$1');

    //parse [1]
    x = replace(x, '\\[1\\]', ':first');

    //parse [n]
    x = replace(x, '\\[([0-9]+)\\]', ':eq($1)');

    //parse :eq's and lower 1
    var z = x.split(':eq(');
    x = z[0];
    if (z.length > 1) {
        for (var i = 1; i < z.length; i++) {
            var end = z[i].indexOf(')');
            var number = parseInt(z[i].substr(0, end)) - 1;
            x = x + ':eq(' + number + z[i].substr(end);
        }
    }

    //parse /
    x = replace(x, '/', ' > ');

    return x;
}

function replace(txt, r, w) {
	var re = new RegExp(r, "g");
	return txt.replace(re, w);
}

Here is an example that uses $xp  to get the text of a hyperlink from an AJAX result:

var FIRST_RECORD_LINK = '//*[@id="rso"]/li[1]/div/h3/a';

$.ajax({
    type: "POST",
    url: '/Test.aspx',
    success: function (data, textStatus, request) {

        var $d = $('<div>').html(data);
        var $a = $xp(FIRST_RECORD_LINK, $d);
        alert($a.text());
    }
});

2015-04-01 – developments

Now Chrome has a Copy CSS Path option. That expression can be used by jQuery without any problems.