Maintaining XSD files in VS2010


Having more-or-less painlessly migrated across to my SSD drive (which is more than can be said for the one I use at work, which randomly wiped itself – even down to the partition itself – after I moved desk last Friday), it’s back to VS2010 stuff.

I had to do some work with XSD files lately in VS2010, and, having sort of suffered through using them in 2008, was pleasantly surprised with the direction that they’ve chosen to go in VS2010. So, if you’re unlucky enough to be working on an XSD files, read on to see if VS2010 will make it any less painful.

Getting started

The main view that you get when you open up an XSD file is a big white page with some options and statistics on your XSD file: –

image

Note that the “add” links don’t add a new element etc. to the schema – they add that selection to the “workspace”, which is the set of entities in your schema that you are “working with” for viewing – confusing.

Editing XSD files

The biggest change is that there is no editable designer surface any more in VS – all your editing (at least as far as I could find) of schemas must be done in the XML Editor. You get intellisense at least though, so it’s not that bad, and you can actually blitz through some tedious authoring relatively quickly. I’d like to see some support for code snippets, though.

image

You get real-time error checking of your schema – although I think that you got this in VS2008 so this is nothing new.

Viewing XSD files

You now get a “class view” of your entire schema, but with amended icons for XSD schema, called the XML Schema Explorer: –

image

Notice how the two types (Department and Employee) use the same Class icon as the Class Explorer etc., whereas the instance (element) – company – shows as an element icon. Role is an enumeration, but sadly this view does not show the available options of the enumeration – shame. One other nice thing is that you can search through the entire tree and do various sorting (name, type, document order etc.).

There’s also the Graph View which is supposed to show the relationship between selected nodes in your workspace:

image

I must’ve misunderstood this one, but I don’t see really what this view does – you drag items from the explorer view on the surface and it puts them there – big deal. I don’t see any relationship lines or stuff like that, so it seems kind of pointless. One nice thing you can do is select any element (e.g. company) and generate a sample XML document from it – quite handy.

However, there is one other view left – Content Model View – which is very nice. It’s an interactive map of your entities and types, allowing you to drill in to the tree but in a non-tree view(!). Let’s say we are viewing the “company” element (see in the explorer above). We would start with this: –

image

If you drill into it, you then get this: –

image

Drilling down again: –

image

And finally: –

image

This is actually a very powerful tool – the viewer handles all sorts, included attribute groups, cardinality etc. – very handy. Having the XSD editor and this view side-by-side makes it easy to both edit your schema and see the impact immediately.

A Dynamic XML Document – Part 2


Continuing on from last post, how do we get the array-style [notation] on a dynamic object? Well, there’s a handy method that you can override on DynamicObject called TryGetIndex which does just that:
 
   1: /// <summary>

   2: /// Searches for any elements that have any attribute with the value specified.

   3: /// </summary>

   4: /// <param name="binder"></param>

   5: /// <param name="indexes"></param>

   6: /// <param name="result"></param>

   7: /// <returns></returns>

   8: public override bool TryGetIndex (GetIndexBinder binder, object[] indexes, out object result)

   9: {

  10:     var valueToSearchFor = indexes[0].ToString();

  11:     var matchingItems = GetElementsByAttributeValue (valueToSearchFor);

  12:     if (matchingItems.Any ())

  13:     {

  14:         result = new DynamicXmlDocument (matchingItems);

  15:         return true;

  16:     }

  17:  

  18:     result = null;

  19:     return false;

  20: }

  21:  

  22: private IEnumerable<XElement> GetElementsByAttributeValue (string attributeValue)

  23: {

  24:     var matchingItems = elements.Where (e => e.Attributes ().Any (att => att.Value == attributeValue));

  25:     return matchingItems;

  26: }

 

Here, I’m searching for any elements that have any attributes with a value as per specified, and then setting the result to a new dynamic xml document based on that sequence.

That’s really it, to be honest! The only things left are the Value getter, which just returns the value of the first element in the dxd, and the implementations of IEnumerable and IEnumerable <T>: –

   1: /// <summary>

   2: /// Gets the contents of the first element in this document.

   3: /// </summary>

   4: public string Value

   5: {

   6:     get { return elements.First ().Value; }

   7: }

   8:  

   9: IEnumerator<DynamicXmlDocument> IEnumerable<DynamicXmlDocument>.GetEnumerator ()

  10: {

  11:     foreach (var element in this.elements)

  12:         yield return new DynamicXmlDocument (element);

  13: }

  14:  

  15: IEnumerator IEnumerable.GetEnumerator ()

  16: {

  17:     foreach (var element in this.elements)

  18:         yield return new DynamicXmlDocument (element);

  19: }

 

I’m not that used to using the yield keyword – to be honest most collections I use day-to-day are the in-built IEnumerable<T> ones, but I see how it’s being used above (this bit is basically taken from here.

Anyway… the point being that with a relatively little amount of effort we have an object which can navigate an XML document very easily and more readably than old-style XML access, and with no real loss of type safety compared to those technologies, either.

Dynamic typing with C#4.0 part 2 – A Dynamic XML Document


Here’s a great example of where dynamic typing makes your code much more readable and logical: parsing an xml document. It turns out that someone has already done this – and I nicked a bit of his code (basically the implementation of IEnumerable) – but it’s funny how similar both of our code was before I found it (link is at end of this post).

Here’s an example XML document:

<catalog>

    <book id="bk101">

        <author>Gambardella, Matthew</author>

        <title>XML Developer's Guide</title>

        <genre>Computer</genre>

        <price>44.95</price>

        <publish_date>2000-10-01</publish_date>

        <description>

            An in-depth look at creating applications

            with XML.

        </description>

    </book>

    <!-- etc. etc. -->

</catalog>

Now, to parse that document, you could currently use either good old XmlDocument (and / or XmlReader), or the more modern XDocument in Linq to Xml. However, both of them and still inherently weakly typed, using strings passed into methods such as “Attribute (“MyAttr”) or Element (“MyElement”). I did see an alpha demo of a strongly-typed version of a Xml Document reader a while ago but haven’t heard anything of that recently. I recall seeing that VB9 also has some good XML support, but I’m exclusively a C# coder so let’s concentrate on that 😉

Anyway. So let’s see if we can make an XML document class in C#4 which will let us read the above XML document like this:

   1: // Create our dynamic XML document based off a Linq-to-Xml XElement.

   2: var xDocument = XDocument.Load ("Example.xml");

   3: dynamic dynamicXmlDocument = new DynamicXmlDocument (xDocument.Root);

   4:  

   5: // Get the first five books

   6: var books = dynamicXmlDocument.book as IEnumerable<DynamicXmlDocument>;

   7: foreach (dynamic book in books.Take (5))

   8: {

   9:     // Print out details on each book

  10:     System.Console.WriteLine ("Id: {0}, Title: {1}, Price: {2}",

  11:         book.id,            // Attribute access

  12:         book.title.Value,    // Element access

  13:         book.price.Value);  // Element access

  14: }

  15:  

  16: // Get a specific book

  17: var specificBook = dynamicXmlDocument.book["bk107"];

  18: System.Console.WriteLine ("Id: {0}, Title: {1}", specificBook.id, specificBook.title.Value); 

  19:  

  20: System.Console.Read ();

This actually wasn’t that difficult to write! Again, inheriting from DynamicObject and overriding a couple of methods, I was able to get this done in about three quarters of an hour.

First thing is the class hierarchy, our constructors and single member field:

   1: class DynamicXmlDocument : DynamicObject, IEnumerable, IEnumerable <DynamicXmlDocument>

   2: {

   3:     IEnumerable <XElement> elements;

   4:  

   5:     /// <summary>

   6:     /// Creates a new instance of the XML Dynamic Document based on a single XElement.

   7:     /// </summary>

   8:     /// <param name="element"></param>

   9:     public DynamicXmlDocument (XElement element)

  10:     {

  11:         elements = new List<XElement> { element };

  12:     }

  13:  

  14:     /// <summary>

  15:     /// Creates a new instance of the XML Dynamic Document based on a sequence of XElements.

  16:     /// </summary>

  17:     /// <param name="elements"></param>

  18:     public DynamicXmlDocument (IEnumerable <XElement> elements)

  19:     {

  20:         this.elements = new List<XElement> (elements);

  21:     }


Nothing too scary there, but notice how we implement IEnumerable and IEnumerable<T> so that we can do the foreach and .Take (5) in the original example.
 
The next bit is the first DynamicObject method we override, which gets called every time you make a property accessor request e.g. myDynamicDocument.book. The method looks for all sub-elements that match the parameter name, and if it finds at least one, returns a new dynamic xml document (dxd) based on them. If not, it looks for any attributes in the first element of the current dxd and returns the value if it finds that. Otherwise it returns null.
 
   1: /// <summary>

   2: /// Gets either all children the XML Dynamic Documents (i.e. elements), or the current element's attribute.

   3: /// </summary>

   4: /// <param name="binder">Specifies the keyword to search on.</param>

   5: /// <param name="result">The resultant object.</param>

   6: /// <returns>True is a match was made.</returns>

   7: public override bool TryGetMember (System.Dynamic.GetMemberBinder binder, out object result)

   8: {

   9:     var elementNameToSearchFor = binder.Name;

  10:     var matchingChildElements = elements.Elements (elementNameToSearchFor);

  11:     if (matchingChildElements.Any())

  12:     {

  13:         result = new DynamicXmlDocument (matchingChildElements);

  14:         return true;

  15:     }

  16:  

  17:     var attributeNameToSearchFor = binder.Name;

  18:     var attribute = elements.First ().Attribute (attributeNameToSearchFor);

  19:     if (attribute != null)

  20:     {

  21:         result = attribute.Value;

  22:         return true;

  23:     }

  24:  

  25:     result = null;

  26:     return false;

  27: }

 

The next question is how to get that array notation e.g. book[“123”] as per the example? That’ll be answered in the next post!