Cross-Browser XPath

Although the popularization of JSON in recent years has decreased the use of XML as the mode of data delivery for new web applications, many services and developers still rely upon the passé format. When writing code in any case–short of optimization–it is best to reduce complexity and increase readability.  XPath enables a programmer to concisely select nodes from large and complex XML documents without the mayhem of endless nested loops and if-statements.  If you are unfamiliar with these concepts, W3Schools has nice introductory-level tutorials on XPath and XSLT.

Anyways, browser implementation of this feature has not always been consistent.  Not surprisingly, Microsoft’s implementation of ECMA-262–dubbed JScript–exposes some extra methods in the XMLDocument class that make the process easier, namely selectNodes() and selectSingleNode(). These methods are not found in the Javascript engines of other browsers.  A coder who goes by the alias km0ti0n released the following bit of code a short while ago; unfortunately, his website no longer appears to be active.

// mozXPath [http://km0ti0n.blunted.co.uk/mozxpath/] km0ti0n@gmail.com
// Code licensed under Creative Commons Attribution-ShareAlike License
// http://creativecommons.org/licenses/by-sa/2.5/
if( document.implementation.hasFeature("XPath", "3.0") ){
	if( typeof XMLDocument == "undefined" ){ XMLDocument = Document; }
  XMLDocument.prototype.selectNodes = function(cXPathString, xNode){
    if( !xNode ) { xNode = this; }
		var oNSResolver = this.createNSResolver(this.documentElement)
		var aItems = this.evaluate(cXPathString, xNode, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
		var aResult = [];
		for( var i = 0; i < aItems.snapshotLength; i++){aResult[i] =  aItems.snapshotItem(i);	}
		return aResult;
	}
	XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode){
		if( !xNode ) { xNode = this; }
		var xItems = this.selectNodes(cXPathString, xNode);
		if( xItems.length > 0 ){return xItems[0];	}
		else{return null;	}
	}
	Element.prototype.selectNodes = function(cXPathString){
		if(this.ownerDocument.selectNodes){	return this.ownerDocument.selectNodes(cXPathString, this);}
		else{throw "For XML Elements Only";}
	}
	Element.prototype.selectSingleNode = function(cXPathString){
		if(this.ownerDocument.selectSingleNode){return this.ownerDocument.selectSingleNode(cXPathString, this);	}
		else{throw "For XML Elements Only";}
	}
}

This snippet of code will add the equivalent methods to other browsers including Firefox, Chrome and Opera.  Here’s a quick example of using each of these functions, but first a sample document:

<result>
	<item>
		<fieldOne>hello</fieldOne>
		<fieldTwo>world</fieldTwo>
	</item>
	<item>
		<fieldOne>foo</fieldOne>
		<fieldTwo>bar</fieldTwo>
	</item>
</result>

and then some code, assuming that doc is a valid XMLDocument containing the data above:

var items = doc.selectNodes('/result/item');

for (var item in items) {
	var fieldOne = item.selectSingleNode('fieldOne');
	var fieldTwo = item.selectSingleNode('fieldTwo');

	alert(fieldOne + ' ' + fieldTwo);
}

This would first alert hello world and subsequently, foo bar.  In essence, this little hack allows your XML parsing code to become more graceful, more readable and more compatible.

This entry was posted in Javascript and tagged , , . Bookmark the permalink.
  • Delicious
  • Facebook
  • Reddit
  • StumbleUpon
  • Twitter
  • RSS Feed
  • Google
  • Digg

One Response to Cross-Browser XPath

  1. Pingback: Cross-Browser XPath | Richard Pianka « xpath

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>