[xsd-users] schema => simple print program, need walkthrough

Boris Kolpackov boris at codesynthesis.com
Fri Dec 21 08:48:36 EST 2007


Hi Rutger,

Rutger Vos <rutgeraldo at gmail.com> writes:

> The schema I'm working with is this one:
> http://www.nexml.org/nexml/xsd/ .

If you can create a .tar.gz archive of all the schemas so that I
can download all of them in one go, then I could give it try and
maybe even create a small test driver for you.

> * csxsd doesn't download remote schema files, so I've downloaded the
> schemas I import (the xml and xlink namespaces) and reference them
> locally, they're in the external/ folder.

In the next version of XSD[1], there will be support for re-mapping
the remote locations of imported/included schemas without changing
the importing/including schemas.


> * csxsd doesn't follow inclusions itself, you need to tell it
> explicitly from which schema files to generate code

Yes, XSD follows the so-called separate compilation model. The next
version[1] will also support the file-per-type compilation model
which will generate all the code from one schema.


> * csxsd - or actually gcc when I try to compile - doesn't like cycles
> in schema inclusions (and hence generated code?), so I've broken them
> to create an acyclic inclusion tree

The generated code can handle cycles as long as they don't involve
inheritance. If there is inheritance involved then you will need
to either get rid of the cycle or use the file-per-type compilation
model mentioned above.


> With those things taken into account, I generate code as follows:
>
> * I make a list of all schema files I will be working with, i.e. in
> shell I do files=$(find . -name "*.xsd") out of which I "grep -v" the
> files that aren't reached by the inclusions starting from nexml.xsd
> (e.g. the "draft1" folder)
>
> * because the schema files are organized in a folder structure (see
> inclusions graph) I assume I will be happiest if the generated code
> ends up in a similar folder structure, so I loop over each $file in
> $files and modify the string to get $outdir, such that for file
> ./characters/dna.xsd $outdir is characters/
>
> * I then run csxsd for each schema file with the following incantation:
>
> ./xsd cxx-tree --namespace-map http://www.nexml.org/1.0=Nexml \
> --generate-polymorphic --output-dir ./out/$outdir $file

Sounds good. Can you perhaps also make available the script that does
all this so that I don't need to reinvent it?


> * however, to make my print program, I understand I should also
> generate parser code (right?), so I also run:
>
> ./xsd cxx-parser --namespace-map http://www.nexml.org/1.0=Nexml \
> --generate-print-impl --output-dir ./out/$outdir $file

No, you don't need to do this. The generated C++/Tree code (cxx-tree)
already has the parsing functionality. C++/Parser is a different kind
of XML Schema to C++ mapping (event-driven as opposed to in-memory,
similar to how SAX and DOM are different).


> * because there is a single root element, which is defined in
> nexml.xsd, I need to generate a test driver from that schema file, so
> I do:
>
> ./xsd cxx-parser  --namespace-map http://www.nexml.org/1.0=Nexml
> --root-element nexml \
> --output-dir ./out --generate-print-impl --force-overwrite
> --generate-test-driver ../../nexml/xsd/nexml.xsd

Again, you can't do this with C++/Tree. Automatic generation of
the test driver implementation is only available in the C++/Parser
mapping.

What you can do with the C++/Tree mapping is to add the
--generate-ostream option to the 'xsd cxx-tree ...' command line.
This will result in std::ostream insertion operators (operator<<)
being generated for each C++ class. Then you can create a simple
test driver for your schema:

#include <memory>
#include <iostream>

#include "nexml.xsd"

using namespace std;

int
main (int argc, char* argv[])
{
  try
  {
    auto_ptr<Nexml::Nexml> root (Nexml::nexml (argv[1]));

    cout << *root << endl;
  }
  catch (const xml_schema::exception& e)
  {
    cerr << e << endl;
    return 1;
  }
}

The only problem in the above test driver is that you schemas
use polymorphism (xsi:type) while the generated std::ostream
insertion operators are not polymorphism-aware and will only
print the date from the base type. But this should at least
get you started.

BTW, in case you haven't read it, I suggest that you take a look
at the C++/Tree Mapping Getting Started Guide, at least the
"Hello World" chapter of it:

http://codesynthesis.com/projects/xsd/documentation/cxx/tree/guide/

[1] You can start using these features before the release by getting
    the pre-release binaries which are available for GNU/Linux and
    Windows:

    http://codesynthesis.com/~boris/tmp/xsd-3.1.0.a5-i686-linux-gnu.tar.bz2
    http://codesynthesis.com/~boris/tmp/xsd-3.1.0.a5-i686-windows.zip


Boris




More information about the xsd-users mailing list