summaryrefslogtreecommitdiff
path: root/examples/cxx/tree/custom/taxonomy
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-09-17 07:15:29 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-09-17 07:15:29 +0200
commitf0510d2f90467de8e8f260b47d79a9baaf9bef17 (patch)
tree0b9929946f06a9cbe9b9e8f2a7600dae4e048f79 /examples/cxx/tree/custom/taxonomy
Start tracking XSD with git
Diffstat (limited to 'examples/cxx/tree/custom/taxonomy')
-rw-r--r--examples/cxx/tree/custom/taxonomy/README50
-rw-r--r--examples/cxx/tree/custom/taxonomy/driver.cxx39
-rw-r--r--examples/cxx/tree/custom/taxonomy/makefile82
-rw-r--r--examples/cxx/tree/custom/taxonomy/people-custom-fwd.hxx20
-rw-r--r--examples/cxx/tree/custom/taxonomy/people-custom.cxx180
-rw-r--r--examples/cxx/tree/custom/taxonomy/people-custom.hxx103
-rw-r--r--examples/cxx/tree/custom/taxonomy/people.xml27
-rw-r--r--examples/cxx/tree/custom/taxonomy/people.xsd45
8 files changed, 546 insertions, 0 deletions
diff --git a/examples/cxx/tree/custom/taxonomy/README b/examples/cxx/tree/custom/taxonomy/README
new file mode 100644
index 0000000..addce83
--- /dev/null
+++ b/examples/cxx/tree/custom/taxonomy/README
@@ -0,0 +1,50 @@
+This example shows how to map user-defined XML Schema types to custom C++
+classes. It presents the complex case where the customized types are
+inherited from in the same schema. For the simple case see the contacts
+example. For more information on the C++/Tree mapping customization see
+the C++/Tree Mapping Customization Guide[1].
+
+[1] http://wiki.codesynthesis.com/Tree/Customization_guide
+
+The example consists of the following files:
+
+people.xsd
+ XML Schema definition for a simple people database.
+
+people.xml
+ Sample XML instance document.
+
+people-fwd.hxx
+people.hxx
+people.ixx
+people.cxx
+ C++ types that represent the given vocabulary and a set of parsing
+ functions that convert XML instance documents to a tree-like in-memory
+ object model. These are generated by XSD from people.xsd with the
+ --custom-type option in order to to customize the person, superman,
+ and batman types. Generation of the people-fwd.hxx forward declaration
+ file is requested with the --generate-forward option.
+
+people-custom-fwd.hxx
+ Header file which forward-declares our own person, superman, and batman
+ as class templates. It is included at the beginning of people-fwd.hxx
+ using the --fwd-prologue option.
+
+people-custom.hxx
+ Header file which defines our own person, superman, and batman class
+ templates by inheriting from the generated person_base, superman_base,
+ and batman_base. It is included at the beginning of people.hxx using
+ the --hxx-prologue option.
+
+people-custom.cxx
+ Source file which contains the implementations and instantiations of
+ our person, superman, and batman class templates.
+
+driver.cxx
+ Driver for the example. It first calls one of the parsing functions
+ that constructs the object model from the input file. It then prints
+ the database to STDERR.
+
+To run the example on the sample XML instance document simply execute:
+
+$ ./driver people.xml
diff --git a/examples/cxx/tree/custom/taxonomy/driver.cxx b/examples/cxx/tree/custom/taxonomy/driver.cxx
new file mode 100644
index 0000000..f102fc3
--- /dev/null
+++ b/examples/cxx/tree/custom/taxonomy/driver.cxx
@@ -0,0 +1,39 @@
+// file : examples/cxx/tree/custom/taxonomy/driver.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <memory> // std::auto_ptr
+#include <iostream>
+
+#include "people.hxx"
+
+using std::cerr;
+using std::endl;
+
+int
+main (int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ cerr << "usage: " << argv[0] << " people.xml" << endl;
+ return 1;
+ }
+
+ try
+ {
+ using namespace people;
+
+ std::auto_ptr<catalog> c (catalog_ (argv[1]));
+
+ for (catalog::person_const_iterator i (c->person ().begin ());
+ i != c->person ().end (); ++i)
+ {
+ i->print (cerr);
+ }
+ }
+ catch (const xml_schema::exception& e)
+ {
+ cerr << e << endl;
+ return 1;
+ }
+}
diff --git a/examples/cxx/tree/custom/taxonomy/makefile b/examples/cxx/tree/custom/taxonomy/makefile
new file mode 100644
index 0000000..a5fa4a3
--- /dev/null
+++ b/examples/cxx/tree/custom/taxonomy/makefile
@@ -0,0 +1,82 @@
+# file : examples/cxx/tree/custom/taxonomy/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../../build/bootstrap.make
+
+xsd := people.xsd
+cxx := driver.cxx people-custom.cxx
+
+obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=.o))
+dep := $(obj:.o=.o.d)
+
+driver := $(out_base)/driver
+clean := $(out_base)/.clean
+
+
+# Import.
+#
+$(call import,\
+ $(scf_root)/import/libxerces-c/stub.make,\
+ l: xerces_c.l,cpp-options: xerces_c.l.cpp-options)
+
+
+# Build.
+#
+$(driver): $(obj) $(xerces_c.l)
+
+$(obj) $(dep): cpp_options := -I$(src_root)/libxsd
+$(obj) $(dep): $(xerces_c.l.cpp-options)
+
+$(out_base)/$(xsd:.xsd=.hxx) \
+$(out_base)/$(xsd:.xsd=.ixx) \
+$(out_base)/$(xsd:.xsd=.cxx): xsd := $(out_root)/xsd/xsd
+
+# We have to double-escape '#' because the message function
+# (which is used in command scripts) expands things twice.
+#
+$(out_base)/$(xsd:.xsd=.hxx) \
+$(out_base)/$(xsd:.xsd=.ixx) \
+$(out_base)/$(xsd:.xsd=.cxx): xsd_options := \
+--generate-inline \
+--generate-forward \
+--generate-polymorphic \
+--custom-type "person=person_impl<person_base>/person_base" \
+--custom-type "superman=superman_impl<superman_base>/superman_base" \
+--custom-type "batman=batman_impl<batman_base>/batman_base" \
+--fwd-prologue '\\\#include "people-custom-fwd.hxx"' \
+--hxx-prologue '\\\#include "people-custom.hxx"'
+
+$(out_base)/$(xsd:.xsd=.hxx) \
+$(out_base)/$(xsd:.xsd=.ixx) \
+$(out_base)/$(xsd:.xsd=.cxx): $(out_root)/xsd/xsd
+
+$(call include-dep,$(dep))
+
+# Convenience alias for default target.
+#
+.PHONY: $(out_base)/
+$(out_base)/: $(driver)
+
+
+# Clean.
+#
+.PHONY: $(clean)
+
+$(clean): $(driver).o.clean \
+ $(addsuffix .cxx.clean,$(obj)) \
+ $(addsuffix .cxx.clean,$(dep)) \
+ $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
+$(call include,$(scf_root)/xsd/tree/xsd-cxx.make)
+
+# Dependencies.
+#
+$(call import,$(src_root)/xsd/makefile)
diff --git a/examples/cxx/tree/custom/taxonomy/people-custom-fwd.hxx b/examples/cxx/tree/custom/taxonomy/people-custom-fwd.hxx
new file mode 100644
index 0000000..973b6e5
--- /dev/null
+++ b/examples/cxx/tree/custom/taxonomy/people-custom-fwd.hxx
@@ -0,0 +1,20 @@
+// file : examples/cxx/tree/custom/taxonomy/people-custom-fwd.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+// Do not include this file directly, use people-fwd.hxx instead. This
+// file is included into generated people-fwd.hxx so we do not need to
+// guard against multiple inclusions.
+//
+
+namespace people
+{
+ template <typename base>
+ class person_impl;
+
+ template <typename base>
+ class superman_impl;
+
+ template <typename base>
+ class batman_impl;
+}
diff --git a/examples/cxx/tree/custom/taxonomy/people-custom.cxx b/examples/cxx/tree/custom/taxonomy/people-custom.cxx
new file mode 100644
index 0000000..14c7087
--- /dev/null
+++ b/examples/cxx/tree/custom/taxonomy/people-custom.cxx
@@ -0,0 +1,180 @@
+// file : examples/cxx/tree/custom/taxonomy/people-custom.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+#include <ostream>
+
+// Include people.hxx instead of people-custom.hxx here.
+//
+#include "people.hxx"
+
+namespace people
+{
+ // person_impl
+ //
+ template <typename base>
+ person_impl<base>::
+ person_impl (const xml_schema::string& name)
+ : base (name)
+ {
+ }
+
+ template <typename base>
+ person_impl<base>::
+ person_impl (std::auto_ptr<xml_schema::string>& name)
+ : base (name)
+ {
+ }
+
+ template <typename base>
+ person_impl<base>::
+ person_impl (const xercesc::DOMElement& e,
+ xml_schema::flags f,
+ xml_schema::container* c)
+ : base (e, f, c)
+ {
+ }
+
+ template <typename base>
+ person_impl<base>::
+ person_impl (const person_impl& p,
+ xml_schema::flags f,
+ xml_schema::container* c)
+ : base (p, f, c)
+ {
+ }
+
+ template <typename base>
+ person_impl<base>* person_impl<base>::
+ _clone (xml_schema::flags f, xml_schema::container* c) const
+ {
+ return new person_impl (*this, f, c);
+ }
+
+ template <typename base>
+ void person_impl<base>::
+ print (std::ostream& os) const
+ {
+ os << this->name () << std::endl;
+ }
+
+ // Explicitly instantiate person_impl class template for person_base.
+ //
+ template class person_impl<person_base>;
+
+
+ // superman_impl
+ //
+ template <typename base>
+ superman_impl<base>::
+ superman_impl (const xml_schema::string& name, bool can_fly)
+ : base (name, can_fly)
+ {
+ }
+
+ template <typename base>
+ superman_impl<base>::
+ superman_impl (std::auto_ptr<xml_schema::string>& name, bool can_fly)
+ : base (name, can_fly)
+ {
+ }
+
+ template <typename base>
+ superman_impl<base>::
+ superman_impl (const xercesc::DOMElement& e,
+ xml_schema::flags f,
+ xml_schema::container* c)
+ : base (e, f, c)
+ {
+ }
+
+ template <typename base>
+ superman_impl<base>::
+ superman_impl (const superman_impl& s,
+ xml_schema::flags f,
+ xml_schema::container* c)
+ : base (s, f, c)
+ {
+ }
+
+ template <typename base>
+ superman_impl<base>* superman_impl<base>::
+ _clone (xml_schema::flags f, xml_schema::container* c) const
+ {
+ return new superman_impl (*this, f, c);
+ }
+
+ template <typename base>
+ void superman_impl<base>::
+ print (std::ostream& os) const
+ {
+ if (this->can_fly ())
+ os << "Flying superman ";
+ else
+ os << "Superman ";
+
+ os << this->name () << std::endl;
+ }
+
+ // Explicitly instantiate superman_impl class template for superman_base.
+ //
+ template class superman_impl<superman_base>;
+
+
+ // batman_impl
+ //
+ template <typename base>
+ batman_impl<base>::
+ batman_impl (const xml_schema::string& name,
+ bool can_fly,
+ unsigned int wing_span)
+ : base (name, can_fly, wing_span)
+ {
+ }
+
+ template <typename base>
+ batman_impl<base>::
+ batman_impl (std::auto_ptr<xml_schema::string>& name,
+ bool can_fly,
+ unsigned int wing_span)
+ : base (name, can_fly, wing_span)
+ {
+ }
+
+ template <typename base>
+ batman_impl<base>::
+ batman_impl (const xercesc::DOMElement& e,
+ xml_schema::flags f,
+ xml_schema::container* c)
+ : base (e, f, c)
+ {
+ }
+
+ template <typename base>
+ batman_impl<base>::
+ batman_impl (const batman_impl& s,
+ xml_schema::flags f,
+ xml_schema::container* c)
+ : base (s, f, c)
+ {
+ }
+
+ template <typename base>
+ batman_impl<base>* batman_impl<base>::
+ _clone (xml_schema::flags f, xml_schema::container* c) const
+ {
+ return new batman_impl (*this, f, c);
+ }
+
+ template <typename base>
+ void batman_impl<base>::
+ print (std::ostream& os) const
+ {
+ os << "Batman " << this->name () << " with " <<
+ this->wing_span () << "m wing span" << std::endl;
+ }
+
+ // Explicitly instantiate batman_impl class template for batman_base.
+ //
+ template class batman_impl<batman_base>;
+}
diff --git a/examples/cxx/tree/custom/taxonomy/people-custom.hxx b/examples/cxx/tree/custom/taxonomy/people-custom.hxx
new file mode 100644
index 0000000..23e7731
--- /dev/null
+++ b/examples/cxx/tree/custom/taxonomy/people-custom.hxx
@@ -0,0 +1,103 @@
+// file : examples/cxx/tree/custom/taxonomy/people-custom.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : not copyrighted - public domain
+
+// Do not include this file directly, use people.hxx instead. This
+// file is included into generated people.hxx so we do not need to
+// guard against multiple inclusions.
+//
+
+#include <iosfwd> // std::ostream
+
+// Include people-fwd.hxx here so that we can refer to the generated
+// types.
+//
+#include "people-fwd.hxx"
+
+namespace people
+{
+ //
+ //
+ template <typename base>
+ class person_impl: public base
+ {
+ public:
+ person_impl (const xml_schema::string& name);
+ person_impl (std::auto_ptr<xml_schema::string>& name);
+
+ person_impl (const xercesc::DOMElement&,
+ xml_schema::flags = 0,
+ xml_schema::container* = 0);
+
+ person_impl (const person_impl&,
+ xml_schema::flags = 0,
+ xml_schema::container* = 0);
+
+ virtual person_impl*
+ _clone (xml_schema::flags = 0,
+ xml_schema::container* = 0) const;
+
+ public:
+ virtual void
+ print (std::ostream&) const;
+ };
+
+
+ //
+ //
+ template <typename base>
+ class superman_impl: public base
+ {
+ public:
+ superman_impl (const xml_schema::string& name, bool can_fly);
+ superman_impl (std::auto_ptr<xml_schema::string>& name, bool can_fly);
+
+ superman_impl (const xercesc::DOMElement&,
+ xml_schema::flags = 0,
+ xml_schema::container* = 0);
+
+ superman_impl (const superman_impl&,
+ xml_schema::flags = 0,
+ xml_schema::container* = 0);
+
+ virtual superman_impl*
+ _clone (xml_schema::flags = 0,
+ xml_schema::container* = 0) const;
+
+ public:
+ virtual void
+ print (std::ostream&) const;
+ };
+
+
+ //
+ //
+ template <typename base>
+ class batman_impl: public base
+ {
+ public:
+ batman_impl (const xml_schema::string& name,
+ bool can_fly,
+ unsigned int wing_span);
+
+ batman_impl (std::auto_ptr<xml_schema::string>& name,
+ bool can_fly,
+ unsigned int wing_span);
+
+ batman_impl (const xercesc::DOMElement&,
+ xml_schema::flags = 0,
+ xml_schema::container* = 0);
+
+ batman_impl (const batman_impl&,
+ xml_schema::flags = 0,
+ xml_schema::container* = 0);
+
+ virtual batman_impl*
+ _clone (xml_schema::flags = 0,
+ xml_schema::container* = 0) const;
+
+ public:
+ virtual void
+ print (std::ostream&) const;
+ };
+}
diff --git a/examples/cxx/tree/custom/taxonomy/people.xml b/examples/cxx/tree/custom/taxonomy/people.xml
new file mode 100644
index 0000000..5f84855
--- /dev/null
+++ b/examples/cxx/tree/custom/taxonomy/people.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/tree/custom/taxonomy/people.xml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<ppl:catalog xmlns:ppl="http://www.codesynthesis.com/people"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.codesynthesis.com/people people.xsd">
+
+ <person>
+ <name>Joe Dirt</name>
+ </person>
+
+ <person xsi:type="ppl:superman" can-fly="false">
+ <name>James "007" Bond</name>
+ </person>
+
+ <person xsi:type="ppl:batman" can-fly="true" wing-span="10">
+ <name>Bruce Wayne</name>
+ </person>
+
+</ppl:catalog>
diff --git a/examples/cxx/tree/custom/taxonomy/people.xsd b/examples/cxx/tree/custom/taxonomy/people.xsd
new file mode 100644
index 0000000..c77a866
--- /dev/null
+++ b/examples/cxx/tree/custom/taxonomy/people.xsd
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : examples/cxx/tree/custom/taxonomy/people.xsd
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:ppl="http://www.codesynthesis.com/people"
+ targetNamespace="http://www.codesynthesis.com/people">
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="superman">
+ <xsd:complexContent>
+ <xsd:extension base="ppl:person">
+ <xsd:attribute name="can-fly" type="xsd:boolean" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="batman">
+ <xsd:complexContent>
+ <xsd:extension base="ppl:superman">
+ <xsd:attribute name="wing-span" type="xsd:unsignedInt" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="catalog">
+ <xsd:sequence>
+ <xsd:element name="person" type="ppl:person" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="catalog" type="ppl:catalog"/>
+
+</xsd:schema>