Jump to content

Softxpath - Lightweight Cross Browser Javascript Library For Querying Xml Documents


Recommended Posts

Hello to veryone!I wrote this small JavaScript library for my job needs and want to share it with you.SoftXPath is small JavaScript library written for web developers who deals with XML parsing on client side. With the help of SoftXPath you will be able to query complex XML documents using powerful Xpath expressions. Now you can focus on building effective Xpath expressions instead of wasting time on compatibility issues. SoftXPath was tested on following browsers FireFox, Mozilla, Opera, Chrome, IE. SoftXPath has 3 methods for XML manipulation:1) load("myfile.xml") takes path to xml file as parameter2) loadXML("<root><item>Hello World</item></root>") takes xml string as parameter3) selectNodes("//item") takes xpath expression as parameterSoftXPath has 3 properties:1) LoadedXML checks if XML string was loaded without errors2) Loaded checks if XML document was loaded without errors3) DefaultNameSpace sets default XML namespaceSoftXPath code example:

<html>						<head>							Include SoftXPath library in your file							<script language="javascript" src="SoftXPath.js"></script>														<script language="javascript">								//Create new instance of SoftXPath object								var myXpathObj = new SoftXpath();								//Set default namespace								myXpathObj.DefaultNameSpace="";								//Call loadXML method with xml string as a parameter								myXpathObj.loadXML("<root><item>Hello</item></root>");								//Check LoadedXML property to see if XML string was loaded								//LoadedXML == true (xml string is valid)								if(myXpathObj.LoadedXML){									//Call selectNodes method with xpath expression as a parameter									//selectNodes method returns array of objects									re = myXpathObj.selectNodes("//item");									if(re.length==0){										alert("No records found!");									}									else{										//Loop over matched nodes										for(var i=0;i<re.length;i++){											//Print current node's text											alert(re[i].text);																																//Print current node's parent element name											//me points to current node itself											alert(re[i].me.parentNode.nodeName);																						//Print current node's name											alert(re[i].me.nodeName);										}									}									}								else{									alert("Loading xml string failed!");								}							</script>							</head>						<body>						</body>					</html>

SoftXpath source code:

function SoftXpath(){		function completeLoad(){			var l=false;			if(moz){				l = (xmlDom.documentElement==null?false:true);			}			else{				if(xmlDom.readyState=="4"){						l = (xmlDom.documentElement==null?false:true);					}				}			getLoaded.call(this,l);		}				function getLoaded(status){			o.Loaded=status;		}		var moz = (typeof document.implementation != 'undefined') && (typeof document.implementation.createDocument != 'undefined') && !document.implementation.hasFeature('LS', '3.0');		var xmlDomOpera = ((document.implementation) && (document.implementation.createDocument) && document.implementation.hasFeature('LS', '3.0')?true:false);		var xmlDom = (moz || xmlDomOpera?document.implementation.createDocument("", "doc", null):new ActiveXObject("MSXML2.DOMDocument.3.0"));				var o = this;		var ns="";		this.DefaultNameSpace=function(n){ns=n;};		if(xmlDomOpera){			ls = document.implementation.createLSParser(1,null);		}		this.load = function(filepath){			xmlDom.async = false;			if(moz){				xmlDom.addEventListener("load", completeLoad, false);			}			else{				xmlDom.onreadystatechange=completeLoad;			}			if(xmlDomOpera){				xmlDom = ls.parseURI(filepath);				o.Loaded = (xmlDom.documentElement.nodeName=="parsererror"?false:true);			}			else{				xmlDom.load(filepath);			}		}		this.loadXML = function(xmlstring){			if(moz  || xmlDomOpera){				var parser = new DOMParser();				xmlDom = parser.parseFromString(xmlstring, "text/xml");				o.LoadedXML=(xmlDom.documentElement.nodeName=="parsererror"?false:true);							}						else{				la = xmlDom.loadXML(xmlstring);				o.LoadedXML=(la==true?true:false);			}		}				this.selectNodes = function(xpath){			var resultsI = new Array();			if(moz){								var xpe = new XPathEvaluator();				var nsResolver = (new XPathEvaluator()).createNSResolver(xmlDom.ownerDocument == null ? xmlDom.documentElement : xmlDom.ownerDocument.documentElement);				var result = (xpath>""?xpe.evaluate(xpath, xmlDom, nsResolver, 0, null):"0");				if(result!="0"){					while (res = result.iterateNext()){						resultsI[resultsI.length]={nodeName:res.nodeName,text:res.textContent,me:res};					}				} 							}						else{								try{					try{						(document.implementation.hasFeature("SelectionLanguage","XPath"));						xmlDom.setProperty ("SelectionNamespaces", this.DefaultNameSpace);						xmlDom.setProperty ("SelectionLanguage", "XPath");					}					catch(e){};															nodes = xmlDom.selectNodes(xpath);					for(i=0;i<nodes.length;i++){						resultsI[i]={nodeName:nodes[i].nodeName,text:nodes[i].text,me:nodes[i]};					}				 }				 catch(e){};								}			return resultsI;		}} SoftXpath.prototype.DefaultNameSpace = function(n){this.ns = n;}

Please let me know if this script was useful.If you found bugs or want to make comments write to me at:webmasteratsoftxmldotcomThanks

Link to comment
Share on other sites

Interesting... reminds me of Sarissa, only you've also included a load() and loadXML() functions, which is nice and convinient.I think you should join the Sarissa team, and possibly contribute with some code... and/or learn from theirs. I for one would like to see your load() and loadXML() functions there. The default namespace thing sounds useful too, assuming it works out as well as advertised. BTW, I believe the first two properties should instead be the returned values of their respective functions. Coding will be much easier this way. Consider

var myXpathObj = new SoftXpath();if (myXpathObj.load("file.xml")) {//continue with XML processing}else {//error recovery here}


var myXpathObj = new SoftXpath();myXpathObj.load("file.xml");if (myXpathObj.Loaded) {//continue with XML processing}else {//error recovery here}

and don't get me started on what happens if I decide to use loadXML instead of load().BTW, Sarrisa once had a selectNodes() method... I never really understood why they removed it.

Link to comment
Share on other sites

  • 2 months later...

Your download link doesn't work in IE (8), and in Firefox, it pops up this annoying dialog that asks me to enter my name and email... why should I give these to you if I want to download a library? I understand that I should give them to you if I wanted to give a bug report or have a question, but for a download?!?Some more things on that demo page (less important):When you say which browsers have been tested, show the minimum version tested with a plus in front of it, or with explicit major versions listed. With IE being so different from one version to the next, this is especially important for it. Examples of good browser listings:

Firefox 2.0+, Opera 9.64+, Chrome 1.0+, IE7+
Firefox 2.0, Firefox 3.0, Opera 9.64, Opera 10, Chrome 1.0, IE7, IE8
Mozilla is basically the same as Firefox, so there's no need to test in that browser. They use the same engine. Besides, nobody really uses the Mozilla suite anymore. I'd suggest that you test in Safari 3.2 (the Windows version of course) as well. While its CSS engine is like Chrome, it has a different JavaScript engine, which means it may have problems.If your latest version indeed detects failure upon load, you should alert the user on load at the demo box. Right now, you allow them to enter anything, and only have an error upon the XPath expression, which is actually valid. In addition, if I enter an invalid XPath expression, I get "No records found" instead of an "Invalid expression" error (ideally with an error description, but if this is hard to do, so be it). That last one is probably something to consider for the library itself.You might want to put some styles around. At least a border and some margins around each example code (ideally something similar to the last box for user input).Your last link isn't exactly a call to action... "If you want to take a part in spreading word about SoftXpath library by start using it in your own applications or changing script for better performance, please go to SoftXpath - Open source project page ". OK, I went there... so what? That other page has nothing but ads. I was expecting a referral program of some kind, a list of some sites that have written about it, or... I don't know... something.And one more thing about the library... I'm confused about this default prefix thing. Normally, I'd expect a namespace assosiation based on a prefix/URI pair. For example, I'd expect:

Would make the XPath expression


in the XML

<root> <root xmlns="http://exmaple.com">TEST</root> </root>

return the inner element (<root xmlns="http://exmaple.com">TEST</root>), rathar than the outer one (the root element), which is what would happen without it.In addition, I'd expect a universal method for binding arbitrary prefixes (not just the default one) to arbitrary explicit URIs. For example, look at PHP's DOMXPath::registerNamespace() function. With such a function, I'd expect that

myXpathObj.registerNamespace(null, "http://example.com");

would be equivalent to the expected result from the above. If I specify

myXpathObj.registerNamespace("myPrefix", "http://example.com");

I'd expect that to get the same results with the same XML, I'd have to rewrite my XPath expression as:


Link to comment
Share on other sites

Hello again!I am really appreciate your important comments about library.First of all, I ask personal details when downloading because until now I don't know who uses the library.In this manner I can follow each one to see if everything is ok or they should have my help.Library itself detects failure on load and loadxml methods and user must handle error, xpath errors still not handled inside library, thanks for good advise.Demo page still do not have error detection functionality but it will come later.You suggestion to use registerNamespace method is excellent for setting custom namespaces without adding these names to xpath expressions.By the way SoftXpath works fine with Safari 3.2When I will have real feedbacks from users it will be easy to reopen open source project.Thanks

Link to comment
Share on other sites

  • 2 weeks later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Create New...