mike chambers | about

E4X : Retrieving a sibling of a node

Thursday, August 17, 2006

One of the advantages of XML is that you can easily represent related information with a parent / child relationship. This makes it easy to parse, and understand. However, some XML formats (such as Apple’s plist format), represent relationships via proximity on the same level.

For example, one way to represent name / value pairs in XML could be:

<Artist>Interpol</Artist>

However, the plist format does this with key / value structure, so the above would be represented in XML as:

<key>Artist</key><string>Interpol</string>

The relationship between key / value is dependent on proximity, and not hierarchy as in the first example. I won’t go into why Apple did this (I don’t know) or whether it is good or bad, but it does present some difficulties in parsing.

In order to reliably parse this, you must first retrieve the key node with the appropriate value, and then get the next node, which will contain the value for the preceding key. Thus, you must be able to retrieve the key node’s next sibling, in relation to its parent.

Here is an example:

package {
	import flash.display.Sprite;

	public class XMLTest extends Sprite
	{
		public function XMLTest()
		{
			var xml:XML = 
				<xml>
					<songs>
						<song>
							<key>Artist</key><string>Interpol</string>
							<key>Track Number</key><int>7</int>
						</song>
						<song>
							<key>Artist</key><string>Bloc Party</string>
							<key>Track Number</key><int>3</int>
						</song>						
					</songs>
				</xml>
				
			var temp:XML;
			var artistName:String;	
			
			//loop through all of the songs
			for each (var song:XML in xml.songs.song)
			{
				//get the node for key in the first song that has the Artist value
				temp = song.key.(text() == "Artist")[0];
				
				//get the next node (i.e. the key nodes next sibling). and save it as a Stirng
				artistName = String(temp.parent().children()[temp.childIndex() + 1]);
				
				trace(artistName);
			}	
		}
	}
}

The important part is this line:

temp.parent().children()[temp.childIndex() + 1]</pre>

Basically, this gets the temp node’s next sibling. To get the previous sibling, just subtract 1 like so:

temp.parent().children()[temp.childIndex() - 1]

Anyways, took me some trial and error to figure out. I added some APIs to the XMLUtil class in corelib, that encapsulate this. They are already included in source, and will be compiled into the SWC at the next release. You can view the class and APIs here. You can find more information on the corelib API here.

twitter github flickr behance