Skip to content

Instantly share code, notes, and snippets.

@3rd-Eden
Created June 1, 2010 10:24
Show Gist options
  • Save 3rd-Eden/420783 to your computer and use it in GitHub Desktop.
Save 3rd-Eden/420783 to your computer and use it in GitHub Desktop.
SpryEvaluateXPath
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;
};
@3rd-Eden
Copy link
Author

3rd-Eden commented Aug 6, 2010

Chrome regexp issues fixed Trunk builds, it should land soon in regular Chrome versions; http://code.google.com/p/v8/issues/detail?id=704

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment