5

Is it possible to generate the most specific XPath expression automatically from the position of the cursor on the web page? The XPath expression would change with "onMouseMove event".

If it's possible, how would you implement it? Or is it already implemented in some Javascript or Python library? I would prefer it in Python with a combination of some web library but Javascript would be good and acceptable too.

Cœur
  • 37,241
  • 25
  • 195
  • 267
xralf
  • 3,312
  • 45
  • 129
  • 200
  • Do you mean like "Google chrome" functionality when right-clicking on an element and getting the html-element for it in the inspector? – Andreas Helgegren Feb 02 '12 at 20:56
  • You mean like firebug functionality to get xpath. – RanRag Feb 02 '12 at 20:58
  • possible duplicate of [Return XPath location with jQuery? Need some feedback on a function](http://stackoverflow.com/questions/4404454/return-xpath-location-with-jquery-need-some-feedback-on-a-function) – Gabriele Petrioli Feb 02 '12 at 21:04
  • @RanRag Yes, exactly, I didn't know that firebug has this functionality. – xralf Feb 02 '12 at 21:09
  • @xralf : so my comment answered your question or not. – RanRag Feb 02 '12 at 21:11
  • 1
    There is no such thing as a "most specific xpath statement". In order to be the most specific, it would encode the whole document. Is a path such as `/*[1]/*[3]/*[5]/*[2]` "more specific" than `/html/body/div[3]/em`? How do you measure "specificness"? – Has QUIT--Anony-Mousse Feb 02 '12 at 21:12
  • @GabyakaG.Petrioli `JQuery` is a library that I don't have time to learn now, so I prefer it rather in `Javascript` or `Python` and this makes a difference because I would have to study `JQuery` syntax specialities. – xralf Feb 02 '12 at 21:12
  • @RanRag I'd like to implement it javascript or python, not only use in `firebug`. – xralf Feb 02 '12 at 21:14
  • @Anony-Mousse That's good comment. I hoped it will be understood but you're right, there can be more most specific statements. `most specific` is every statement that identifies an element which is most nested (hasn't any other children) and is unambiguous ( = there can't be two elements identified with this XPath expression) – xralf Feb 02 '12 at 21:18

3 Answers3

2

See the Get XPath thread in DZone Snippets for finding the XPath. See the How do I check if the mouse is over an element in jQuery? question here for identifying when the mouse cursor is over an element.

Community
  • 1
  • 1
JamieSee
  • 12,696
  • 2
  • 31
  • 47
  • Thank you. This is really helpful, only the `JQuery` part would be better in `Javascript`, but I can ask for this checking mouse position in another question. – xralf Feb 02 '12 at 21:25
  • JQuery is just a library of javascript functions, under the hood it's all javascript. See http://www.jquery.com/. It's useful for a TON of things and is cross-browser compliant. – JamieSee Feb 02 '12 at 21:51
  • I know but the syntax is quite advanced. – xralf Feb 02 '12 at 21:53
  • 1
    True, it's initially unfamiliar and there'll be a little learning curve involved, but like any good tool, it gains you back a lot of time once you've passed that and start using it. Fortunately the documentation for it is pretty good. I've found learning it really worthwhile, and once the other developers here saw what I could do with it, they were hooked too. – JamieSee Feb 02 '12 at 22:01
2

I have answered an almost identical question (using jQuery) at Return XPath location with jQuery? Need some feedback on a function

If you change the click event to mouseenter you would have what you ask for..

$(document).delegate('*','mouseenter',function(){
    var path = $(this).parents().andSelf();
    var xpath='/';
    for (var i = 0; i < path.length; i++)
    {
        var nd = path[i].nodeName.toLowerCase();
        xpath += '/';
        if (nd != 'html' && nd != 'body')
        {
            xpath += nd;
            if (path[i].id != '')
            {
                xpath += '#' + path[i].id;
            }
            else
            {
                xpath += '['+ ($(path[i-1]).children().index(path[i])+1) +']';
            }
            if (path[i].className != '')
                xpath += '.' + path[i].className;
        }
        else
        {xpath += nd;}                    
    }
    $('#xpath').html(xpath); // show the xpath in an element with id xpath..
    return false;
});

Demo at http://jsfiddle.net/gaby/hsv97/25/


Update with no jQuery used.. (for modern browsers)

function getXpath(event){
    var hierarchy = [],
        current = event.srcElement||event.originalTarget;
    while (current.parentNode){
        hierarchy.unshift(current);
        current = current.parentNode;
    }
    var xPath = hierarchy.map(function(el,i){
            return el.nodeName.toLowerCase() + ((el.id !== '') ? '#'+el.id : '') + ((el.className !== '') ? '.'+el.className.split(' ').join('.') : '');
        }).join('/');
    document.getElementById('xpath').innerHTML = xPath;
    return xPath;
}

if (document.addEventListener){
    document.addEventListener('mouseover', getXpath, false);
} else {
    document.onmouseover = getXpath;
}

Demo at http://jsfiddle.net/gaby/hsv97/29/

Community
  • 1
  • 1
Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
  • Thank you, I appreciate it, but `JQuery` is not in my skills yet so don't understand it. – xralf Feb 02 '12 at 21:27
  • Thank you. I already accepted the faster answer from James, but your seems be as good as his. – xralf Feb 02 '12 at 21:57
  • @GabyakaG.Petrioli you vanilla version is invalid, does not have indexes. my version: http://jsfiddle.net/nycu2/1/ – slf Mar 25 '14 at 18:12
0

vanilla javascript (with indices) http://jsfiddle.net/nycu2/1/

function nodeindex(element, array) {
    var i,
        found = -1,
        element_name = element.nodeName.toLowerCase(),
        matched
       ;

    for (i = 0; i != array.length; ++i) {
        matched = array[i];
        if (matched.nodeName.toLowerCase() === element_name) {
            ++found;


        if (matched === element) {
            return found;
        }
        }
    }

    return -1;
}

function xpath(element, suffix) {
    var parent, child_index, node_name;

    parent = element.parentElement;

    if (parent) {
        node_name = element.nodeName.toLowerCase();
        child_index = nodeindex(element, parent.children) + 1;
        return xpath(parent, '/' + node_name + '[' + child_index + ']' + suffix);
    } else {
        return '//html[1]' + suffix;
    }
}

function xpathstring(event) {
    var
    e = event.srcElement || event.originalTarget,
        path = xpath(e, '');;

    document.querySelector('.xpathresult').value = path;

    highlight();
}
slf
  • 22,595
  • 11
  • 77
  • 101