Page view counter

Silverlight Tips of the Day - Blog by Mike Snow

Game Programming with Silverlight

Silverlight Tip of the Day #93 – Reading XML with Silverlight

XML (Extensible Markup Language) is a great format for saving structured data in. In this Tip I will be showing you how to read and process XML files from Silverlight using the XmlReader object.

Let’s say, for example, you want to store a tree structure of images grouping by them category. Your XML could look like this:

<?xml version="1.0" encoding="utf-8" ?>
<ImageTree>
  <Area name="grass">
    <Image name="Normal Grass">grass1.png</Image>
    <Image name="Dry Grass">grass2.png</Image>
    <Image name="Mixed Grass">grass3.png</Image>
    <Image name="Long Grass">grass4.png</Image>
  </Area>
  <Area name="tile">
    <Image name="Brick">brick.png</Image>
    <Image name="White Stone">stone.png</Image>
    <Image name="Cracked Stone">crackedstone.png</Image>
    <Image name="Black Brick">brick2.png</Image>
  </Area>
</ImageTree>

Few things to note about the XML above:

  1. XML can only have one root node which in my case I have called <ImageTree>
  2. <Area> and <Image> tags are called Elements
  3. “name” is an attribute and its content is the value for the attribute.

Now, on to the code below:

  1. To open an XML file I will be using the WebClient object. I have placed a file called MapImages.xml in my ClientBin folder that contains the data I will read. When the file read operation is complete (remember everything is asynchronous) the callback function client_DownloadStringCompleted will be called.
  2. When reading the data I check to see what the NodeType is. I only care about nodes that are of type Element or Text and I ignore stuff like comments, whitespace, etc.
  3. Once you read an Element you can get the attribute (such as name=”Brick”) for the Element by calling reader.MoveToFirstAttribute().
  4. The file name for each image is stored in the Tag property of each tree view item.
public Page()
{
    InitializeComponent();           
 
    Uri url = new Uri("MapImages.xml", UriKind.Relative);
    WebClient client = new WebClient();
    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
    client.DownloadStringAsync(url);
}
 
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    if (e.Error == null)
    {
        TreeViewItem areaItem = null;
        TreeView tv = new TreeView();
        TreeViewItem rootItem = new TreeViewItem();
        rootItem.Header = "Images";
        tv.Items.Add(rootItem);
 
 
        StringReader stream = new StringReader(e.Result);
        XmlReader reader = XmlReader.Create(stream);
        string imageName = String.Empty;
        string areaName = String.Empty;
        string fileName = String.Empty;
 
        while (reader.Read())
        {
            if (reader.NodeType == XmlNodeType.Element)
            {
                if (reader.Name == "Area")
                {
                    if (true == reader.MoveToFirstAttribute())
                    {
                        areaName = reader.Value;
                        areaItem = new TreeViewItem();
                        areaItem.Header = areaName;
                        rootItem.Items.Add(areaItem);
                    }
                }
                else if (reader.Name == "Image")
                {
                    if (true == reader.MoveToFirstAttribute())
                    {
                         imageName = reader.Value;
                    }
                }                        
            }
            else if (reader.NodeType == XmlNodeType.Text)
            {
                fileName = reader.Value;
                TreeViewItem imageItem = new TreeViewItem();
                imageItem.Header = imageName;
                imageItem.Tag = fileName;
                if (null != areaItem)
                    areaItem.Items.Add(imageItem);
            }
        }
        MainCanvas.Children.Add(tv); // Add the treeview to our main canvas.
    }
}

The result of the code above is a tree view with all the items added as seen in the image below.

image

On a final note, this code is hard wired to read a specifically formatted and error free file. You will want to add error checking in case the file is invalid in anyway.

Thank you,
--Mike Snow

 Subscribe in a reader

Comments

Silverlight Tips of the Day - Blog by Mike Snow said:

The purpose of this post is to create an outline summary all the blogs from my Silverlight Tips of the

# February 10, 2009 6:22 PM

Visual Web Developer Team Blog said:

Most Recent Posts: Tip #93 - Reading XML with Silverlight Tip #92 - How to Load Images from a Stream

# February 10, 2009 6:25 PM

Microsoft Weblogs said:

XML (Extensible Markup Language) is a great format for saving structured data in. In this Tip I will

# February 10, 2009 7:21 PM

Silverlight Tip of the Day #93 ??? bReading/b XML with Silverlight b…/b | tutoringny.com said:

Pingback from  Silverlight Tip of the Day #93 ??? bReading/b XML with Silverlight b&#8230;/b | tutoringny.com

# February 11, 2009 2:35 AM

mbaker3 said:

I'm surprised to see an XML tutorial for Silverlight that doesn't implement LINQ.  Any reason for not using it?

# February 11, 2009 9:06 AM

Dew Drop - February 11, 2009 | Alvin Ashcraft's Morning Dew said:

Pingback from  Dew Drop - February 11, 2009 | Alvin Ashcraft's Morning Dew

# February 11, 2009 9:49 AM

mike.snow said:

mbaker3- I wanted to demonstrated XmlReader. I will be doing a tutorial on LINQ next. Thanks.

# February 11, 2009 12:11 PM

Silverlight Tips of the Day - Blog by Mike Snow said:

In Tip of the Day #93 I showed you how to read XML via XmlReader . However, a better and simpler approach

# February 11, 2009 2:53 PM

Community Blogs said:

In this issue: Rob Houweling, Jonathan van de Veen, Peter Bromberg, Jeff Weber, Mike Snow, Jordan Knight

# February 11, 2009 11:56 PM

Programming with Silverlight, WPF & .NET » XML mit Silverlight lesen said:

Pingback from  Programming with Silverlight, WPF &amp; .NET &raquo; XML mit Silverlight lesen

# February 16, 2009 5:54 AM

SharpGIS said:

The problem with using the reader is that you require your tags to be in a specific order. However that's not how XML works.

You could use the XML-to-LINQ, but that adds 50k to your XAP (why isn't it that these standard Dlls are part of the install grrrr?)

# April 17, 2009 1:34 PM

NewsPeeps said:

Thank you for submitting this cool story - Trackback from NewsPeeps

# August 8, 2009 6:36 PM

HSCoder said:

I've implemented the code exactly as above.  It compiles correctly and runs.  The problem is that the callback function never gets called.  I've traced through in the debugger and watched the cl.DownloadStringAsync(uri) statement get executed.  Immediately after that I am checking the cl.isBusy and it shows false (async download not still in progress).  However, the callback function is never executed and there are no errors thrown at all.  Anybody have any ideas on what I might be doing wrong?  I am new to Silverlight, so I may be making an obvious mistake...

Here is my code:

Here's where I set everything up:

               // Open doc using WebClient (must use this for Silverlight)

               WebClient cl = new WebClient();

               cl.DownloadStringCompleted += new DownloadStringCompletedEventHandler(cl_DownloadStringCompleted);

               Uri uri =

                   new Uri(@"C:\Users\Aly\Desktop\Prototype3\Prototype3UI\Prototype3UI\ServerMonitorStatus.xml", UriKind.Absolute);

               cl.DownloadStringAsync(uri);

               bool status = true;

               status = cl.IsBusy;

               while (cl.IsBusy)

               {

                   Thread.Sleep(1000);

                   status = cl.IsBusy;

               }

               Console.WriteLine("xmlData: " + xmlData);

and here is my callback function:

       void cl_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)

       {

           xmlData = e.Result;

           Console.WriteLine("xmlData: " + xmlData);

       }

Thanks for any help you can give me!

# August 9, 2009 2:40 PM

brucewpalmer said:

Am having the same problem as HSCODER. Any suggestions?

# November 18, 2009 2:16 PM

mike.snow said:

Did you include the XML in your project? Make it relative path. You can't open files on the client that arne't included in the project.

Or Try a absolute path by putting the file on a server and accessing it via http://...

# November 18, 2009 2:23 PM

brucewpalmer said:

I loaded the file up to my ftp site and still couldn't get a response on the async read. Does it have to be http?

# November 18, 2009 5:45 PM

mike.snow said:

Yes, like www.mysite.com/MyFile.xml

Are you able to include the XML file in your SL project?

# November 18, 2009 5:47 PM

brucewpalmer said:

I'm able to add a local version of the file to my project. But I really need it external so the config can be updated by a system manager without rebuilding. Got http to run but says it can't set credentials to access my site. I used Webclient.Credentials = new NetWorkCredentials(user, passwd) but got an exception that the property is not allowed.

# November 18, 2009 6:14 PM

mike.snow said:

Can you access the XML file via IE?

# November 18, 2009 7:13 PM