Created
June 1, 2010 10:24
SpryEvaluateXPath
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Spry.Data.XMLDataSet.evaluateXPath = function( contextNode, xpath ){ | |
var results = [], | |
parser, i, length, tmp; | |
// Quit processing if we don't even have sufficient data to process | |
if( !( contextNode && xpath ) ) return results; | |
// Check if the Google Xpath library is available. If it's included it's | |
// usually an indication that user wants to use it as default. | |
if( window.ExprContext && window.xpathParse ){ | |
results.concat( xpathParse( xpath ).evaluate( new ExprContext( contextNode ) ).nodeSetValue() ); | |
// if we have results, return | |
return results; | |
} | |
// Check if native technologies are available for parsing the xpath | |
if( window.XSLTProcessor ){ | |
parser = ( new XPathEvaluator() ).evaluate( xpath, contextNode, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); | |
if( !!parser ){ | |
while( tmp = parser.iterateNext() ){ | |
results.push( tmp ); | |
} | |
// if we have results, return | |
return results; | |
} | |
} | |
// And we can attempt to leverage IE technologies here | |
if( window.ActiveXObject ){ | |
parser = contextNode.selectNodes( xpath ); | |
if( !!parser ){ | |
for( i = 0, length = parser.length; i < length; i++ ){ | |
results.push( parser[i] ); | |
} | |
// if we have results, return | |
return results; | |
} | |
} | |
// The Google Xpath library is not available, and the native functions didn't | |
// produce any results. So we use Spry custom parser to handle 80% of the cases | |
// The following paths are handled by the code below: | |
// | |
// /gallery/photos/photo | |
// /gallery/photos/* | |
// gallery/photos/photo | |
// /gallery//photo | |
// //photo | |
// //photo/@path | |
// //photo/@* | |
// Following code by the Spry Team with a small Chrome patch by Arnout Kazemier :) | |
var ctx = [contextNode]; | |
var immediateChild = true; | |
// We are forced to use new RegExp("\\/\\/?|[^\\/]+","g") instead of /\/\/?|[^\/]+/g due to a bug in Google Chrome | |
var tknRegExp = new RegExp("\\/\\/?|[^\\/]+","g"); | |
var matches = tknRegExp.exec(xpath); | |
while (matches) | |
{ | |
var tkn = matches[0]; | |
if (tkn == "/" || tkn == "//") | |
immediateChild = (tkn == "/"); | |
else | |
{ | |
var isAttr = (tkn.charAt(0) == "@"); | |
var nodeName = isAttr ? tkn.substr(1) : tkn; | |
results = []; | |
for (var i = 0; i < ctx.length; i++) | |
{ | |
var cnode = ctx[i]; | |
var list = isAttr ? cnode.attributes : (immediateChild ? cnode.childNodes : cnode.getElementsByTagName(nodeName)); | |
for (var j = 0; j < list.length; j++) | |
{ | |
var n = list[j]; | |
if ((!isAttr && !immediateChild) || ((n.nodeType == 1 || n.nodeType == 2) && (nodeName == "*" || n.nodeName == nodeName))) | |
results.push(n); | |
} | |
} | |
ctx = results; | |
} | |
matches = tknRegExp.exec(xpath); | |
} | |
// enough parsing already, time to return the results | |
return results; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Chrome regexp issues fixed Trunk builds, it should land soon in regular Chrome versions; http://code.google.com/p/v8/issues/detail?id=704