Re: How to to convert object to XML string and back again
On Dec 21, 3:49 pm, brang...@ntlworld.com (Dave Harris) wrote:
jaibudu...@gmail.com (Le Chaud Lapin) wrote (abridged):
I guess by "XML-to-object-to-XML people" you mean the ones who want to
generate the XML automatically. If so, that is a rather misleading way to
refer to them. You can attempt to generate data automatically without
using XML, and you can also use XML without automated generation.
True.
Java can be compiled directly to machine code - it doesn't need a JVM.
Certainly automatically generating XML does not require a full JVM-like
runtime. It just needs the compiler to include a description of the
program's types in the executable. Doing so wouldn't make a language less
general purpose.
I'm not sure what you have in mind here. My approach led to code like:
enum Colour { Black, Red, Green, Blue, White };
....
Colour faciaColour;
LoadEnum( pXml, L"facia", faciaColour, White );
which seems tidy enough. There is code that does run-time interpretation
of string values, but it's in a library somewhere and doesn't add to the
mess in client code. Unexpected strings get ignored, and missing strings
get their default values (White in this case).
Ok, this last sentence, "Unexpected strings get ignored, and missing
strings get their default values (White in this case)." is very
important, and touches on the thesis of pretty much all my
philosophical posts in this group:
The engineer must exercise specificity at some point. <<<
Here you've exercised it. You decided beforehand that missing strings
get their default values. You've also implicitly decided that extra
strings get ignored.
Note that, in your case, because you have said, in advance, that it's
ok that strings can be missing, there is no issue. But there are many
situations where XML will model a C++ object on disk, and if someone
were to "version" the XML and add and extra field, the C++ importation
code would not be able to cope, or rather, "coping" would be a very
bad idea. There must then be either:
1. A policy stipulating that extra fields are simply ignored.
2. Exception thrown.
There are some people (not you) who would actually say just ignore any
extra fields as a rule. C++ objects representing missile launchers
might not appreciate this rule.
This same problem happens with versioning in binary serialization.
People say that the objects are versioned, but that's not really
what's happening. What's happening is that a new type is being
formed. If a target T of serialization receives an object from source
S, and T is not expecting the new "version" of the object that S sent,
then what? Exception? Take what you can and discard the rest? What if
the new object is 3 times the size of the original object? When is the
disparity too great to ignore? The computer cannot know - it cannot
think. The programemr will have to tel it.."Throw an exception for
even the minutest disparity" or "Just ignore and move on." There is no
real gray area. Whatever the computer does, a programmer will have
told it to do that, whether purposely, or not.
It becomes less clean as the data evolves, leading to things like:
ColourObject *pFaciaColour;
if (!LoadObject( pXml, L"facia2", pFaciaColour, White )) {
Colour faciaColour;
LoadEnum( pXml, L"facia", faciaColour, White );
pFaciaColour = new EnumColour( faciaColour );
}
where the original enum type has been replaced by a heirarchy of classes
that provide different colour models - RGB, CMYK etc. The serialisation
code first looks for the new format, and if it can't find it then looks
for the old format and converts it.
Do you think this is too rigid and will "quickly disintegrate"?
No, the problem is often that it is too flexible.
I wrote post in this group, long ago, about about rigidity being the
foundation of flexibility. Lack of rigidity (concrete classes) means
broken assignment, broken default construction, etc (or weird and
tedious at best).
You're using a simple colour object here. But more complex object
will make more complex hierarchical XML. And one of the things that
the XML fanatics (not you) espouse is the interchangeability of the
XML data file.
I am not referring to the encoding being ASCII strings to be
interpreted. I am going to demonstrate in a moment how I would do the
ASCII human-readability part in C++ only. I am talking about the
people who use the phrase..."it consumes XML objects"
These individuals speak as if the XML file can float around in
cyberspace from company to company, changing as it wishes, and each
company will be able to have C++ objects that yield themselves from it
automagically.
This is not true.
If one company adds a single field, and you have not specified the
"missing values get ignored" stipulation _up front_, all bets are
off. It's a recipe for nightmare.
If you _do_ specify that wrongfully absent or present values get
ignored, then you do not need XML, you only need C++:
struct ChaudLapinPseudoXML : Asscociative_Polyarchy <String,
Associative_Set<String, List<String> > >
{
} ;
Notes:
1. An Associative_Polyarchy is nothing more than the tree equivalent
of std:map<>.
2. An Associative_Set is the equivalent of std:map<>
Note here, that everything in this data structure is a string or list
of strings. You can do a lookup in it, given the path to a node, and
once the value is found (List<String>), do your conversions.
Conversions can be done either by hand each time or using library.
The key here is that there is no magic. You've bitten the bullet and
said, "I'm going to be doing a lot of string conversions
(intepretations)." This is not the same as what the OP might like -
to load arbitrary objects off disk as Java would, and I do not mean
the code of the objects, but the arbitary state structure.
In any case, my structure too, would be portable, and with the "ignore
unexpected rule"..., companies could do whatever they wanted and it
would be unbreakable..because the form, the *type*, is pre-specified,
and unchangeable "an associative polyarchy maping string to
asscociative set mapping string to list of string". New "fields" could
come and go because of the "ignore unexpected" rule.
You cannot do this with any arbitrary C++ object and XML because
changing an field changes the type, and it is not prudent to prescribe
ignorance up front because motivation for the new field (new type)
cannot be known in advance.
So in summary, if you are using XML as a hierarchical data store of
intepretable strings that will be interpreted as state separate from
the state of object itself, that's fine. If you are using it to model
the actual structure of C++ objects, the XML must remain rigid in
type, or there will be a mess during "interoperability".
-Le Chaud Lapin-
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]