Re: XPath and find/findAll methods

On Wednesday, November 23, 2011, Robin Berjon <robin@berjon.com> wrote:
> On Nov 23, 2011, at 01:08 , Jonas Sicking wrote:
>> I really don't think that selectors can ever compete with the
>> expressiveness of XPath. Consider the following expression:
>>
>> //div[count(.//span) > 6][count(.//span[@data-foo = ../@data-bar]) mod 2
= 1]
>>
>> This expression finds all <div> elements which has at least 6 <span>
>> descendants and where an odd number of those <span> elements have a
>> "data-foo" attribute equal to its parents "data-bar" attribute. It is
>> obviously trivial to add arbitrary additional complexity to this
>> expression.
>>
>> Trying to do the same thing in Selectors will just result in a
>> incomprehensible mess.
>
> That's exactly what worries me with this plan.
>
>> At the same time, XPath can't ever compete in expressiveness to
>> Javascript. Finding all <div> elements with a "data-foo" attribute
>> that contains a prime number is not possible in XPath but trivial in
>> javascript.
>
> Well, for values of trivial that could be quite slow :) But yes.
>
>> I'm not convinced that it's worth investing in XPath. At least not
>> beyond the low-hanging fruit of making most of the arguments to
>> .evaluate optional. But I think trying to make selectors compete in
>> expressiveness with XPath is a loosing battle.
>
> I don't think that anyone has requested much beyond making the existing
API actually usable (either by fixing it directly or by adding a new,
simple one). That's all that's needed IMHO and it doesn't strike me as much.
>
> I would be thinking about something along the lines of (untested, off the
top of my head):
>
> Node.prototype.queryXPath = function (xpath, ns) {
>    ns = ns || {};
>    var snap = this.ownerDocument
>                   .evaluate(xpath,
>                             this,
>                             function (p) { return ns[p] || null; },
>                             XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
>                             null);
>    var ret = [];
>    for (var i = 0; i < snap.snapshotLength; i++)
ret.push(snap.snapshotItem(i));
>    return ret;
> };
>
> or, if people prefer, even just:
>
> Node.prototype.queryXPath = function (xpath) {
>    var snap = this.ownerDocument
>                   .evaluate(xpath,
>                             this,
>                             function () { return "
http://www.w3.org/1999/xhtml"; },
>                             XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
>                             null);
>    var ret = [];
>    for (var i = 0; i < snap.snapshotLength; i++)
ret.push(snap.snapshotItem(i));
>    return ret;
> };
>
> Which hardly strikes me as a terribly complex addition.

I like this approach. Though I would make the type ANY and return whatever
type the expression produced.

/ Jonas

Received on Wednesday, 23 November 2011 16:45:53 UTC