Delphi xml data binding pains
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.
Leave a comment Cancel reply
Recent
The vatican vault
- September 2023
- August 2023
- March 2023
- February 2023
- December 2022
- October 2022
- January 2022
- October 2021
- March 2021
- November 2020
- September 2020
- July 2020
- June 2020
- April 2020
- March 2020
- February 2020
- January 2020
- November 2019
- October 2019
- September 2019
- August 2019
- July 2019
- June 2019
- May 2019
- April 2019
- March 2019
- February 2019
- January 2019
- December 2018
- November 2018
- October 2018
- September 2018
- August 2018
- July 2018
- June 2018
- May 2018
- April 2018
- March 2018
- February 2018
- January 2018
- December 2017
- November 2017
- October 2017
- August 2017
- July 2017
- June 2017
- May 2017
- April 2017
- March 2017
- February 2017
- January 2017
- December 2016
- November 2016
- October 2016
- September 2016
- August 2016
- July 2016
- June 2016
- May 2016
- April 2016
- March 2016
- January 2016
- December 2015
- November 2015
- October 2015
- September 2015
- August 2015
- June 2015
- May 2015
- April 2015
- March 2015
- February 2015
- January 2015
- December 2014
- November 2014
- October 2014
- September 2014
- August 2014
- July 2014
- June 2014
- May 2014
- April 2014
- March 2014
- February 2014
- January 2014
- December 2013
- November 2013
- October 2013
- September 2013
- August 2013
- July 2013
- June 2013
- May 2013
- February 2013
- August 2012
- June 2012
- May 2012
- April 2012
Can you have a look? http://stackoverflow.com/questions/29507797/ixmlnode-set-prefix-and-namespace?noredirect=1#comment47176803_29507797
This is a well know old bug in Delphi.
The XML binding wizard is useless with modern sheets.
Can you tell me any alternatives to it? I dont want to change the programing language
Well, i ended up coding the classes by hand. I salvaged what i could from one import, then simply sad down and mapped the rest by hand – using the XML etc. framework that Delphi used.
But sadly no, I have not yet found an alternative. Perhaps remobjects is the company to ask about this, since they have their own service importer which deals with xml and datatypes
I want to sugest an simple work-arround.
First open the XML as a text file, and remove the namespaces/prefixes (just replace it with empty string “”), then overwrite the xml file. So you have at the end an more simple structure, without namespaces.
Maybe is need it to remove the “namespace” also from the “declare-section”. So another replace with empty string (“”).
I remember I had such an XML file in the past, and to process it I did this.
So the processing was done in 2 steps:
1. open the XML as text file, remove the prefixes (namespaces) and save the file.
2. open it as XML and import the data.
I build an batc-program which was doing the 2 steps and it worked perfectly for years.
It is not the most professional method, but is very simple and it works.
I’ve reported it as a bug. Vote for it here https://quality.embarcadero.com/browse/RSP-18172?filter=-2