17

I have, for example, the next XPath query:

//div[span="something"]/parent::div/child::div[@class=\"someClass\"]

I want to use this XPath query in JavaScript:

return $("a:contains('Fruits')").mouseover();

I tried this:

return $("div[span=\"something\"]/parent::div/child::div[@class=\"someClass\"]").mouseover();

But it didn't work. Is there another semantic for XPath queries in order to use them in JavaScript?

Jinxed
  • 356
  • 2
  • 16
Adam Sh
  • 8,137
  • 22
  • 60
  • 75

8 Answers8

25

You could add the results of an existing XPath evaluation to a jQuery selection, I threw together this jquery extension that seems does it all for you.

Example usage:

$(document).xpathEvaluate('//body/div').remove()

Here's the add-in.

$.fn.xpathEvaluate = function (xpathExpression) {
   // NOTE: vars not declared local for debug purposes
   $this = this.first(); // Don't make me deal with multiples before coffee

   // Evaluate xpath and retrieve matching nodes
   xpathResult = this[0].evaluate(xpathExpression, this[0], null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);

   result = [];
   while (elem = xpathResult.iterateNext()) {
      result.push(elem);
   }

   $result = jQuery([]).pushStack( result );
   return $result;
}
Orwellophile
  • 13,235
  • 3
  • 69
  • 45
17

You can re-write your xpath queries as CSS selectors:

$('div:has(> div > span:contains(something)) > div.someClass');

You can achieve the same effect as parent:: using the :has pseduo selector to select an element based on its children: div.foo:has(> div.bar) will select all div elements with class foo that have a child div with class bar. This is equivalent to div[@class="bar"]/parent::div[@class="foo"].

See:

You could probably approach this in several other ways using various combinations jQuery's DOM traversal methods. For example, this would be a very direct translation of your xpath query:

$('div:has(> span:contains(something))')  // //div[span="something"]
    .parent('div')                        // /parent::div
    .children('div.someClass');           // /child::div[@class="someClass"]

It's worth noting that div.someClass in CSS isn't the exact equivalent of div[@class="someClass"] in xpath. The CSS will match <div class='foo someClass bar'>, but the xpath won't. See Brian Suda's article on parsing microformats with XSLT for more detail.

georgebrock
  • 28,393
  • 13
  • 77
  • 72
4

As the co-author of Wicked Good XPath, I certainly recommend it for cross browser XPath support (on HTML documents, you can try using it with XML documents but the support is incomplete).

We welcome any sort of correctness test / performance benchmark on our library. During development, the library has been tested on IE 7 through 10 plus the Android 2.2 browser which doesn't have native XPath support.

Dominator008
  • 339
  • 4
  • 9
2

There is no Cross-browser implementation as far as I know. There is a xpath plugin for jQuery which says is still in developement.

Other than that there is a Google-authored pure JavaScript implementation of the DOM Level 3 XPath specification called wicked-good-xpath which is good.

Dominator008
  • 339
  • 4
  • 9
sv_in
  • 13,929
  • 9
  • 34
  • 55
2

if you want to select an element inside an iframe, from parent window, you should change second parameter of evaulate() function to iframe's document element, like :

var iFrameDocument = $('iframe#myPage').get(0).contentWindow.document;
xpathResult = this[0].evaluate(xpathExpression, iFrameDocument, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
spetsnaz
  • 1,181
  • 1
  • 14
  • 11
1

I'm not sure about the parent::div clause, but without it it should look like this:

$('div[span="something"] div.someClass');
Constantinius
  • 34,183
  • 8
  • 77
  • 85
  • 1
    In xpath `div[span="something"]` selects `div` elements with a child `span` that has the text value `something`, it doesn't look for a `span` attribute. I think you're mixing it up with the (very similar looking) `div[@span="something"]`. See examples: http://www.w3.org/TR/xpath/#path-abbrev – georgebrock Sep 03 '12 at 09:41
0

read from here about the evaluate method : https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript

var xpathResult = document.evaluate( xpathExpression, contextNode, namespaceResolver, resultType, result );
CosminO
  • 5,018
  • 6
  • 28
  • 50
0

jQuery only has limited support for XPath. You can see what it does support here: http://docs.jquery.com/DOM/Traversing/Selectors#XPath_Selectors

As mentioned by @Ameoo you can use the evaluate method, which is available in most modern browsers - except, predictably, IE: jquery select element by xpath

Community
  • 1
  • 1
Robin Winslow
  • 10,908
  • 8
  • 62
  • 91