I'm looking for a XPath library to query over XML documents in FF, IE, Opera and Safari... and couldn't find one. Have you seen any?
-
Федор, seems you're not reading the posted answers? Did you already find a suitable implementation? Cheers – Dimitre Novatchev Dec 03 '08 at 03:41
12 Answers
Google has just released Wicked Good XPath - A rewrite of Cybozu Lab's famous JavaScript-XPath.
Link: https://github.com/google/wicked-good-xpath
The rewritten version is 40% smaller and about 30% faster than the original implementation.

- 339
- 4
- 9
-
this is the proper choice now in 2012. too bad you can't deprecate answers – Janus Troelsen Oct 17 '12 at 15:05
-
1Maybe, it is a good solution for HTML documents. But there is an open issue for XML documents https://code.google.com/p/wicked-good-xpath/issues/detail?id=7 – dizel3d Nov 11 '14 at 10:54
-
Note that at the time of writing, the download at the given link isn't working. Quickest solution I found was to get it from an NPM package ([here](https://github.com/jacobmarble/node-wgxpath)). – Kat Jan 09 '15 at 20:37
-
The project has moved to GitHub due to imminent shutdown of Google Code. I've just updated the link. – Dominator008 Apr 07 '15 at 18:14
Google's AJAXSLT open source project fits well the stated requirements.
As their own description goes to say:
"AJAXSLT is an implementation of XSLT in JavaScript. Because XSLT uses XPath, it is also an implementation of XPath that can be used independently of XSLT. This implementation has the advantange that it makes XSLT uniformly available on more browsers than natively provide it, and that it can be extended to yet more browsers if necessary. AJAXSLT is interesting for developers who strive aggressively for cross browser compatibility of their advanced web applications. "
UPDATE: In the end of 2010 Michael Kay has been compiling his Saxon XSLT 2.0 processor to Javascript (thus making it available to all 5 major browsers) using GWT. It is likely there will be a light-weight in-browser Saxon soon.

- 240,661
- 26
- 293
- 431
-
As of Nov 2011, the client edition (CE) of Kay's Saxon is still in alpha. – james.garriss Nov 09 '11 at 13:53
-
@james.garriss: this doesn't mean that it isn't used. There are interesting threads in the xsl-list on this topic. I suspect that Saxonica's main problem isn't technological, but more on finding the right business model for Saxon CE, so that it could be profitable. – Dimitre Novatchev Nov 09 '11 at 14:05
-
The linked page now has the following to say: *"The world of browser and web applications has moved on since this library was implemented in 2005. Many more browsers now implement XSLT and XPath natively, and, more importantly, fewer web applications use XML as their transfer data format, and moved on to the more appropriate and pragmatic JSON. A simpler more flexible way to bind data to HTML on the browser side for display in web applications is google-jstemplate."* – Wayne Dec 20 '11 at 20:22
-
@lwburk: I wouldn't be surprized to see Saxon CE used by all major browsers as their standard JS-based XSLT 2.0 processor. – Dimitre Novatchev Dec 20 '11 at 20:27
You could use the basic XPath plug-in for jQuery to get XPath query-ing functionality.
Also, you could consider reading this article on XPath XML processing (again with jQuery)

- 7,720
- 2
- 53
- 77

- 11,929
- 4
- 44
- 74
-
1Thanks! I've had a look at both. XPath plugin for jQuery simply converts XPath expression to the jQuery selection expression. It doesn't work even for simple cases. – Fedor Sheremetyev Oct 08 '08 at 15:42
-
This is what I use
// xpath.js
// ------------------------------------------------------------------
//
// a cross-browser xpath class.
// Derived form code at http://jmvidal.cse.sc.edu/talks/javascriptxml/xpathexample.html.
//
// Tested in Chrome, IE9, and FF6.0.2
//
// Author : Dino
// Created : Sun Sep 18 18:39:58 2011
// Last-saved : <2011-September-19 15:07:20>
//
// ------------------------------------------------------------------
/*jshint browser:true */
(function(globalScope) {
'use strict';
/**
* The first argument to this constructor is the text of the XPath expression.
*
* If the expression uses any XML namespaces, the second argument must
* be a JavaScript object that maps namespace prefixes to the URLs that define
* those namespaces. The properties of this object are taken as prefixes, and
* the values associated to those properties are the URLs.
*
* There's no way to specify a non-null default XML namespace. You need to use
* prefixes in order to reference a non-null namespace in a query.
*
*/
var expr = function(xpathText, namespaces) {
var prefix;
this.xpathText = xpathText; // Save the text of the expression
this.namespaces = namespaces || null; // And the namespace mapping
if (document.createExpression) {
this.xpathExpr = true;
// I tried using a compiled xpath expression, it worked on Chrome,
// but it did not work on FF6.0.2. Threw various exceptions.
// So I punt on "compiling" the xpath and just evaluate it.
//
// This flag serves only to store the result of the check.
//
// document.createExpression(xpathText,
// // This function is passed a
// // namespace prefix and returns the URL.
// function(prefix) {
// return namespaces[prefix];
// });
}
else {
// assume IE and convert the namespaces object into the
// textual form that IE requires.
this.namespaceString = "";
if (namespaces !== null) {
for(prefix in namespaces) {
// Add a space if there is already something there
if (this.namespaceString.length>1) this.namespaceString += ' ';
// And add the namespace
this.namespaceString += 'xmlns:' + prefix + '="' +
namespaces[prefix] + '"';
}
}
}
};
/**
* This is the getNodes() method of XPath.Expression. It evaluates the
* XPath expression in the specified context. The context argument should
* be a Document or Element object. The return value is an array
* or array-like object containing the nodes that match the expression.
*/
expr.prototype.getNodes = function(xmlDomCtx) {
var self = this, a, i,
doc = xmlDomCtx.ownerDocument;
// If the context doesn't have ownerDocument, it is the Document
if (doc === null) doc = xmlDomCtx;
if (this.xpathExpr) {
// could not get a compiled XPathExpression to work in FF6
// var result = this.xpathExpr.evaluate(xmlDomCtx,
// // This is the result type we want
// XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
// null);
var result = doc.evaluate(this.xpathText,
xmlDomCtx,
function(prefix) {
return self.namespaces[prefix];
},
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null);
// Copy the results into an array.
a = [];
for(i = 0; i < result.snapshotLength; i++) {
a.push(result.snapshotItem(i));
}
return a;
}
else {
// evaluate the expression using the IE API.
try {
// This is IE-specific magic to specify prefix-to-URL mapping
doc.setProperty("SelectionLanguage", "XPath");
doc.setProperty("SelectionNamespaces", this.namespaceString);
// In IE, the context must be an Element not a Document,
// so if context is a document, use documentElement instead
if (xmlDomCtx === doc) xmlDomCtx = doc.documentElement;
// Now use the IE method selectNodes() to evaluate the expression
return xmlDomCtx.selectNodes(this.xpathText);
}
catch(e2) {
throw "XPath is not supported by this browser.";
}
}
};
/**
* This is the getNode() method of XPath.Expression. It evaluates the
* XPath expression in the specified context and returns a single matching
* node (or null if no node matches). If more than one node matches,
* this method returns the first one in the document.
* The implementation differs from getNodes() only in the return type.
*/
expr.prototype.getNode = function(xmlDomCtx) {
var self = this,
doc = xmlDomCtx.ownerDocument;
if (doc === null) doc = xmlDomCtx;
if (this.xpathExpr) {
// could not get compiled "XPathExpression" to work in FF4
// var result =
// this.xpathExpr.evaluate(xmlDomCtx,
// // We just want the first match
// XPathResult.FIRST_ORDERED_NODE_TYPE,
// null);
var result = doc.evaluate(this.xpathText,
xmlDomCtx,
function(prefix) {
return self.namespaces[prefix];
},
XPathResult.FIRST_ORDERED_NODE_TYPE,
null);
return result.singleNodeValue;
}
else {
try {
doc.setProperty("SelectionLanguage", "XPath");
doc.setProperty("SelectionNamespaces", this.namespaceString);
if (xmlDomCtx == doc) xmlDomCtx = doc.documentElement;
return xmlDomCtx.selectSingleNode(this.xpathText);
}
catch(e) {
throw "XPath is not supported by this browser.";
}
}
};
var getNodes = function(context, xpathExpr, namespaces) {
return (new globalScope.XPath.Expression(xpathExpr, namespaces)).getNodes(context);
};
var getNode = function(context, xpathExpr, namespaces) {
return (new globalScope.XPath.Expression(xpathExpr, namespaces)).getNode(context);
};
/**
* XPath is a global object, containing three members. The
* Expression member is a class modelling an Xpath expression. Use
* it like this:
*
* var xpath1 = new XPath.Expression("/kml/Document/Folder");
* var nodeList = xpath1.getNodes(xmldoc);
*
* var xpath2 = new XPath.Expression("/a:kml/a:Document",
* { a : 'http://www.opengis.net/kml/2.2' });
* var node = xpath2.getNode(xmldoc);
*
* The getNodes() and getNode() methods are just utility methods for
* one-time use. Example:
*
* var oneNode = XPath.getNode(xmldoc, '/root/favorites');
*
* var nodeList = XPath.getNodes(xmldoc, '/x:derp/x:twap', { x: 'urn:0190djksj-xx'} );
*
*/
// place XPath into the global scope.
globalScope.XPath = {
Expression : expr,
getNodes : getNodes,
getNode : getNode
};
}(this));

- 189,189
- 101
- 473
- 713
Take a look at http://dev.abiss.gr/sarissa/ project. They have migrated most of XML-related APIs to IE, as well as evaluate method on document object. And indeed, jQuery doesn't have an XPath processor, it has a very simple path selector like: /a/b/c only

- 31,255
- 9
- 54
- 56
Here is the most recent cross-browser implementation of XPath in Javascript: https://github.com/andrejpavlovic/xpathjs
It is fully functional and unit tested, and has great support. The coolest part is that it also supports namespaces!

- 364
- 4
- 12
You may want to try jQuery XPath plugin with support for XPath 2.0 syntax that works cross-browser.

- 31,255
- 9
- 54
- 56
I don't think it allows for ad-hoc queries, but you might take a look at Johann Burkard's XSLT jQuery plug-in for inspiration on how to implement XPath queries. I use it in my jQuery Reference Dashboard widget and it's really solid.

- 21,688
- 16
- 67
- 79
You could make use of the existing native DOM support of each browser. For this you would have to create your own wrapper, the reason is the differences between browser. You can take a look at http://dotnetcaffe.blogspot.com
Best regards

- 1
-
Thanks for the link! I had to gave up finding a library and implemented a simple browser-specific wrapper around native DOM. Will try to use yours. – Fedor Sheremetyev Dec 15 '09 at 21:57
FormFaces (XForms implementation in JS) has a reliable XPath engine that can be easly extracted and used independently.
I think you can use Cameron McCormack's xpath library here. It's perfectly working for me.

- 645
- 1
- 7
- 14