ReferenceError: Error #1065 re: E4X XML search

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.

comments

  • http://exanimo.com matthew

    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.

  • Derek

    you can throw it in a try/catch

  • jamesr

    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.

  • jamesr

    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.

  • Ryan

    Glad to have helped!

  • http://exanimo.com matthew

    @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.

  • http://tjoadesign.nl/blog/?p=113 Searching XML on attribute results in runtime error: Variable @ is not defined. « Development scratchbook

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