summaryrefslogtreecommitdiff
path: root/xsd-examples/cxx/parser/polyroot
diff options
context:
space:
mode:
Diffstat (limited to 'xsd-examples/cxx/parser/polyroot')
-rw-r--r--xsd-examples/cxx/parser/polyroot/README36
-rw-r--r--xsd-examples/cxx/parser/polyroot/batman.xml16
-rw-r--r--xsd-examples/cxx/parser/polyroot/buildfile24
-rw-r--r--xsd-examples/cxx/parser/polyroot/driver.cxx138
-rw-r--r--xsd-examples/cxx/parser/polyroot/person.xml15
-rw-r--r--xsd-examples/cxx/parser/polyroot/superman.xml16
-rw-r--r--xsd-examples/cxx/parser/polyroot/supermen-pimpl.cxx85
-rw-r--r--xsd-examples/cxx/parser/polyroot/supermen-pimpl.hxx64
-rw-r--r--xsd-examples/cxx/parser/polyroot/supermen.xsd36
-rw-r--r--xsd-examples/cxx/parser/polyroot/testscript6
10 files changed, 436 insertions, 0 deletions
diff --git a/xsd-examples/cxx/parser/polyroot/README b/xsd-examples/cxx/parser/polyroot/README
new file mode 100644
index 0000000..f41b91c
--- /dev/null
+++ b/xsd-examples/cxx/parser/polyroot/README
@@ -0,0 +1,36 @@
+This example shows how to handle the xsi:type attributes when it is used
+on root elements. For general coverage of XML Schema polymorphism handling
+in the C++/Parser mapping see the polymorphism example.
+
+The example consists of the following files:
+
+supermen.xsd
+ XML Schema which describes the "supermen" instance documents.
+
+person.xml
+superman.xml
+batman.xml
+ Sample XML instance documents.
+
+supermen-pskel.hxx
+supermen-pskel.cxx
+ Parser skeletons generated by the XSD compiler from supermen.xsd.
+ Note the use of the --generate-polymorphic command line option.
+
+supermen-pimpl.hxx
+supermen-pimpl.cxx
+ Parser implementations that print the XML data to STDOUT.
+
+driver.cxx
+ Driver for the example. It implements a custom document parser
+ that determines which XML Schema type is being parsed and uses
+ the corresponding parser implementation. The driver first
+ constructs a parser instance from all the individual parsers
+ found in supermen-pimpl.hxx. In then invokes this parser instance
+ to parse the input file.
+
+To run the example on the sample XML instance documents simply execute:
+
+$ ./driver person.xml
+$ ./driver superman.xml
+$ ./driver batman.xml
diff --git a/xsd-examples/cxx/parser/polyroot/batman.xml b/xsd-examples/cxx/parser/polyroot/batman.xml
new file mode 100644
index 0000000..600ad6f
--- /dev/null
+++ b/xsd-examples/cxx/parser/polyroot/batman.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : cxx/parser/polyroot/batman.xml
+copyright : not copyrighted - public domain
+
+-->
+
+<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="supermen.xsd"
+ xsi:type="batman" can-fly="true" wing-span="10">
+
+ <name>Bruce Wayne</name>
+
+</person>
diff --git a/xsd-examples/cxx/parser/polyroot/buildfile b/xsd-examples/cxx/parser/polyroot/buildfile
new file mode 100644
index 0000000..6ae0fdc
--- /dev/null
+++ b/xsd-examples/cxx/parser/polyroot/buildfile
@@ -0,0 +1,24 @@
+# file : cxx/parser/polyroot/buildfile
+# license : not copyrighted - public domain
+
+import libs = libxsd%lib{xsd}
+import libs += libxerces-c%lib{xerces-c}
+
+./: exe{driver} doc{README} xml{batman person superman}
+
+exe{driver}: {hxx cxx}{* -supermen-pskel} {hxx ixx cxx}{supermen-pskel} $libs \
+ testscript
+
+<{hxx ixx cxx}{supermen-pskel}>: xsd{supermen} $xsd
+{{
+ diag xsd ($<[0]) # @@ TMP
+
+ $xsd cxx-parser --std c++11 \
+ --generate-inline \
+ --skel-file-suffix -pskel \
+ --generate-polymorphic \
+ --output-dir $out_base \
+ $path($<[0])
+}}
+
+cxx.poptions =+ "-I$out_base" "-I$src_base"
diff --git a/xsd-examples/cxx/parser/polyroot/driver.cxx b/xsd-examples/cxx/parser/polyroot/driver.cxx
new file mode 100644
index 0000000..986c8c0
--- /dev/null
+++ b/xsd-examples/cxx/parser/polyroot/driver.cxx
@@ -0,0 +1,138 @@
+// file : cxx/parser/polyroot/driver.cxx
+// copyright : not copyrighted - public domain
+
+#include <map>
+#include <string>
+#include <iostream>
+
+#include "supermen-pimpl.hxx"
+
+using std::cerr;
+using std::endl;
+using xml_schema::ro_string;
+
+// Customize the xml_schema::document object to handle polymorphic
+// root element. For more information see the multiroot example.
+//
+class document: public xml_schema::document
+{
+public:
+ document (const xml_schema::parser_map& parser_map)
+ : xml_schema::document (true), // Indicate polymorphic parsing.
+ parser_map_ (parser_map)
+ {
+ }
+
+protected:
+ // This function is called to obtain the root element type parser.
+ // If the returned pointer is 0 then the whole document content
+ // is ignored. The type argument contains the XML Schema type
+ // if xsi:type attribute was specified for this element and 0
+ // otherwise.
+ //
+ virtual xml_schema::parser_base*
+ start_root_element (const ro_string& ns,
+ const ro_string& name,
+ const ro_string* type)
+ {
+ if (name != "person" || !ns.empty ())
+ return 0;
+
+ xml_schema::parser_base* base;
+
+ // Search the parser map.
+ //
+ if (type == 0)
+ {
+ // No xsi:type. Static type should be used.
+ //
+ ro_string st (person_pskel::_static_type ());
+ base = parser_map_.find (st);
+ }
+ else
+ {
+ base = parser_map_.find (*type);
+ }
+
+ if (base != 0)
+ {
+ parser_used_ = dynamic_cast<person_pskel*> (base);
+ parser_used_->pre ();
+ }
+ else
+ parser_used_ = 0; // No parser for this type.
+
+ return parser_used_;
+ }
+
+ // This function is called to indicate the completion of document
+ // parsing. The parser argument contains the pointer returned by
+ // start_root_element.
+ //
+ virtual void
+ end_root_element (const ro_string& /* ns */,
+ const ro_string& /* name */,
+ xml_schema::parser_base* /* parser */)
+ {
+ // Instead of caching the current parser in parser_used_, we
+ // could also dynamic_cast the parser argument to the person_pskel
+ // type.
+ //
+ if (parser_used_)
+ parser_used_->post_person ();
+ }
+
+
+private:
+ const xml_schema::parser_map& parser_map_;
+ person_pskel* parser_used_;
+};
+
+int
+main (int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ cerr << "usage: " << argv[0] << " instance.xml" << endl;
+ return 1;
+ }
+
+ try
+ {
+ // Construct the parser.
+ //
+ xml_schema::string_pimpl string_p;
+ xml_schema::boolean_pimpl boolean_p;
+ xml_schema::unsigned_int_pimpl unsigned_int_p;
+
+ person_pimpl person_p;
+ superman_pimpl superman_p;
+ batman_pimpl batman_p;
+
+ person_p.parsers (string_p);
+ superman_p.parsers (string_p, boolean_p);
+ batman_p.parsers (string_p, boolean_p, unsigned_int_p);
+
+ // Parse the XML document.
+ //
+ xml_schema::parser_map_impl person_map;
+
+ person_map.insert (person_p);
+ person_map.insert (superman_p);
+ person_map.insert (batman_p);
+
+ document doc_p (person_map);
+
+ doc_p.parse (argv[1]);
+ }
+ catch (const xml_schema::exception& e)
+ {
+ cerr << e << endl;
+ return 1;
+ }
+ catch (const std::ios_base::failure&)
+ {
+ cerr << argv[1] << ": unable to open or read failure" << endl;
+ return 1;
+ }
+}
diff --git a/xsd-examples/cxx/parser/polyroot/person.xml b/xsd-examples/cxx/parser/polyroot/person.xml
new file mode 100644
index 0000000..2182457
--- /dev/null
+++ b/xsd-examples/cxx/parser/polyroot/person.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : cxx/parser/polyroot/person.xml
+copyright : not copyrighted - public domain
+
+-->
+
+<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="supermen.xsd">
+
+ <name>John Doe</name>
+
+</person>
diff --git a/xsd-examples/cxx/parser/polyroot/superman.xml b/xsd-examples/cxx/parser/polyroot/superman.xml
new file mode 100644
index 0000000..97dbf1b
--- /dev/null
+++ b/xsd-examples/cxx/parser/polyroot/superman.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : cxx/parser/polyroot/superman.xml
+copyright : not copyrighted - public domain
+
+-->
+
+<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="supermen.xsd"
+ xsi:type="superman" can-fly="false">
+
+ <name>James "007" Bond</name>
+
+</person>
diff --git a/xsd-examples/cxx/parser/polyroot/supermen-pimpl.cxx b/xsd-examples/cxx/parser/polyroot/supermen-pimpl.cxx
new file mode 100644
index 0000000..d35e1fd
--- /dev/null
+++ b/xsd-examples/cxx/parser/polyroot/supermen-pimpl.cxx
@@ -0,0 +1,85 @@
+// file : cxx/parser/polyroot/supermen-pimpl.cxx
+// copyright : not copyrighted - public domain
+//
+
+#include <iostream>
+
+#include "supermen-pimpl.hxx"
+
+using std::cout;
+using std::endl;
+
+// person_pimpl
+//
+void person_pimpl::
+pre ()
+{
+ cout << "starting to parse person" << endl;
+}
+
+void person_pimpl::
+name (const std::string& v)
+{
+ cout << "name: " << v << endl;
+}
+
+void person_pimpl::
+post_person ()
+{
+ cout << "finished parsing person" << endl
+ << endl;
+}
+
+// superman_pimpl
+//
+void superman_pimpl::
+pre ()
+{
+ cout << "starting to parse superman" << endl;
+}
+
+void superman_pimpl::
+can_fly (bool v)
+{
+ cout << "can-fly: " << v << endl;
+}
+
+void superman_pimpl::
+post_person ()
+{
+ post_superman ();
+}
+
+void superman_pimpl::
+post_superman ()
+{
+ cout << "finished parsing superman" << endl
+ << endl;
+}
+
+// batman_pimpl
+//
+void batman_pimpl::
+pre ()
+{
+ cout << "starting to parse batman" << endl;
+}
+
+void batman_pimpl::
+wing_span (unsigned int v)
+{
+ cout << "wing-span: " << v << endl;
+}
+
+void batman_pimpl::
+post_superman ()
+{
+ post_batman ();
+}
+
+void batman_pimpl::
+post_batman ()
+{
+ cout << "finished parsing batman" << endl
+ << endl;
+}
diff --git a/xsd-examples/cxx/parser/polyroot/supermen-pimpl.hxx b/xsd-examples/cxx/parser/polyroot/supermen-pimpl.hxx
new file mode 100644
index 0000000..17ce7ff
--- /dev/null
+++ b/xsd-examples/cxx/parser/polyroot/supermen-pimpl.hxx
@@ -0,0 +1,64 @@
+// file : cxx/parser/polyroot/supermen-pimpl.hxx
+// copyright : not copyrighted - public domain
+
+#ifndef SUPERMEN_PIMPL_HXX
+#define SUPERMEN_PIMPL_HXX
+
+#include "supermen-pskel.hxx"
+
+class person_pimpl: public virtual person_pskel
+{
+public:
+ virtual void
+ pre ();
+
+ virtual void
+ name (const std::string&);
+
+ virtual void
+ post_person ();
+};
+
+class superman_pimpl: public virtual superman_pskel,
+ public person_pimpl
+{
+public:
+ virtual void
+ pre ();
+
+ virtual void
+ can_fly (bool);
+
+ // By default, post_superman() calls post_person(). In case of
+ // polymorphic parsing we want the opposite: post_person() calls
+ // post_superman().
+ //
+ virtual void
+ post_person ();
+
+ virtual void
+ post_superman ();
+};
+
+class batman_pimpl: public virtual batman_pskel,
+ public superman_pimpl
+{
+public:
+ virtual void
+ pre ();
+
+ virtual void
+ wing_span (unsigned int);
+
+ // By default, post_batman() calls post_superman(). In case of
+ // polymorphic parsing we want the opposite: post_superman()
+ // calls post_batman().
+ //
+ virtual void
+ post_superman ();
+
+ virtual void
+ post_batman ();
+};
+
+#endif // SUPERMEN_PIMPL_HXX
diff --git a/xsd-examples/cxx/parser/polyroot/supermen.xsd b/xsd-examples/cxx/parser/polyroot/supermen.xsd
new file mode 100644
index 0000000..e397b50
--- /dev/null
+++ b/xsd-examples/cxx/parser/polyroot/supermen.xsd
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : cxx/parser/polyroot/supermen.xsd
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="person">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="person" type="person"/>
+
+ <xsd:complexType name="superman">
+ <xsd:complexContent>
+ <xsd:extension base="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="superman">
+ <xsd:attribute name="wing-span" type="xsd:unsignedInt" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+</xsd:schema>
diff --git a/xsd-examples/cxx/parser/polyroot/testscript b/xsd-examples/cxx/parser/polyroot/testscript
new file mode 100644
index 0000000..c5ad682
--- /dev/null
+++ b/xsd-examples/cxx/parser/polyroot/testscript
@@ -0,0 +1,6 @@
+# file : cxx/parser/polyroot/testscript
+# license : not copyrighted - public domain
+
+$* $src_base/batman.xml >| : batman
+$* $src_base/person.xml >| : person
+$* $src_base/superman.xml >| : superman