|
Introduction
XML is now everywhere, its been universally embraced across the whole
industry. Its fundamental to Web Services, .NET, J2EE & 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 there not without issues. DTD has 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 & XDR
are on there 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 lets 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, & MSXML. Leaving 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 others templates for different languages). First
lets 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, then we would probably want the
Recipe element to be represented as a class. This class would have a property
Name, and optional properties PrepTime & CookingTime.
We would also expect the elements PreparationStep & Ingredient to be
represented as classes, and for our recipe class to have a collection of
PreparationStep & 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 more tricky. You can see from the schema
that it's an element, that represent 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 & CookingTime where optional
within the schema, they have an addition property in the wrapper class
PrepTimeValid & CookingTimeValid. These allow you to deturmine if
these properties are valid within the object. If they are false then the
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 etc. All you need to do is compile
& 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 ASP's using VBScript & JavaScript as there
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 & JSP's so the syntax should be very
familiar.
Step By Step
- Open Visual Code-Generator
- Select menu File->Project Wizard
- Select a suitable location, and give the project a name
- Select the XML Schema Wrapper Workspace from the list and
hit OK
- Select the kind of schema you want to use as a template (XSD or XDR)

- We will let the wizard give us a default schema to start with so
just hit OK
- Accept all the prompts to create directories and files.
- You now have a new project.
- To build the wrapper from the Schema press F5.
- If you select the Output Tab you can see a list of all the files
created.
 |
- Job done, all you have to do now is open the project using
.Net and built 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 by selecting the
Templates tab, and double clicking on the template you want to
change.
- Note 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 your 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 100's 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
|