|
|
XML-System
Why?
XML is the core of SDS, and SDS currently use four XML formats to
represent information. A framework for making it easy to utilise XML
is then necessary. Such a framework has been built which takes care
of (but might be extended):
- reading and parsing xml-files
- building trees of the various elements of the xml data
- making it easy to access and update the trees
- allow easy building of such trees from other sources
- dump such trees to a new xml-file which might be parsed again
This functionality is split into two parts: an xml-module and a
API-generator. The xml-module provides the raw functionality needed
to work with xml, ie reading and dumping. The API-generator reads a
specification and generates the correct classes and the glue code
between the generated classes and the xml-module. Both the xml-module
and the generated api is specific for a language, e.g C++, but the
specification is used for all languages. This means that the same API
is available in all languages which the XML-system has been ported to,
currently C++, Java and Common Lisp. This saves a lot of work and
maintenance and makes it trivial to create a new dataformat in XML
which is instantly usable in several languages. To prove the point,
the API-specifications are in XML and the API-generator's API is of
course created by the API-generator (ie a bootstrap).
More on the APIs
The apis directory contains specifications for the various
APIs which use the XML-system. An API is common in several languages
and should be specified here and not be hand-written. Adding support
for new languages is not too difficult, and examples for C++, Java and
Common Lisp exist. The API-Generator will generate only the front-end
and simple code for using the xml-system. The actual functionality of
your tool must still be written :-)
C++ xml-system
- include/abstract.H - Has the ABC XML_Parseable which has to be
the parent of any XML-"serializable" class. Just as important is the
XML_Factory class which must be subclassed for your dtd/"domain" (e.g
CSF, Prefs) and used with XML_Tool.
- include/xml/tools.H - Most communication when dumping and
reading xml will go through this class.
- include/xml/infotype.H - The classes here are simple wrappers of
information which should be set to the attrInfo and subelemInfo
members in XML_Parseable.
I guess that currently only the PTR_TO
macro is useful for a "normal" developer. Use it as in normal code,
e.g src/csf/class.cpp. Only if you decide to hack
xmltool.cpp you should check out the other macros. Use the macros when setting
and getting variables to let xmltool.cpp survive when stuff is
changed. The system used is particularly nasty and may not work on
all compilers.
And remember:
- Good examples of more or less complex classes which are mapped
to one or more elements are found in the csf and prefs
directories. Both these directories have their own factories and
small testprograms to show how they're utilised from above.
- If you want the data from a XML_ParseablePtr you should use the
get() function to get a pointer which you can cast to the appropriate
type. If it's a multi-type list, you should do a conditional on
getElementName(). The whole system is what it is because of C++'s fascist
typing. Compare it with the Lisp-code...
- The XML behaviour can be overrided, and sometimes this is necessary. A
special case which is supported by XML_Parseable::printAsXML is when
several subelemInfos point to the same memory-area. The system then
assumes that you only want the content in that list (usually is a
list) listed once and not once for every subelement
registered to that memory location. Check the CSF_API class which
maps several elements to the same list but where content is only
printed once. A very hackish special case, but is very useful in
SDOC.
- All XML_Parseable derived classes which can be instantiated
needs a copy() function. Usually this returns a new version of the
class, using the copy-constructor and should be trivial to
add. REMEMBER that the XML_ParseablePtr is a wrapped pointer
(Ptr_Wrap) which
takes care of calling copy() so you don't really need to mess with an
assignment-operator and a copy-constructor, and
destructors become trivial as the XML_ParseablePtr cleans up after
itself. The pointer-wrapping saves a lot of code and complexity in
most classes, and basically all the complexity is reduced to
xmltool.cpp and functions which manipulate pointers. Macros will
probably show up soon.
- The XML_Parseable class will take care of deleting attrInfo and
subelemInfo. Actually Sarray does this by itself..
CL/CLOS xml-system
Most of the CLOS system for XML seems to be working quite well and
uses more or less the same naming and classes as the C++ code. Most of
what is said above also applies to the CLOS implementation, except for
the XML_ParseablePtr which isn't needed (lists are used all over the
place to save space). It has
however gone through some lispification (use of '-' instead of '_' in
names and constants have been put in +..+). Heavier use of neat macros
were inevitable and reduces the code size to 1/4 of the equivalent c++
code.
|