0

I have some XML in the below format.

 <user uid="0001">
    <FirstName>John</FirstName>
    <LastName>Smith</LastName>
    <ImagePath>images/0001.jpg</ImagePath>
    <flightno>GS1234</flightno>
</user>
<user uid="0002">
    <FirstName>Luke</FirstName>
    <LastName>Dixon</LastName>
    <ImagePath>images/0002.jpg</ImagePath>
    <flightno>TD1234</flightno>
</user>
<user uid="0003">
    <FirstName>Paul</FirstName>
    <LastName>Kerr</LastName>
    <ImagePath>images/0003.jpg</ImagePath>
    <flightno>GS1234</flightno>
</user>

This is a small sample, there are a couple 100 of these.

I have used E4x filtering to filter down another set of XML data that produces an as3 array. The array contains some flight numbers (eg : [GS1234,PB7367,TD1234].

I'm wondering how I can filter my XML (as shown above) to only show the users whose 'flightno' EXISTS in the AS3 array.

I'm guessing its some sort of E4X query but I can't seem to get it right!

Thanks!

1 Answer 1

1
// Don't mind me using this trick with inline XML, it's not the point.
// It's here just to make it possible to copy and paste code 
// with multiline XML sample.The actual solution is a one-liner below.
var usersXML:XML = new XML(<x><![CDATA[
<data>
<user uid="0001">
    <FirstName>John</FirstName>
    <LastName>Smith</LastName>
    <ImagePath>images/0001.jpg</ImagePath>
    <flightno>GS1234567</flightno>
</user>
<user uid="0002">
    <FirstName>Luke</FirstName>
    <LastName>Dixon</LastName>
    <ImagePath>images/0002.jpg</ImagePath>
    <flightno>TD1234</flightno>
</user>
<user uid="0003">
    <FirstName>Paul</FirstName>
    <LastName>Kerr</LastName>
    <ImagePath>images/0003.jpg</ImagePath>
    <flightno>GS1234</flightno>
</user>
</data>
]]></x>.toString());

// once again, the way I create sample departingXML 
// is not important, it's just for copying and pasting into IDE.
var departingXML:XML = new XML(<x><![CDATA[
<flights>
    <flight>
        <number>GS1234</number>
        <date>10/11/2015</date>
        <time>1440</time>
    </flight>
    <flight>
        <number>TD1234</number>
        <date>10/11/2015</date>
        <time>1450</time>
    </flight>
</flights>
]]></x>.toString());


// 1. create filter array
var flightNoArray:Array = [];
departingXML.flight.number.(flightNoArray.push(toString()));

trace(flightNoArray); // GS1234,TD1234
trace(typeof(flightNoArray[0])); // string

// 2. filter users:
var list:XMLList = usersXML.user.(flightNoArray.indexOf(flightno.toString()) >= 0);

trace(list); // traces users 0002 and 0003

I wouldn't call it efficient or at least readable though.

// Note: this line is somewhat queer and I don't like it,

departingXML.flight.number.(flightNoArray.push(toString()));

// but this is the only way I can now think of to get and array 
// of strings from an XMLList nodes without a loop.
// I would advise to use a readable and simple loop instead.
  • usersXML.user -- this gets you an XMLList with all nodes named "user"
  • usersXML.user.(some condition) -- this filters the XMLList of user nodes given a condition
  • flightNoArray.indexOf(flightno.toString()) >= 0 -- and this is a filter condition
  • flightno.toString() -- gets you a string inside flightno child
  • REFERENCE: Traversing XML structures.
  • Explanation of the search trick in the note above.

UPDATE: it turned out in comments that it was also the way the filter array was populated that was causing trouble. The code below demonstrates some more E4X.

This is how the filter list was created and what was actually happening:

// once again, the way I create sample departingXML 
// is just for the sake of copying and pasting, it's not related to solution.
var departingXML:XML = new XML(<x><![CDATA[
<flights>
    <flight>
        <number>GS1234</number>
        <date>10/11/2015</date>
        <time>1440</time>
    </flight>
    <flight>
        <number>TD1234</number>
        <date>10/11/2015</date>
        <time>1450</time>
    </flight>
</flights>
]]></x>.toString());

// the way it was done before
var flightNoArray: Array = []; 
for each(var num: XML in departingXML.flight) { 
    flightNoArray.push(num.number);

    // WARNING! num.number is an XMLList! It s NOT a string.
    // Addressing nodes by name ALWAYS gets you an XMLList, 
    // even if there's only one node with that name
    // Hence, `flightNoArray.indexOf("string")` could not possibly work, 
    // as there are lists inside of the array, not strings.


    // We can check if this is a fact:
    trace(flash.utils.getQualifiedClassName(flightNoArray[flightNoArray.length-1])); 
    // (traces XMLList)

    // Or this way (note toXMLString() method)
    trace(flightNoArray[flightNoArray.length-1].toXMLString()); 
    // (traces <number>GS1234</number>)
} 

trace(flightNoArray); 

trace(flightNoArray); traces GS1234,TD1234 because this is the way toString() method works for xml nodes -- it gets you text, that is inside. This is why there is a special method toXMLString(), that gets you a string representation of a node.

Sign up to request clarification or add additional context in comments.

24 Comments

Doesn't seem to be working that, i just get "unable to parse XML"
I guess it's just that flash pro cs6 (I'm using) is capable of parsing inline xml with multiple lines, and previous versions of flash IDE are not. Anyway, the gist is in the line below // solution:.
I'm using cc mate, ill have a play around. Thanks for your help.
@GazSmith Ok, I've updated the answer. Now it should be Ok to just copy and paste the thing.
Damn i was hoping i removed the link before you saw it xD
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.