Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / XSLT

XLINQ to WoW Realm Status

3.83/5 (9 votes)
19 Sep 2008CPOL8 min read 1   80  
This article will explain and show how to use XLINQ (LINQ to XML) to get WoW Realm status.

Introduction

A lot of people are playing World of Warcraft these days (9,000,000+, to be exact). So I thought it would be appropriate to display to the public how to bring together the two passions of many people's lives. That being gaming and programming.

Background

With XML being an open data format that many people can use on any platform, it's no wonder big companies are relying on it to not only store, but display data too. Some companies/individuals are using it to save application settings, blog posts, and many other things. One example of this would be Blizzard using it to display WoW Realm status.. This article will show how to take advantage of this open data format and .NET 3.5's new XML to LINQ framework for use in any application, either web or a deployable executable.

Please note that at the time this article was written, .NET 3.5 was in Beta 2 as well as Visual Studio 2008, and World of Warcraft had 9,000,000+ subscribers.

Using the Code

Understanding the Story Behind the Data

If we're going to be querying against anything, we need data. So to start off, we'll take a look at Blizzard's WoW Realm Status XML page.

If you're using a modern web browser, you won't see any XML, you should see a moderately formatted page with the status, type, and popularity of each realm. Now, if you're wondering why you don't see any XML, that's a good question. This page, like many HTML pages, is just XML with a style sheet attached. If you're familiar with XHTML, you would know it's a hybrid of HTML in the fact that it's XML compliant. Much like HTML pages, it has a stylesheet attached. To see this, right-click on the page and go to View Source.

You should see this:

XML
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="realmstatus.xsl"?>

The first line is the XML declaration, the second is the stylesheet being attached to the data. I won't go any further into how XML/XML stylesheets work, mainly because that isn't the aim of this article. The reason I've explained this is to help you understand why there is styling showing up in an XML file.

Understanding the Data

If you continue to look at the source of the XML, you'll see a line that looks like this for every realm:

XML
<r n="Aegwynn" t="2" s="1" l="1"/>

Blizzard has created some highly optimized XML in the fact that the attribute names are very, very short. My guess is this would make downloads much faster. Now, each one of these attributes stands for something. Let's try to figure out what they mean.

  • N: Obvious in my opinion, this is the name of the realm.
  • T: T? What could that be? Well, there are a few ways to figure that out, either by looking at the formatted XML and cross-referencing it with the raw XML, or looking at the stylesheet. Looking at the stylesheet, we see this attribute represents the realm Type. 1 = Normal, 2 = PvP, 3 = RP, 4 = RPPvP.
  • S: Looking at the stylesheet, we can see S is for Status, which represents the status of the realm. 1 = Up, everything else = Down.
  • L: If you look towards the bottom of the stylesheet, you can see L is for Population (or Load). 1 = Low, 2 = Normal, 3 = High, 4 = Max (Queued).

If we take a look at the example line from above, we can see the server is Aegwynn, a PvP server that is up with Low popularity. Pretty easy, huh?

Using the Data in Code

Now we have an understanding of the data we're working with. Next, we want to be able to use this in the context of code. This is actually quite simple using XLINQ (LINQ to XML).

For the purposes of this article, I'm going to use a Windows Forms application, but feel free to use this code in any context (ASP.NET, WCF, WPF, etc).

Begin by starting up Visual Studio 2008 and creating a Windows Forms application. Add a class to the project called RealmStatus. This class is basically going to be a wrapper for each realm XML element in the realm status XML. To make this wrapper more user-friendly, let's create some enums.

C#
public enum RealmPopulation
{
    Low = 1,
    Normal,
    High,
    Max
}

public enum RealmType
{
    Normal = 1,
    PvP,
    RP,
    RPPvP
}

These enums will help us in both code and visual presentation of the data. Next, we need to make a class to wrap the whole realm status element. To do this, we'll create a class using .NET's new Automatic Property feature.

C#
public class RealmStatus
{
    public string Name { get; set; }
    public RealmPopulation Population { get; set; }
    public RealmType Type { get; set; }
    public bool Up { get; set; }
}

Now that we have our class that represents a WoW's realm status, let's move onto grabbing and querying against the XML.

Add another class and call it WowRealms. Before we continue, we need to add a using statement to the top of our class.

C#
using System.Xml.Linq;

Next is our WowRealms class, which I've made static since it shouldn't hold state.

C#
public static class WowRealms
{
}

Now we need to create a method that will get the XDocument from the URL we used earlier. With XLINQ, this is actually pretty simple.

C#
public static XDocument GetDocument()
{
    return XDocument.Load("http://www.worldofwarcraft.com/realmstatus/status.xml");
}

Yep, that's really all we have to do to get a valid XDocument item of the XML data we saw earlier. Now the fun begins!

Let's create a method that will let us retrieve a RealmStatus object from a name. To do this, we need to use LINQ to XML to query against the list of elements and return a new RealmStatus object. Create a method that will return a RealmStatus object called GetRealmStatusByName.

C#
public static RealmStatus GetRealmStatusByName(string realmName)
{
    XDocument document = GetDocument();
    RealmStatus realmStatus = 
    (from s in document..Element("page").Element("rs").Elements("r")
                               where s.Attribute("n").Value == realmName
                               select new RealmStatus()
                               {
                                   Name = s.Attribute("n").Value,
                                   Population = (RealmPopulation)Enum.Parse
                (typeof(RealmPopulation), s.Attribute("l").Value),
                                   Type = (RealmType)Enum.Parse(typeof(RealmType), 
                    s.Attribute("t").Value),
                                   Up = s.Attribute("s").Value == "1"
                               }).SingleOrDefault();
    return realmStatus;
}

Finally, a method with some meat on its bones. At first glance, this method can look quite confusing, but to be honest, it's really quite simple. Let's dissect this method.

C#
XDocument document = GetDocument();

This is really self-explanatory, we're just getting the XML data from the status.xml file.

C#
RealmStatus realmStatus = (from s in document.Element("rs").Elements("r")
                           where s.Attribute("n").Value == realmName

The first two lines are the beginning of our LINQ query. On the first line, we're setting up the query by getting all "r" elements in the "rs" element. To help visualize this, let's take a look at the XML file.

XML
<rs>
    <r n="Aegwynn" t="2" s="1" l="1"/>
    <r n="Aerie Peak" t="1" s="1" l="3"/>
    <r n="Agamaggan" t="2" s="1" l="1"/>
    <r n="Aggramar" t="1" s="1" l="3"/>
    ...
</rs>

As you can see, we have the root element <rs> and child elements <r>. On the second line of the LINQ query, we're adding a where expression looking for only a realm with the name passed from the method argument. To do this, we're getting the "n" attribute of the "r" element.

C#
select new RealmStatus()
{
   Name = s.Attribute("n").Value,
   Population = (RealmPopulation)Enum.Parse(typeof(RealmPopulation), 
        s.Attribute("l").Value),
   Type = (RealmType)Enum.Parse(typeof(RealmType), s.Attribute("t").Value),
   Up = s.Attribute("s").Value == "1"
}).SingleOrDefault();

This part of the LINQ query is like any SELECT statement in a normal SQL query. We're going to grab the attributes from each element and use the .NET Object Initialization feature to insert the property values from our query. Though this may seem like we only want to get one realm, this operation would actually be preformed for each element returned in our query if we were getting more then one (1) result. The very last line of the query is a call to the method SingleOrDefault() since we know there can only be one result for a server name.

C#
return realmStatus;

.. and return our result! A note of caution -- if there are no results for a given realm name, it will return null.

Now it's time to test out our code! To do this, let's create a simple interface to allow someone to type in a realm name and search for it and display some output to the user. I created a very basic interface that looks like this:

There's also a Label below the TextBox we can use to display some output that you cannot see because it has its Text property set to None. Now that we have our UI and code base created, let's add an event handler for the Button's Click event and output some data to the user.

Here's the code I used in my Button's Click event handler:

C#
private void SearchButton_Click(object sender, EventArgs e)
{
    string realmName = RealmNameTextBox.Text;
    RealmStatus realmStatus = WowRealms.GetRealmStatusByName(realmName);
    if (realmStatus == null)
    {
        OutputLabel.Text = 
          string.Format("No realm with name {0} was found", realmName);
    }
    else
    {
        string serverStatus = string.Empty;
        if (realmStatus.Up)
        {
            serverStatus = "Up";
        }
        else
        {
            serverStatus = "Down";
        }
        OutputLabel.Text = string.Format("{0} ({1}) has a population of {2} and is {3}", 
    realmStatus.Name, realmStatus.Type, realmStatus.Population, serverStatus);
    }
}

This code is pretty straightforward. You'll notice how easy wrapping this has made it for us to use, and how clean our code is for the form. Now, we have a working data layer and presentation layer... enough talk, let's try it.

Great, it works!

Well, I hope this helped those of you looking to learn new technologies, and maybe intrigued some of you gamers to give programming a shot. As you've seen, this code is very flexible and easy to use, not just in Windows Forms, but WPF, WCF, ASP.NET, and even Vista gadgets!

I've showed off some of .NET 3.5's brand new technologies that are making today's developers more productive and efficient. These features include: XLINQ in the Base Class Library, Automatic Properties, and Object Initialization. This is only the tip of the iceberg, I encourage all the readers of this article to go out and buy/download Visual Studio 2008/.NET 3.5 Express editions, and don't limit yourselves.

Have fun!

Points of Interest

  • At the time this article was written, Visual Studio 2008 and .NET Framework 3.5 were both in Beta 2, and Blizzard's World of Warcraft had over 9,000,000 subscribers.

History

  • 11/2/2007: Initial post.
  • 9/19/2008: Edited to reflect XML update, thanks btlife!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)