Using LINQ to Query the Armory

Feb 2, 2008 at 1:12 AM
Edited Feb 2, 2008 at 1:14 AM
I'm a ways from being able to use .NET v3.5 in my project, but I thought I would share some really cool code I wrote today.

I stole the WebClient idea from you, because using the URL doesn't seem to quite work the way I had been hoing on it's own. But if you crack open Visual Studio 2008 and give the below a whirl, it actually cranks through the character sheet quite quickly. And, as you can see, it's mind-blowing how minimal the amount of code is.

      XDocument _charSheet;
 
      System.Net.WebClient _wc = new System.Net.WebClient();
      _wc.QueryString.Add("r", this.Realm);
      _wc.QueryString.Add("n", this.CharName);
      _wc.Headers.Add("user-agent", "MSIE 7.0");
 
      System.Xml.XmlTextReader _reader = new System.Xml.XmlTextReader(_wc.OpenRead(ArmoryCharSheet));
      _charSheet = XDocument.Load(_reader);
      //Clipboard.SetText(_charSheet.ToString());
      //InterrogateTheElement(_charSheet.Root);
 
      IEnumerable<XElement> _charInfoEl = _charSheet.Root.Descendants("characterInfo");
      if (_charInfoEl.Count() < 1) {
        MessageBox.Show("No descendants at <characterInfo>");
      } else if (_charInfoEl.Count() > 1) {
        MessageBox.Show("Multiple descendants at <characterInfo>");
      }
 
      //InterrogateTheElement(_chars.First());
      var _charInfo = from item in _charInfoEl.Descendants("character")
                      select new {
                        Battlegroup = item.Attribute("battleGroup").Value,
                        CharURL = item.Attribute("charUrl").Value,
                        Class = item.Attribute("class").Value,
                        ClassID = item.Attribute("classId").Value,
                        Faction = item.Attribute("faction").Value,
                        FactionID = item.Attribute("factionId").Value,
                        Gender = item.Attribute("gender").Value,
                        GenderID = item.Attribute("genderId").Value,
                        GuildName = item.Attribute("guildName").Value,
                        GuildURL = item.Attribute("guildUrl").Value,
                        LastModifiedString = item.Attribute("lastModified").Value,
                        Level = item.Attribute("level").Value,
                        Name = item.Attribute("name").Value,
                        Prefix = item.Attribute("prefix").Value,
                        Race = item.Attribute("race").Value,
                        RaceID = item.Attribute("raceId").Value,
                        Realm = item.Attribute("realm").Value,
                        Suffix = item.Attribute("suffix").Value
                      };
 
      IEnumerable<XElement> _profsEl = _charInfoEl.Descendants("professions");
      var _profs = from item in _profsEl.Descendants("skill")
                      select new {
                        Key = item.Attribute("key").Value,
                        Name = item.Attribute("max").Value,
                        Max = item.Attribute("name").Value,
                        Value = item.Attribute("value").Value
                      };
 
      IEnumerable<XElement> _baseStatsEl = _charInfoEl.Descendants("baseStats");
      var _baseStats = from item in _baseStatsEl.Descendants()
                   select new {
                     Stat = item.Name.ToString(),
                     Base = item.Attribute("base").Value,
                     Effective = item.Attribute("effective").Value,
                     Element = item
                   };

The area that baffled me the most, as I was playing with the XML was the skills, because of all of the possible possibilities. My solution was simply to output it as an XML Element...which got me to thinking - why not store more of the information you pull out of the Armory as XML Elements? It would be a decent way of storing it in the database, and would save me a tremendous amount of work from the way I do it now...for values that I am storing just to store them. :)

Anyway, I was quite amused with myself, and I thought you would appreciate the code above.


Also, to be complete, there is a commented call in the code that calls the following function, which simply was being used for debugging/evaluation purposes as I was working through the code:
    private void InterrogateTheElement(XElement _elem) {
      IEnumerable<XElement> _pages =
        from _p in _elem.Elements()
        select _p;
      
      foreach (XElement _p in _pages) {
        MessageBox.Show(_p.Name.ToString());
      }
    }