Archive

Archive for September 17, 2013

Delphi xml data binding pains

September 17, 2013 6 comments
xml structures

xml structures

Delphi ships with an XML data binding wizard that is, perhaps, not the most widely used utility in the Delphi toolbox but truly one of the most valuable. It really is a shame that it’s not more widely used because it can really simplify working with xml in all it’s forms. For instance, if you have a custom fileformat for your project or preferences files, then sculpting that as a schema in something like XML Spy – and then getting Delphi to generated easy to use classes to access the file is very simple.

But there are problems. Serious problems if you want to use the XML data binding wizard for anything complex and professional.

The current problem is that the import wizard screws-up namespaces. As you probably know an XSD file allows you to not only sculpt the structure of an XML file – it also allows you to pre-define data structures. Think of it as a schema that can contain delphi record definitions. An XSD file can also refer to other XSD files which is not unlike the dependencies pascal has for units, where we declare the list of units we need in the uses clause.

And this is where the XML data binding wizard simply ruins the whole game. In my example we have a huge set of XSD files that are all inter-linked and defines a large set of data structures. These structures are defined by the government – so we really dont have a choice in the matter. The data binding wizard imports everything correctly and it also generates code that matches the data structures. But it forgets to prefix various datatypes with the correct namespace token.

Example: Let’s say you have an XSD file that defines personal information. Stuff like name, address, an array of phone numbers, array of email or PM services etc.
This file imports a second file where all the datatypes are defined. So the address record etc. are defined in this second file, but put into a more meaningful structure in the first file. This is just like declaring your records and types in one unit and using them from a second unit in pascal.

The problem? XML requires you to prefix external datatypes so the parser can tell the difference. One example is a structure called “id” which defines an array of “id” items. This is perfectly valid as long as you prefix the array items correctly:

<?xml version="1.0" encoding="utf-8"?>
<MyRecord xmlns="root namespace" xmlns:tnsa="second namespace">
<id>
  <tnsa:id>
    < .. >
  </tnsa:id>
  <tnsa:id>
    < .. >
  </tnsa:id>
</id>
</MyRecord>

In the above pseudo xml output, we see that the first “id” tag has no prefix, it defaults to the root namespace. Whenever datatypes declared in “second namespace” is used, it should be prefixed with “tnsa” as defined. But the Delphi data binding wizard simply ignores this and doesn’t prefix any of the generated tags. Instead we get this:

<?xml version="1.0" encoding="utf-8"?>
<MyRecord xmlns="root namespace" xmlns:tnsa="second namespace">
<id>
  <id>
    < .. >
  </id>
  <id>
    < .. >
  </id>
</id>
</MyRecord>

Which causes a natural error because any parser that receives the generated XML will think the sub-items are of the same type as that defined in the root schema, causing a rather nasty validation exception.

It really sucks when you have to “roll your own” data binding for a product costing 10 times more than it’s competitors.┬áThis bug has been here since Delphi 7 – it really is about time the codegen was updated to correctly prefix the generated data. I was able to use the free version of visual studio to generate a C# databinding out of the box correctly, something that made me very sad for the product we all love.