tags:

views:

164

answers:

1

Hi All,

Say we have the following XML:

<people>
 <person>
  <name>Jake</name>
  <skills>
   <skill>JavaScript</skill>
   <skill>HTML</skill>
   <skill>Flex</skill>
   <skill>CSS</skill>
  </skills>
 </person>
 <person>
   <name>John</name>
   <skills>
    <skill>C++</skill>
    <skill>Foxpro</skill>
   </skills>
 </person>
 <person>
  <name>Josh</name>
  <skills>
   <skill>JavaScript</skill>
   <skill>XML</skill>
   <skill>Flex</skill>
  </skills>
 </person> 
</people>

What I want to be able to do with E4X is find all person objects that match a list/array of skills I pass it. So, say I want find all people with either HTML or JavaScript skills.

I know I can do:

people.person.(descendants("skill").contains("HTML"))

or

people.person.(descendants("skill").contains("JavaScript"))

But I really want (/need) to do it one line (it's part of a XMLListCollection filter function in Flex).

Something like this would be ideal

people.person.(descendants("skill").contains("HTML","JavaScript"))

Although I tried variations on that theme and got nowhere. What would be great would be:

people.person.(descendants("skill").in("HTML", "JavaScript"))

or something like that.

Anybody know if what I'm doing is possible?

I really want to avoid adding my own loops in there.

Jake

+1  A: 

Didn't verify this with the compiler but this should work...

people.person.(descendants("skill").contains("HTML") || descendants("skill").contains("JavaScript"))

Here's another take —

If you want to check against an Array within the E4X statement, I guess you're out of luck. There is one possible workaround though, but it involves using a custom function inside the E4X, and simply moving the loop outside of your main code block. Kind of redundant, if you really want to avoid loops.

var skillsArray:Array = ["HTML", "JavaScript"];
var peopleWithSkills:XMLList = people.person.(matchSkills(descendants("skill"), skillsArray));

function matchSkills(xmlList:XMLList, skillsArray:Array):Boolean
{
 for each (var personSkill:XML in xmlList)
 {
  if (skillsArray.indexOf(personSkill.toString()) > -1)
  {
   return true;
  }
 }

 return false;
}

My best suggestion would be to really look into your heart and decide whether you need to avoid the loops, or if you just want to avoid them. ;)

Niko Nyman
Hi again Niko. You an E4X expert? The trouble is I want to pass an actual array object rather than two known values. Jake
Jake Howlett
Not an expert, but let's say I enjoy solving these problems. ;)
Niko Nyman
I guess you're right. I just want to avoid loops rather than need to avoid them. Thanks again for the solution. I'll have a play with the code and mark it as the answer if I get it to solve the problem.
Jake Howlett
Worked a treat Niko! and with no obvious degradation in performance. You can see it in use here http://www.codestore.net/apps/staffskills.nsfThe array of value comes from the selected items in the List on the left. Selecting more than one skill will show documents in the grid from any of the selected skills.Thanks again for your help.
Jake Howlett