Comparing XML nodes of the same name with E4X

english mobile

I recently found a situation that the Flex E4X documentation didn't cover, and I couldn't find an example for ActionScript 3 or JavaScript that covered it. Essentially, I had XML in the data property of an itemRenderer that looked something like this:

<question id="1>
<selected>
1
</selected>
<selected>
5
</selected>

</question>

Essentially, my itemRenderer has five buttons (A-E), any or all of which can be selected. If the user clicks one of the buttons and it is already selected, it should be deselected. Or, in other words, if there is already an element in the data XML's "selected" collection with the same value as what the user clicked (assuming A=1 and E=5), then that element should be deleted.

I had a challenge, though, in that I didn't want to use a for loop. I was using XML, and E4X should be able to handle this easily. The problem I had was that every E4X example I found that referenced the contents of the nodes of an XML node presumed that there would only be one of each node of the same node. So if my XML structure had been

<question id="1>
<selected>
1
</selected>

</question>

then life would have been easy. I could have used data.(selected==userSelection) and away I'd go. But the problem when you have multiple nodes named "selected" is that data.selected returns an XMLList that contains all of the nodes. Hence, it cannot be equal to any single number, even though when there is only one node it works fine.

So, after much research, I came up with something like this:

myXMLNode:XML="<selected>"+userSelection+"</selected>";
if (data.selected.contains(myXMLNode){
//loop through and delete any nodes with that value
} else {
//add a node of that value
}

I wasn't really happy with this, and I posted to the Flex Coders mailing list. Tracy Spratt suggested that I use the text() method of the XML object, so I wound up with something like this in my final logic:

if (data.selected.(text()==userSelection).length()==0){
//add the selected node to the data object
data.prependChild(myXMLNode);
} else {
//remove the selected node from the data object
for (i=data.selected.length()-1; i>=0; i--){
if (data.selected[i] == userSelection){
delete data.selected[i];
}

I hope this will help someone else solve this problem without having to waste as much time as I spent on this!

6 comments:

Unknown said...

i am stuck with the same problem.
user
permission READ /permission
permission WRITE /permission
/user

dat.b.length gives me 2 when i have two b's.this is fine.
but when i only have READ..i get length as 4 (length of read string)..

i converted data.b as xml which just gives me null and so i am not able to access text() method as in ur application..

any solution please

thanks

Amy B said...

It looks like you might have tried to post your XML to the blog, but your special characters failed.

If your XML looks like this

dat:XML = <user>
  <permission>READ</permission>
  <permission>WRITE</permission>
</user>

readNode:XML = dat.permission.(text()=='READ');

delete readNode;

I was doing other things than just deleting the node, which is why I did the loop, but you can just delete it directly.

I'm not sure what the answer is for length() returning the length of the string rather than the length of the XMLList, and unfortunately I don't have time to test it today. I'll try to investigate and see what I can come up with when I get time.

Stiggler said...

Thanks for the write-up. This is exactly what I've been scratching my head over this afternoon.

To add to your example, why not use the same methodology for removing the nodes as well, rather than looping through the entire list?

var selectedList:XMLList = data.selected.(text()==userSelection);

if(selectedList.length()==0){
//add the selected node to the data object
data.prependChild(myXMLNode);
} else {
//remove the selected node from the data object
for (i=selectedList.length()-1; i>=0; i--){
delete selectedList[i];
}

Amy B said...

I think I was doing other things as well that didn't make it into this post, but I don't see any reason you couldn't do it that way :-).

Steven Rieger said...

Hi Amy,

I'm hoping you can help me here. I have a similar problem and I can't wrap my head around it. I am trying to use the advanced data grid with my xml to group the data. I can not for the life of me figure this out can you help?

I have a demo with view source enabled here if you can.
http://estar.lmsnet.com/lmsdev/testgrouping.html

Thanks!!!!

krishna said...

Hi

I have xml like this


1
2
3
...
...
...
n

I want to delete last node without checking the length of the xml...
is it possible ?

and i want to add a node in the middle...

Please help me....