开发者

E4X filtering in Spidermonkey

I'm using E4X in SpiderMonkey, and the majority of the language seems pretty solid, but I can't get filtering to work:

var xml = <root>
    <person id="dave">Dave</person>
    <person id="ian">Ian</person>
    <person>John</person>
</root>

trace( xml.*.(name() == 'person') );
trace( xml.*.(attribute('@id')) );

Expected:

<person id="dave">Dave</person>
<person id="ian">Ian</person>
<person>John</person>

<pers开发者_StackOverflow社区on id="dave">Dave</person>
<person id="ian">Ian</person>

Results:

ReferenceError: name is not defined
ReferenceError: attribute is not defined

I can't even get hasOwnProperty() to work either:

xml.*.(trace( hasOwnProperty('@id') ));

false
false
false

Specifically, I'm using JSFL in Flash, which uses the SpiderMonkey engine.

From my basic knowledge of E4X so far, this is pretty unexpected / buggy, right? As I can get these expressions to work just fine in ActionScript / FlashPlayer!

Thanks, Dave


OK, so I've tried a bunch of things, and I still can't get the original syntax to work, so the best I can come with (it's a pretty good workaround, considering) is to extend the XMLList prototype and add a filter() method:

XMLList.prototype.function::filter = function(callback)
{
    var output  = new XMLList();
    var length  = input.length();
    for(var i = 0; i < length; i++)
    {
        if(callback(input[i], i, input))
        {
            output += input[i];
        }
    }
    return output;
}

So with the following XML...

var xml = <root>
    <person id="dave">Dave</person>
    <person id="ian">Ian</person>
    <person>John</person>
    <group>
        <person id="jane">Jane</person>
        <person>Sarah</person>
    </group>
</root>

It's pretty intuitive to grab and filter nodes:

// old
var nodes = xml..person.( hasOwnProperty('@id') );

// new
var nodes = xml..person.filter( function(node){ return node.hasOwnProperty('@id'); } );

<person id="dave">Dave</person>
<person id="ian">Ian</person>
<person id="jane">Jane</person>

If anyone can correct me on this, I'd be super-glad, if not, I'd just like to know why my original filtering just didn't work.

Dave


Just a small correction for the answer posted here, regarding the filter function:

XMLList.prototype.function::filter = function(callback)
{
    var output  = new XMLList();
    var input = this;
    var length  = input.length();
    for(var i = 0; i < length; i++) {
        //console.println(i + ", " + input[i]);
        if(callback(input[i], i, input))
        {
            //console.println("Yes");
            output += input[i];
        }
    }
    //console.println('output = ' + output);
    return output;
}

The original solution is the best and that was exactly what I was looking for!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜