OX Mapping - Mapping XML Schema to Classes Pt 2
In my previous entry I went through the what's and why's of mapping XML Schema to classes. I'd like to use this post to outline the rough algorithm of how I've tackled this mapping, it may be useful for other people to compare their implementations. Also, with Indigo coming along soon it will be interesting to see how OX Mapping is implemented using this new technology.
The basic mapping is quite simple, the rules are as follows:
- Each element with a complex type in the schema maps to a class.
- Each simple type element belonging to a complex type is a property on that class.
- Each nested complex type element has an implicit one-to-many relationship with the parent element.
- Where minOccurs=0 the property is optional.
- Where maxOccurs>1 the property should be defined as an array.
- For each relationship the class should contain access methods or properties. For relationships where maxOccurs>1 the class should have a method that returns an array of the mapped type, where maxOccurs=1 it should be a property. The relationship should be bi-directional with an access property for the parent.
- Where maxOccurs>1 a collection should be defined to house the complex type element. This collection should include helper functions to access elements using indexes defined using constrains and keys in the schema.
- Enumerated facets should be translated to enumerated types in the code.
- You should be able to define explicit constraints that include relationships between elements.
This is basically what the XML Typed DataSet Generator is doing. The DataSet prefers a specific format of schema, but the basic premise is there. Of course these aren't all the rules, there are plenty more.
It all becomes more complicated when you introduce derived schemas. If a given schema contains complex types that reference other complex types, maybe from other schemas then the OX Mapper can be implemented in two ways. It can ignore the derivation information and just generate a flat class or it can take the derivation information from the schema and generate equivalent classes in the code. This will allow the class user to keep a polymorphic relationship with other derived schemas else where in the system.
The process could work like this:
- If a new element contains a complex type that derives from another complex type the base class is defined as any element that implements the base type. If the base type is defined in a different schema then the element should be defined in that schema.
- If the relationship and index features of the base type need to be preserved and used in the derived type then a 'replacement' schema should be used rather then normal complex type derivation. Using a replacement the existing element is modified and the existing constraints still apply.
- If only new constraints need to be added to an existing element (an existing class from another schema) then the type does not need to be derived and only new constraints are required to be added at the parent element level. This can be done using a replacement schema and modifying the parent element.
The problem is that now the derived types need to be compiled in with the assembly for the names to be resolved. This may require an additional step where another OX Mapping process needs to import the base schema(s). The actual process is more involved and many of the problems stem from the necessity to include constraints as part of the interface on a class. Without this requirement the whole process would be a lot easier.
So - is this really worth spending much time on? If you were creating an SOA infrastructure for your clients, or internally in your department you would want to model your complex types with re-usability in mind. With this re-usability you would want to development a base core model and maybe derive complex types for specific vertical applications using them. You would also want to interoperate these types at the code level, if you wanted to make use of re-usable libraries. The bottom line is that you would really want your typed universe in the WSDL/XSD world to map to the typed universe in the .NET world of shared assemblies. If you want all this then your OX Mapper will need to be clever enough to bridge this gap. The question is, will Indigo meet this challenge?