Archive for June, 2007

SimpleXmlParser

For the recent Facebook platform integration project I was tasked with parsing various forms of Xml returned from the Facebook REST web service. REST or Representational State Transfer, is a term coined by Roy Fielding in his Ph.D. dissertation to describe an architecture style of networked systems. In the Facebook world, to get back some data from there servers you make a POST to a specific PHP page (http://api.facebook.com/restserver.php). The results are returned as an Xml document. In PHP there is a library called SimpleXmlParser which can be used to parses a XML file into a data structure. In the Microsoft.NET world we have the XmlReader class which provides forward-only, read-only access to a stream of XML data. In .Net the XmlReader is the most memory efficient approach to parsing an Xml structure. Unfortunately, those of us who choose to use this class know the level of frustration one will experience when asked to parse an Xml document which contain variable node names.

<?xml version="1.0" encoding="UTF-8"?>
<query>
  <session>2222222222</session>
  <users list="true">
    <user>
      <uid>10000001</uid>
      <name>Person 1</name>
    </user>
    <user>
      <uid>10000002</uid>
      <name>Person 2</name>
    </user>
  </users>
</query>

Examining the Xml arrangement we quickly see a pattern to how we might construct a data structure that would ease our ability to access specific keys within the information. The following is how I would like to parse the Xml data and access the list of users.

SimpleXmlResponse xml = SimpleXmlParser.Parse (fileContents, string.Empty)
SimpleXmlList list = xml["users"] as SimpleXmlList
xml  Count = 2  SimpleXmlResponse
  [0]  {[session, 2222222222]}  KeyValuePair
          Key  "session" string
          Value "2222222222"  object {string}
   [1]  {[users, SimpleXmlList]}  KeyValuePair
          Key  "users" string
          Value Count = 2  object {SimpleXmlList}
                 [0]  {[10000001, SimpleXmlItem]} KeyValuePair
                         Key "10000001" string
                         Value  Count = 2  SimpleXmlItem
                            [0] {[uid, 10000001]} KeyValuePair
                            [1] {[name, Person 1]}  KeyValuePair
                  [1] {[10000002, SimpleXmlItem]} KeyValuePair
                          Key "10000002" string
                          Value Count = 2 SimpleXmlItem
                            [0] {[uid, 10000002]} KeyValuePair
                            [1] {[name, Person 2]}  KeyValuePair

Here are a few things to note:

  • The three objects listed above (SimpleXmlResponse, SimpleXmlList, SimpleXmlItem) are nothing more than classes that inherit from System.Collections.Generic.Dictionary. There purpose is to ease readability and facilitate the casting of the result data.
  • Since SimpleXmlResponse has a value which might contain either a string or a SimpleXmlList, we store this value as an object. This data type will require us to cast the value to string for simple nodes.
  • Each child node contained within those elements flagged as lists (list attribute = true) will have more than one value key pair. As a result, we must either assume the first element is distinct and can be used as the key for the SimpleXmlList element, or we must explicitly identify which element is distinct.

Ubuntu saves the day!

UbuntuLast night I was tasked with extracting some data from an unbootable Windows XP desktop. Now I know there is hardware out there that would have allowed me to pull the hard drive and mount it on another PC, but my goal was to mount the computer from a bootable CD or USB drive. What I hoped would be a fairly easy thing, turned out to be so painful that I opted for a simpler approach.

Let me start off by apologizing to the Windows gods because my solution involved Open Source a copy of Ubuntu 7.04. You heard me correct….an open source Linux based operating system was used to save my XP data.

It was a really sad evening to realize that it took me longer to read the instruction on how I MIGHT be able to create a Vista boot disk, then it did to download the 650mb ISO, burn it on to a cd, boot to Linux, open up a NTFS partition and copy 4GB of data to my local NAS.

I love Microsoft.NET, but there is something special about a fully functional OS that fits on a single CD!