ReferenceError: Error #1065 re: E4X XML search

October 28th, 2009

I was trying to do a simple E4X search of my XML for an attribute named “type” and I came across this error.

ReferenceError: Error #1065: Variable @type is not defined.

After ramming my head against a wall for around 30 minutes I asked Duncan if he ever saw such a thing. After all, other searches on the same XML were working perfectly. After some thought he remembered having a similar issue. Turns out that every node you are searching needs to have that attribute, in my case every node needed the “type” attribute.

7 Comments »

  1. This kind of makes sense when you think about what the predicate search is actually doing: basically, iterating over the whole XMLList and running the filter in the scope of each item. In other words, an XMLList predicate filter like myXMLList.(@attr == "value") is the XMLList equivalent of the following for Arrays:

    
    function f(item:Object):Boolean
    {
        with (item)
            return @attr == "value";
    }
    myArray.filter(f);
    

    In this context, it makes a lot more sense why you would get that error: you’re trying to access the @attr property of an object that doesn’t have one. Using the attribute() function doesn’t throw an error. What might not be immediately clear is that the attribute() function that we’re calling is the instance method on the current XML object. Again, this is more clear in the Array.filter example:

    
    function f(item:Object):Boolean
    {
        with (item)
            return attribute("attr") == "value";
    }
    myArray.filter(f);
    

    Here, it becomes more obvious that 1) the attribute() function is being called on every iteration (i.e. once per each item in the Array) and 2) the method being called is the one defined on the item itself (because that’s the first/only thing in the scope chain to define the function). If one of the items in the Array did not define an attribute() method, then we would get an error on that iteration, just like we did when the item didn’t define an @attr property. So when we use the attribute() method, we are actually making one assumption (which I alluded to before): that each item in the collection defines that method.

    Comment by matthew — October 28, 2009 @ 4:24 pm

  2. you can throw it in a try/catch

    Comment by Derek — November 18, 2009 @ 9:23 am

  3. Cheers for this, you’ve just stopped my small headache turning into massive one. I understand what matthew said, but i’d still think that if you were using the filtering to find a node at a certain level, with an attribute of a certain value, then internally it would deal with the fact that the node it’s querying does not contain an attribute of that name. As you’re obviously not looking for that node.

    Surely it would make more sense to return either the result or nothing at all, rather than throwing an error?

    I don’t think you can throw it in a try/catch as suggested either, as once the error is thrown, the loop if broken.

    Comment by jamesr — November 19, 2009 @ 5:30 am

  4. Actually, in response to mathews comment, if you run this code using describeType, even though all the nodes in the children don’t contain an attribute called ‘name’, it still returns the values for those that do, without throwing any errors.

    var xml : XML = describeType( myClass ); var list : XMLList = xml.children()@name;

    trace( list ); trace( xml..@name );

    I realise that this isn’t using filtering with expressions, but i’d think it would go through a fairly similar process.

    Comment by jamesr — November 19, 2009 @ 5:47 am

  5. Glad to have helped!

    Comment by Ryan — November 19, 2009 @ 7:06 am

  6. @jameser I think the reason that it can’t “return either the result or nothing at all,” is a result of the implicit scope. With node selection (like the example you gave), it’s a simple lookup with an explicit scope—in your example, the scope is xml.children(). When using a filter to check an attribute value, however, the scope is implicit. For example, consider myXMLList.(@attr == "value"). Flash has to resolve the variable @attr by climbing the scope chain. But it’s not defined on the XMLList (or anything else in the scope chain) so you get an error. Still, this seems like desirable behavior in light of this example:

    
    var myVar:Number = 5;
    trace(myXMLList.(@attr == myVar));
    

    Clearly, the expectation is that the myVar in the filter is the variable defined above, and that Flash will find the variable in the scope chain after not finding it in the XMLList. The same behavior must apply to @attr, but since that doesn’t exist anywhere in the scope chain, you’ll get the error Ryan describes.

    Comment by matthew — December 29, 2009 @ 8:55 am

  7. [...] See this. [...]

    Pingback by Searching XML on attribute results in runtime error: Variable @ is not defined. « Development scratchbook — January 30, 2010 @ 7:34 am

RSS feed for comments on this post. TrackBack URI

Leave a comment