Today I was playing around with Xsd (Xml Schema) files a bit for
automatic Xml generation of specific types I need for an editor.
Starting to work with Xsd files isn't that hard, looks like Xml, but
stuff is named "element", "complexType", "sequence", etc. Once you are
familar with that you can easily write Xsd files (but please, not
another "Customer" example, I'm going to puke), which validate your Xml
data automatically for you. But I don't wanted to do that, I just need
a clean and easy way to generate specific types like Colors, Vectors,
Material parameters, etc. Btw: Everthying shown here is only intended
to be used by the Editor, Artists don't want to work with Xml files and
I don't think Programmers should either. Let the work be done by the
computer.
The things I will cover here don't use much of the keywords in Xsd. See References and your MSDN help
for a complete overview what you can do with Xsd (or any other Xml
Schema for Validation). For a more complex and longer example of an
useful Xsd file see the Google sitemap xsd file.
I on the other side try to keep things simple. Instead of using 6 xml
lines for describing just a color, I prefer 1 simple line (using xml
attributes instead of child nodes).
Here is the sourcecode for this article (requires .NET 2.0 and uses NUnit). Take a look at the unit tests to see how to use this code.
Ok, here is an examples using Xsd (you might notice I don't use
namespaces or annotations, they only bloat things up ^^ If your Xsd
files get more complex, you should think about expanding them.):
And this would generate by default:
Or a more useful example inside the Material node:
So, how do we do all that stuff? Yes, exactly, by using the
System.Xml.Schema namespace. All the required classes are in there, but
most function do only check your code or help you to analyse. We want
to create xml. Anyway, we have always start with loading and compiling
the Xsd file first. If anything goes wrong here, you will get an
exception explaining what you did wrong in the Xsd file. This is the
handy dandy method I use for loading XmlSchemas:
If you want to load a bunch of Xsd files (I already have created
around 30 of them in just a couple of hours ^^), it is much better to
add them all to the same XmlSchemaSet and compile them all at once.
Note: This has the disadvantage that any compiling error will result in
all the rest of the schemas not to be loaded. But it is much faster
this way.
We need 2 more methods for our goal to generate a xml node.
This first one will create the xml node and go through all schema items
(only ComplexType items are handled in this example) if possible. Then
it returns the child node to allow maybe changing some more things.
And finally we use this method to fill in all the xml elements
and using the default values (you can specify them with default="value"
in the xsd file). First we go through all child nodes and recursively
call this function again until all nodes are handled. Then we go
through all schema attributes and add them as well.
Ok, there is one helper method missing for getting the default
value. Lets assume that most elements don't have a default element and
will return an empty string for the default value. It is much more
useful to have "real" default values like 0 or false and thats excatly
what TryToFindDefaultValue is for:
Ok, that it. Now you can create nodes from any loaded schema using code like this one from the unit tests (see project files above):
Btw: You can also use Visual Studio to edit or create xsd files
in a more fancy way, but I didn't found it more productive than typing
in xsd directly for small xsd files.
References:
Have fun. |