Friday, February 4, 2005


XPath is useful. To some extent, it is addressing a problem (XML is
annoying to navigate) that might not be there if XML wasn't
gratuitously over-applied to technical problems, but it does what it does reasonably nicely and clearly. If XML is going to be used as a data description language, XPath is useful to have.

Unfortunately, the XPath API, as defined in href="">DOM Level
3 and as implemented in Mozilla, is not designed for anyone who
actually wants to use it. It's perfectly fine if you want to
look at it and admire it, but if you actually want ot use it, it's
rather annoying. I understand there can be the attitude in API design
that "utility functions" that duplicate existing (more complete, but
more complex) API functions need not be included. Get over it, they
should be included. One or two well conceived utility functions can
dramatically improve usability. Java got a lot better when they added
String.split() rather than having to wade through the irritation of
StringTokenizer. For that matter, an overabundance of utility
functions is, at worst, a documentation issue.

With XPath, you're using it to fetch a node or nodes of an XML
document. You can also use it to count nodes, get strings, etc, but
when it comes down to it, you're identifying nodes in an XML
document. So, if I want to get say, the first image element with a
class of "big" that is nested underneath a div somewhere in an HTML
document, I use the xpath expression:
//div//img[@class="big"] Unfortunately, the API requires that
I call document.evaluate with 5 parameters, two of which are null and
one of which is an annoying long constant name, something like:
Ok, that's a
bit annoying, but it's not so bad, right? I get an array back and I
just take the first element. Wrong. I get an "XPathResult"
back which has its own little iterator interface. So, instead I find
myself using this utility function:

mkgray.xpath = function xpath(p, context) {
var arr = new Array();
var xpr = document.evaluate(p,context,null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for(i=0;item=xpr.snapshotItem(i);i++){ arr.push(item); }
return arr;

I'm hoping there's something in the API I'm simply overlooking that someone will point out to me, but in the meantime, I'll continue hoping for utility methods.

No comments:

Post a Comment