Generating Wrapper Classes from an XML Schema

Environment:
   Platform: NT SP6 or higher and the free community edition of Visual Code-Generator (1.2.2 or higher)
   Development platform: VB, VB.Net, C#, and Java

Summary

This article describes how to take an XML schema and generate a set of wrapper classes from it that allow you to manipulate an XML document via simple strongly typed objects, thus removing the need for developers to get bogged down in the complexities of schemas or deal with the nuts and bolts of MSXML.

Introduction

XML is now everywhere. It's been universally embraced across the whole industry. It's fundamental to Web Services, .NET, J2EE, and many, many more technologies. However, its real potential is achieved when XML is used in conjunction with XML Schemas; without a schema, there is nothing to formalise what is valid within your XML document. Without this, XML is reduced to another file format, to all intents an purposes as proprietary as a binary format.

So Schemas are a good thing?

Well of course, but they're not without issues. DTD has a complex, unintuitive syntax and is very limited. XDR is simple but a little too basic. XSD is extremely comprehensive, but very complex. That said, DTD and XDR are on their way out, and XSD has been accepted as the new standard, making it a one-horse race.

This makes understanding XSD an essential skill required for working with XML. In order to actually work with XML itself, you need to be very familiar with some kind of XML parser. MSXML is very good, comprehensive, but still quite complicated. All this to get to grips with before you've even started!

But what choice do you have?

Well, let's look first at what we have:

  • XSD, a complicated machine-readable description of what our XML document should look like.
  • MSXML, a complicated XML parser capable of reading and writing XML documents.

In essence, you have everything you need to create a component that will take an XSD Schema and generate a set of wrapper classes that abstract away all the details of XSD, XML, and MSXML. This leaves you to manipulate the data held in your XML documents.

So how does it work?

We have produced a template that can be used to generate a set of wrapper classes from an XDR or XSD schema. In this article, we will look at the C# templates (there are other templates for different languages). First, let's look at the schema file we want to wrapper.

Figure 1 shows a fragment from an XSD schema; it holds information about a recipe. Each recipe has a number of ingredients and preparation steps.

<xsd:complexType name="Recipe">
  <xsd:sequence>
    <xsd:element name="Summary" type="xsd:string"/>
    <xsd:element name="Ingredient" type="Ingredient" maxOccurs="unbounded"/>
    <xsd:element name="PreparationStep" type="PreparationStep"
                 maxOccurs="unbounded"/>
  </xsd:sequence>
  <xsd:attribute name="Name" type="xsd:string" use="required"/>
  <xsd:attribute name="PrepTime" type="xsd:unsignedShort" use="optional"/>
  <xsd:attribute name="CookingTime" type="xsd:unsignedShort" use="optional"/>
</xsd:complexType>

Figure 1

If we wanted to wrapper this with a class, we would probably want the Recipe element to be represented as a class. This class would have a property Name, and optional properties PrepTime and CookingTime.

We would also expect the elements PreparationStep and Ingredient to be represented as classes, and for our recipe class to have a collection of PreparationStep and Ingredient objects.

public String Summary
{
  get {…}
  set {…}
}
public IngredientCol IngredientsCol
{
  get {…}
}
public PreparationStepCol PreparationStepsCol
{
  get {…}
}
public String Name
{
  get {…}
  set {…}
}
public UInt16 PrepTime
{
  get {…}
  set {…}
}
public Boolean PrepTimeValid
{
  get {…}
  set {…}
}
public UInt16 CookingTime
{
  get {…}
  set {…}
}
public Boolean CookingTimeValid
{
  get {…}
  set {…}
}
Figure 2

The Summary element is a little trickier. You can see from the schema that it's an element that represents a primitive type string. Now, we could take care of this by wrapping it with a class, but that seems a little over the top; so, we'll make it a property of the Recipe class.

Figure 2 shows a summary of the assessors for the generated Recipe class. You may notice that because PrepTime and CookingTime were optional within the schema, they have an addition property in the wrapper class PrepTimeValid and CookingTimeValid. These allow you to determine whether these properties are valid within the object. If they are false, they indicate that the attribure is not in the XML document.

The templates produce the whole project, all the classes, the collections, all the methods, XML serialization, and so forth. All you need to do is compile and use it! You can even place annotation blocks into the schema that allow you to document the generated code. This, combined with .NET's documentation generator, allows you to produce documentation for your new library.

Using the Wrapper Classes

The wrapper classes couldn't be simpler to use. Figure 3 shows a how to use the example wrapper classes using VB.Net.

First, we create an instance of the class we want to be the root element of our document, in this case CookBookCls. We set the properties on this class in the same way we would any other object. If we want to add an Ingredient object to the collection, this can be done via the IngredientCol collection; the Add method returns the new Ingredient object which we can populate.

The PreparationStep collection is exactly the same.

Finally, we want to see the XML that these objects represent. We can access this using the method ToXml.

' Sample CookBook
Dim oCookBook As New CookBook.CookBookCls()
Dim oRecipe As CookBook.RecipeCls

' setup the book itself
oCookBook.Name = "Adventures in food"
oCookBook.Author = "Mr Joe Blogs"

' Add a recipt
oRecipe = oCookBook.RecipeCol.Add
oRecipe.Name = "Blackberry Yummies"
oRecipe.Summary = "A perfect treat for summertime …"
oRecipe.CookingTime = Convert.ToUInt16(30)
oRecipe.PrepTime = Convert.ToUInt16(15)

' add an ingrediants to the Recipe
With oRecipe.IngredientCol.Add()
    .Amount = 3
    .UnitEnum = CookBook.Unit.Unit_tbsp
    .Description = "Butter"
End With
…Snip…
With oRecipe.IngredientCol.Add()
    .Amount = 1.25
    .UnitEnum = CookBook.Unit.Unit_cup
    .Description = "fresh blackberries"
End With

' Add the preparation steps
With oRecipe.PreparationStepCol.Add
    .Summary = "Pre-Heat Oven"
    .Details = "Preheat oven to 325 degrees C…"
End With
…Snip…
With oRecipe.PreparationStepCol.Add
    .Summary = "Cook for 35-40 mins"
    .Details = "Pour batter into the prepared…"
End With

' display resulting XML
System.Console.WriteLine(oCookBook.ToXml(True))

Figure 3

Sample Output

The following output is from the above sample code. As you can see, the XML complies with the XSD schema that the wrapper classes were generated from.

<?xml version="1.0" encoding="utf-8"?>
<CookBook Name="Adventures in food" Author="Mr Joe Blogs">
  <Recipe Name="Blackberry Yummies" PrepTime="15" CookingTime="30">
    <Summary>A perfect treat for summertime or ...</Summary>
    <Ingredient Description="Butter" Amount="3" Unit="tbsp" />
...Snip...
    <Ingredient Description="fresh blackberries" Amount="1.25" Unit="cup" />
    <PreparationStep>
      <Summary>Pre-Heat Oven</Summary>
      <Details>Preheat oven to 325 degrees C ...</Details>
    </PreparationStep>
...Snip...
    <PreparationStep>
      <Summary>Cook for 35-40 mins</Summary>
      <Details>Pour batter into the prepared ...</Details>
    </PreparationStep>
  </Recipe>
</CookBook>

 

Figure 4

Code Generation

But that's not the end of it all. Say you don't like the way our templates work; you want to add your own methods, or change the way we've implemented some of the functionality. Well, with most generators this is a problem! You could request a change from the manufacturer, or change the generated code yourself. Neither option is very satisfactory. But with this generator you can change the templates.

We allow you access to the templates. You can create a new project within Visual Code-Generator, and make the changes you wish. What's more, the templates are based on ASPs using VBScript and JavaScript as their internal scripting language, making them very simple to work with.

Figure 5

Figure 5 shows a section from the template the generates the class files for C#. If you wanted to add a copy constructor or change then a names of the classes, this is simple to do. As mentioned before, the templates work in exactly the same way as ASP and JSPs, so the syntax should be very familiar.

Step By Step

  1. Open Visual Code-Generator.
  2. Select menu File->Project Wizard.
  3. Select a suitable location, and give the project a name.
  4. Select the XML Schema Wrapper Workspace from the list and hit OK.
  5. Select the kind of schema you want to use as a template (XSD or XDR).



    Click here for larger image

  6. We will let the wizard give us a default schema to start with, so just click OK,
  7. Accept all the prompts to create directories and files.
  8. You now have a new project.
  9. To build the wrapper from the Schema, press F5.
  10. If you select the Output Tab, you can see a list of all the files created.
  • The job is done; all you have to do now is open the project using .Net and build it.
  • If you have your own schema, you can open the Project.xsd or Project.xdr file and cut and paste it into there; then just hit F5 again to re-build the output using your schema.
  • If you want to edit the templates, you can do so by selecting the Templates tab, and double-clicking on the template you want to change.
  • Note that you are working on a copy of the templates. Changes made to this project will not effect other projects you may have created in the past.

Conclusion

Whatever you're doing with XML, 9 times out of 10 you'll end up encapsulating the complexity of reading and writing from the XML document. These templates do that for you, saving 100s of man days, and with the flexibility to be changed in seconds. All you need is a valid XSD or XDR file, and in seconds you have a class library to work with instead of the customary messing around with MSXML.

Related Information

XML Wrapper Template: Transform XML Documents into Visual Basic Classes
XML Code Generator: Generating Visual Basic Classes from XML Schemas

Downloads

Download Community Edition of Visual Code-Generator
Download source - 24 Kb


Comments

  • Why not use .NET XMl Serialization?

    Posted by Legacy on 06/06/2002 12:00am

    Originally posted by: Mark

    This functionality is already built in .NET via XML Serialization. Look under the the namspace System.Xml.Serialzation

    Reply
  • Visual Code-Generator 1.2.4

    Posted by Legacy on 06/05/2002 12:00am

    Originally posted by: Simon Sprott

    Visual Code-Generator 1.2.4 is now available with improved ATL templates and integrated help files.

    http://www.code-generator.com

    Reply
  • XML2ATL workspace

    Posted by Legacy on 05/30/2002 12:00am

    Originally posted by: solon

    XML to ATL template is not working very well : in XML2ATL.gen template, line 27, when I try to use XDR schema a runtime error is thrown. I have replaced OpenXsdSchema(...) with OpenXdrSchema( schema_file, true) and the code is generated, but it doesn't have any put_attrib methods ( only get_attrib) - is there any way to generate put methods and code to serialize the objects into XML ( like VB version ) ? Thanks.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds