我正在使用“普通和现代”浏览器(FF,Chrome,Opera,Safari ......)进行大量的XPath,但我正在寻找一个允许IE支持document.evaluate()
方法的JavaScript库
它存在吗?我知道在StackOverflow中有一些类似的问题,但他们被问及&多年前回答。
这个想法是:在读取xpath和amp;时分解代码。也产生(相同)xpath。
更新,2011年8月8日:
我在这里找到@ExtremeCoder提出的lib:http://sourceforge.net/projects/html-xpath/
这正是我所需要的(它“覆盖”document.evaluate仅适用于IE)...但它会在chrome&它在IE上不起作用:/
更新 2012年8月29日(是的,一年后)。
我测试了各种各样的库。很多覆盖document.evaluate的东西都不是很强大或者受到不同的bug的影响。 我最终使用了没有XSLT部分的旧的Google Ajax XSLT;)
http://goog-ajaxslt.sourceforge.net/
(所以我验证你的答案@Cheeso)
顺便说一下,很多(或所有)这些库都不再维护了。
更新,2012年9月28日:
Google 启动另一个XPath lib项目。 我还没有测试它,但它看起来很有前途和更新。 http://code.google.com/p/wicked-good-xpath/
像往常一样,感谢Microsoft(对于资源管理器8/9/10)(原文!),请学习支持基本标准和其他浏览器行为。
答案 0 :(得分:1)
http://blogs.msdn.com/b/dareobasanjo/archive/2004/04/20/116815.aspx
我认为应该这样做。
-
道歉,我认为这个网站实际上正是您所寻找的:http://www.dashop.de/blog/en/dev/JavaScript/content/XPath/JavaScript-XPath-Implementation.html
答案 1 :(得分:0)
这就是我使用的:
// 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));
您可以在所有浏览器中使用相同的代码,但不是document.evaluate()
,而不是直接使用 var xpath = new XPath.Expression("/a:kml/a:Document",
{ a : 'http://www.opengis.net/kml/2.2' });
var node = xpath.getNode(xmldoc);
。相反,你这样使用它:
{{1}}
答案 2 :(得分:0)
根据您的需要,您可以找到有用的MochiKit选择器API:http://mochi.github.com/mochikit/doc/html/MochiKit/Selector.html
我所有人都使用了xpath,它非常轻巧,适用于所有主流浏览器。
答案 3 :(得分:0)
以下是Javascript中最新的XPath跨浏览器实现:https://github.com/andrejpavlovic/xpathjs
它功能齐全,经过单元测试,并得到了很大的支持。最酷的部分是它还支持命名空间!