From d80d096ee8743fd6f7382d274272b0b6d7faf9bf Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 18 Oct 2010 11:17:51 +0200 Subject: Support for schema evolution using substitution groups New examples: hybrid/evolution/ignore and hybrid/evolution/passthrough. --- .../cxx/hybrid/evolution/passthrough/driver.cxx | 193 +++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 examples/cxx/hybrid/evolution/passthrough/driver.cxx (limited to 'examples/cxx/hybrid/evolution/passthrough/driver.cxx') diff --git a/examples/cxx/hybrid/evolution/passthrough/driver.cxx b/examples/cxx/hybrid/evolution/passthrough/driver.cxx new file mode 100644 index 0000000..35a334c --- /dev/null +++ b/examples/cxx/hybrid/evolution/passthrough/driver.cxx @@ -0,0 +1,193 @@ +// file : examples/cxx/hybrid/evolution/passthrough/driver.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include // std::auto_ptr +#include +#include + +#include "transform.hxx" +#include "transform-pimpl.hxx" +#include "transform-simpl.hxx" + +using namespace std; +using namespace transform; + +// Parser substitution map callback. This callback is called when the +// parser needs to check whether an element belongs to a substitution +// group. We use this callback to handle unknown transformations. +// +static bool +parser_callback (const xml_schema::ro_string& root_ns, + const xml_schema::ro_string& root_name, + const xml_schema::ro_string& /*member_ns*/, + const xml_schema::ro_string& member_name, + const char*& type) +{ + // Check that the root of the substitution group is 'transformation'. + // + if (root_name == "transformation" && + root_ns == "http://www.codesynthesis.com/transform") + { + // Check that the element's name has the '-transformation' suffix. This + // is the convention we use in our schema to minimize the chance of + // treating any unknown elements as a transformation. + // + // + string s ("-transformation"); + string n (member_name); + + if (n.size () > s.size () && + string (n, n.size () - s.size (), s.size ()) == s) + { + // Tell the parser to use unknown_type to parse this element. + // + type = unknown_type_pimpl::_static_type (); + return true; + } + } + + return false; +} + +// Serializer substitution map callback. This callback is called when +// the serializer needs to map a type to an element belonging to a +// substitution group. We use this callback to handle unknown +// transformations. +// +static bool +serializer_callback (const char* type, + const void* obj, + const char*& ns, + const char*& name) +{ + // Check whether this is unknown_type. + // + if (string (type) == unknown_type_simpl::_static_type ()) + { + // Cast the opaque obj pointer to unknown_type. + // + const unknown_type* u = reinterpret_cast (obj); + + // Extract the actual element name from the object. + // + const xml::qname& n (u->element_name ()); + ns = n.ns ().c_str (); + name = n.name ().c_str (); + + return true; + } + + return false; +} + +int +main (int argc, char* argv[]) +{ + const char* input; + + if (argc < 2) + { + input = "STDIN"; + cerr << "XML file not specified, reading from STDIN" << endl; + } + else + input = argv[1]; + + try + { + // Set the substitution map callbacks. + // + xml_schema::parser_smap_callback (&parser_callback); + xml_schema::serializer_smap_callback (&serializer_callback); + + // Parse. + // + transformations_paggr transformations_p; + + // The last argument to the document's constructor indicates that we + // are parsing polymorphic XML documents. + // + xml_schema::document_pimpl doc_p ( + transformations_p.root_parser (), + transformations_p.root_namespace (), + transformations_p.root_name (), + true); + + transformations_p.pre (); + + if (argc < 2) + doc_p.parse (cin); + else + doc_p.parse (argv[1]); + + auto_ptr tf (transformations_p.post ()); + + // Print what we've got. + // + for (transformations_type::transformation_iterator i = + tf->transformation ().begin (); + i != tf->transformation ().end (); + ++i) + { + transformation_type& t = *i; + + if (move_type* m = dynamic_cast (&t)) + { + cout << m->name () << ": " << m->description () << endl + << "\tx: " << m->x () << endl + << "\ty: " << m->y () << endl + << endl; + } + else if (rotate_type* r = dynamic_cast (&t)) + { + cout << r->name () << ": " << r->description () << endl + << "\tangle: " << r->angle () << endl + << endl; + } + else if (unknown_type* u = dynamic_cast (&t)) + { + cout << u->name () << ": " << u->description () << endl + << "\ttransformation is unknown" << endl + << endl; + } + } + + // Serialize. + // + transformations_saggr transformations_s; + + // The last argument to the document's constructor indicates that we + // are serializing polymorphic XML documents. + // + xml_schema::document_simpl doc_s ( + transformations_s.root_serializer (), + transformations_s.root_namespace (), + transformations_s.root_name (), + true); + + doc_s.add_prefix ("", "http://www.codesynthesis.com/transform"); + + transformations_s.pre (*tf); + doc_s.serialize (cout, xml_schema::document_simpl::pretty_print); + transformations_s.post (); + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const xml_schema::serializer_exception& e) + { + cerr << "error: " << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read/write failure" << endl; + return 1; + } + + return 0; +} -- cgit v1.1