From 5e527213a2430bb3018e5eebd909aef294edf9b5 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 18 Dec 2020 18:48:46 +0300 Subject: Switch to build2 --- xsd-examples/cxx/tree/custom/README | 40 ++++++ xsd-examples/cxx/tree/custom/buildfile | 6 + xsd-examples/cxx/tree/custom/calendar/.gitignore | 2 + xsd-examples/cxx/tree/custom/calendar/README | 47 +++++++ xsd-examples/cxx/tree/custom/calendar/buildfile | 47 +++++++ xsd-examples/cxx/tree/custom/calendar/calendar.xml | 22 +++ xsd-examples/cxx/tree/custom/calendar/calendar.xsd | 31 ++++ xsd-examples/cxx/tree/custom/calendar/driver.cxx | 39 ++++++ .../cxx/tree/custom/calendar/xml-schema-custom.cxx | 56 ++++++++ .../cxx/tree/custom/calendar/xml-schema-custom.hxx | 33 +++++ xsd-examples/cxx/tree/custom/comments/.gitignore | 2 + xsd-examples/cxx/tree/custom/comments/README | 57 ++++++++ xsd-examples/cxx/tree/custom/comments/buildfile | 48 +++++++ .../cxx/tree/custom/comments/dom-parse.cxx | 93 ++++++++++++ .../cxx/tree/custom/comments/dom-parse.hxx | 23 +++ xsd-examples/cxx/tree/custom/comments/driver.cxx | 90 ++++++++++++ xsd-examples/cxx/tree/custom/comments/people.xml | 20 +++ xsd-examples/cxx/tree/custom/comments/people.xsd | 29 ++++ .../cxx/tree/custom/comments/xml-schema-custom.cxx | 117 ++++++++++++++++ .../cxx/tree/custom/comments/xml-schema-custom.hxx | 60 ++++++++ xsd-examples/cxx/tree/custom/contacts/.gitignore | 1 + xsd-examples/cxx/tree/custom/contacts/README | 40 ++++++ xsd-examples/cxx/tree/custom/contacts/buildfile | 25 ++++ .../cxx/tree/custom/contacts/contacts-custom.cxx | 50 +++++++ .../cxx/tree/custom/contacts/contacts-custom.hxx | 43 ++++++ xsd-examples/cxx/tree/custom/contacts/contacts.xml | 20 +++ xsd-examples/cxx/tree/custom/contacts/contacts.xsd | 31 ++++ xsd-examples/cxx/tree/custom/contacts/driver.cxx | 38 +++++ xsd-examples/cxx/tree/custom/double/.gitignore | 2 + xsd-examples/cxx/tree/custom/double/README | 62 ++++++++ xsd-examples/cxx/tree/custom/double/buildfile | 46 ++++++ .../cxx/tree/custom/double/double-custom.cxx | 96 +++++++++++++ .../cxx/tree/custom/double/double-custom.hxx | 67 +++++++++ xsd-examples/cxx/tree/custom/double/driver.cxx | 31 ++++ xsd-examples/cxx/tree/custom/double/order.xsd | 25 ++++ xsd-examples/cxx/tree/custom/mixed/.gitignore | 1 + xsd-examples/cxx/tree/custom/mixed/README | 50 +++++++ xsd-examples/cxx/tree/custom/mixed/buildfile | 30 ++++ xsd-examples/cxx/tree/custom/mixed/driver.cxx | 122 ++++++++++++++++ .../cxx/tree/custom/mixed/people-custom.cxx | 89 ++++++++++++ .../cxx/tree/custom/mixed/people-custom.hxx | 83 +++++++++++ xsd-examples/cxx/tree/custom/mixed/people.xml | 38 +++++ xsd-examples/cxx/tree/custom/mixed/people.xsd | 45 ++++++ xsd-examples/cxx/tree/custom/taxonomy/.gitignore | 2 + xsd-examples/cxx/tree/custom/taxonomy/README | 53 +++++++ xsd-examples/cxx/tree/custom/taxonomy/buildfile | 31 ++++ xsd-examples/cxx/tree/custom/taxonomy/driver.cxx | 38 +++++ .../cxx/tree/custom/taxonomy/people-custom-fwd.hxx | 19 +++ .../cxx/tree/custom/taxonomy/people-custom.cxx | 156 +++++++++++++++++++++ .../cxx/tree/custom/taxonomy/people-custom.hxx | 105 ++++++++++++++ xsd-examples/cxx/tree/custom/taxonomy/people.xml | 26 ++++ xsd-examples/cxx/tree/custom/taxonomy/people.xsd | 44 ++++++ xsd-examples/cxx/tree/custom/wildcard/.gitignore | 1 + xsd-examples/cxx/tree/custom/wildcard/README | 45 ++++++ xsd-examples/cxx/tree/custom/wildcard/buildfile | 27 ++++ xsd-examples/cxx/tree/custom/wildcard/driver.cxx | 47 +++++++ .../cxx/tree/custom/wildcard/wildcard-custom.cxx | 84 +++++++++++ .../cxx/tree/custom/wildcard/wildcard-custom.hxx | 66 +++++++++ xsd-examples/cxx/tree/custom/wildcard/wildcard.xml | 14 ++ xsd-examples/cxx/tree/custom/wildcard/wildcard.xsd | 25 ++++ 60 files changed, 2680 insertions(+) create mode 100644 xsd-examples/cxx/tree/custom/README create mode 100644 xsd-examples/cxx/tree/custom/buildfile create mode 100644 xsd-examples/cxx/tree/custom/calendar/.gitignore create mode 100644 xsd-examples/cxx/tree/custom/calendar/README create mode 100644 xsd-examples/cxx/tree/custom/calendar/buildfile create mode 100644 xsd-examples/cxx/tree/custom/calendar/calendar.xml create mode 100644 xsd-examples/cxx/tree/custom/calendar/calendar.xsd create mode 100644 xsd-examples/cxx/tree/custom/calendar/driver.cxx create mode 100644 xsd-examples/cxx/tree/custom/calendar/xml-schema-custom.cxx create mode 100644 xsd-examples/cxx/tree/custom/calendar/xml-schema-custom.hxx create mode 100644 xsd-examples/cxx/tree/custom/comments/.gitignore create mode 100644 xsd-examples/cxx/tree/custom/comments/README create mode 100644 xsd-examples/cxx/tree/custom/comments/buildfile create mode 100644 xsd-examples/cxx/tree/custom/comments/dom-parse.cxx create mode 100644 xsd-examples/cxx/tree/custom/comments/dom-parse.hxx create mode 100644 xsd-examples/cxx/tree/custom/comments/driver.cxx create mode 100644 xsd-examples/cxx/tree/custom/comments/people.xml create mode 100644 xsd-examples/cxx/tree/custom/comments/people.xsd create mode 100644 xsd-examples/cxx/tree/custom/comments/xml-schema-custom.cxx create mode 100644 xsd-examples/cxx/tree/custom/comments/xml-schema-custom.hxx create mode 100644 xsd-examples/cxx/tree/custom/contacts/.gitignore create mode 100644 xsd-examples/cxx/tree/custom/contacts/README create mode 100644 xsd-examples/cxx/tree/custom/contacts/buildfile create mode 100644 xsd-examples/cxx/tree/custom/contacts/contacts-custom.cxx create mode 100644 xsd-examples/cxx/tree/custom/contacts/contacts-custom.hxx create mode 100644 xsd-examples/cxx/tree/custom/contacts/contacts.xml create mode 100644 xsd-examples/cxx/tree/custom/contacts/contacts.xsd create mode 100644 xsd-examples/cxx/tree/custom/contacts/driver.cxx create mode 100644 xsd-examples/cxx/tree/custom/double/.gitignore create mode 100644 xsd-examples/cxx/tree/custom/double/README create mode 100644 xsd-examples/cxx/tree/custom/double/buildfile create mode 100644 xsd-examples/cxx/tree/custom/double/double-custom.cxx create mode 100644 xsd-examples/cxx/tree/custom/double/double-custom.hxx create mode 100644 xsd-examples/cxx/tree/custom/double/driver.cxx create mode 100644 xsd-examples/cxx/tree/custom/double/order.xsd create mode 100644 xsd-examples/cxx/tree/custom/mixed/.gitignore create mode 100644 xsd-examples/cxx/tree/custom/mixed/README create mode 100644 xsd-examples/cxx/tree/custom/mixed/buildfile create mode 100644 xsd-examples/cxx/tree/custom/mixed/driver.cxx create mode 100644 xsd-examples/cxx/tree/custom/mixed/people-custom.cxx create mode 100644 xsd-examples/cxx/tree/custom/mixed/people-custom.hxx create mode 100644 xsd-examples/cxx/tree/custom/mixed/people.xml create mode 100644 xsd-examples/cxx/tree/custom/mixed/people.xsd create mode 100644 xsd-examples/cxx/tree/custom/taxonomy/.gitignore create mode 100644 xsd-examples/cxx/tree/custom/taxonomy/README create mode 100644 xsd-examples/cxx/tree/custom/taxonomy/buildfile create mode 100644 xsd-examples/cxx/tree/custom/taxonomy/driver.cxx create mode 100644 xsd-examples/cxx/tree/custom/taxonomy/people-custom-fwd.hxx create mode 100644 xsd-examples/cxx/tree/custom/taxonomy/people-custom.cxx create mode 100644 xsd-examples/cxx/tree/custom/taxonomy/people-custom.hxx create mode 100644 xsd-examples/cxx/tree/custom/taxonomy/people.xml create mode 100644 xsd-examples/cxx/tree/custom/taxonomy/people.xsd create mode 100644 xsd-examples/cxx/tree/custom/wildcard/.gitignore create mode 100644 xsd-examples/cxx/tree/custom/wildcard/README create mode 100644 xsd-examples/cxx/tree/custom/wildcard/buildfile create mode 100644 xsd-examples/cxx/tree/custom/wildcard/driver.cxx create mode 100644 xsd-examples/cxx/tree/custom/wildcard/wildcard-custom.cxx create mode 100644 xsd-examples/cxx/tree/custom/wildcard/wildcard-custom.hxx create mode 100644 xsd-examples/cxx/tree/custom/wildcard/wildcard.xml create mode 100644 xsd-examples/cxx/tree/custom/wildcard/wildcard.xsd (limited to 'xsd-examples/cxx/tree/custom') diff --git a/xsd-examples/cxx/tree/custom/README b/xsd-examples/cxx/tree/custom/README new file mode 100644 index 0000000..b2a65b5 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/README @@ -0,0 +1,40 @@ +This directory contains a number of examples that show how to customize the +C++/Tree mapping. The following list gives an overview of each example: + +calendar + Shows how to customize XML Schema built-in types by mapping xsd:date + built-in type to the date class from the Boost date_time library. + +comments + This example shows how to customize the anyType XML Schema built-in + type to implement preservation of comments stored in XML documents. + Because anyType is a base type for every generated type, you can use + this technique to implement custom functionality that spans the + entire type system. + +contacts + Shows how to map a user-defined XML Schema type to a custom C++ class. + This example presents the simple case where the customized type is not + used as a base in the same schema. + +double + Shows how to customize parsing and serialization code for the xsd:double + XML Schema built-in type. It can be used as a guide on how to customize + built-in XML Schema types that are mapped to fundamental C++ types. + +mixed + Shows how to use type customization to parse and serialize mixed content. + +taxonomy + Shows how to map user-defined XML Schema types to custom C++ classes. + This example presents the complex case where the customized types are + inherited from in the same schema. + +wildcard + Shows how to use type customization to parse and serialize a specific + attribute that is matched by a wildcard (anyAttribute). + +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 diff --git a/xsd-examples/cxx/tree/custom/buildfile b/xsd-examples/cxx/tree/custom/buildfile new file mode 100644 index 0000000..e650f99 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/buildfile @@ -0,0 +1,6 @@ +# file : cxx/tree/custom/buildfile +# license : not copyrighted - public domain + +# Exclude examples which depend on not yet packaged libraries. +# +./: {*/ -calendar/} diff --git a/xsd-examples/cxx/tree/custom/calendar/.gitignore b/xsd-examples/cxx/tree/custom/calendar/.gitignore new file mode 100644 index 0000000..2f35b6b --- /dev/null +++ b/xsd-examples/cxx/tree/custom/calendar/.gitignore @@ -0,0 +1,2 @@ +calendar.?xx +xml-schema.hxx diff --git a/xsd-examples/cxx/tree/custom/calendar/README b/xsd-examples/cxx/tree/custom/calendar/README new file mode 100644 index 0000000..f7f6989 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/calendar/README @@ -0,0 +1,47 @@ +This example shows how to customize the XML Schema built-in types by mapping +xsd:date built-in type to the date class from the Boost date_time library. +You will need the Boost date_time library[1] installed in order to build +and run this example. For more information on the C++/Tree mapping +customization see the C++/Tree Mapping Customization Guide[2]. + +[1] http://www.boost.org +[2] http://wiki.codesynthesis.com/Tree/Customization_guide + +The example consists of the following files: + +calendar.xsd + XML Schema definition for a simple calendar format. + +calendar.xml + Sample XML instance document. + +xml-schema.hxx + C++ types for XML Schema built-in types. This header file is generated + by XSD using the --generate-xml-schema option. The --custom-type option + is also used to customize the xsd:date type. + +calendar.hxx +calendar.ixx +calendar.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 calendar.xsd with the + --extern-xml-schema option in order to include xml-schema.hxx. + +xml-schema-custom.hxx + Header file which defines our own xml_schema::date class. It is + included at the end of xml-schema.hxx using the --hxx-epilogue + option. + +xml-schema-custom.cxx + Source file which contains the implementation of our xml_schema:date + class. + +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 calendar events to STDERR. + +To run the example on the sample XML instance document simply execute: + +$ ./driver calendar.xml diff --git a/xsd-examples/cxx/tree/custom/calendar/buildfile b/xsd-examples/cxx/tree/custom/calendar/buildfile new file mode 100644 index 0000000..3c26122 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/calendar/buildfile @@ -0,0 +1,47 @@ +# file : cxx/tree/custom/calendar/buildfile +# license : not copyrighted - public domain + +import libs = libxsd%lib{xsd} +import libs += libxerces-c%lib{xerces-c} +import libs += libboost-date-time%lib{boost_date_time} + +./: exe{driver} doc{README} + +exe{driver}: {hxx cxx}{* -calendar -xml-schema} \ + {hxx ixx cxx}{calendar} \ + {hxx }{xml-schema} \ + $libs + +exe{driver}: xml{calendar}: test.input = true + +<{hxx ixx cxx}{calendar}>: xsd{calendar} $xsd +{{ + diag xsd ($<[0]) # @@ TMP + + $xsd cxx-tree --std c++11 \ + --generate-inline \ + --extern-xml-schema xml-schema.xsd \ + --output-dir $out_base \ + $path($<[0]) +}} + +hxx{xml-schema}: $xsd +{{ + diag xsd gen ($>[0]) + + # Note that the specified xml-schema.xsd doesn't exist and is only used to + # deduce the generated header name. + # + $xsd cxx-tree --std c++11 \ + --generate-xml-schema \ + --custom-type date \ + --hxx-epilogue '#include "xml-schema-custom.hxx"' \ + --output-dir $out_base \ + xml-schema.xsd +}} + +cxx.poptions =+ "-I$out_base" "-I$src_base" + +# Define XSD_CXX11 since we include libxsd headers directly. +# +cxx.poptions += -DXSD_CXX11 diff --git a/xsd-examples/cxx/tree/custom/calendar/calendar.xml b/xsd-examples/cxx/tree/custom/calendar/calendar.xml new file mode 100644 index 0000000..8fff59c --- /dev/null +++ b/xsd-examples/cxx/tree/custom/calendar/calendar.xml @@ -0,0 +1,22 @@ + + + + + + + + Don't forget to change the tire. + + + + Can be cancelled if it is too cold. + + + diff --git a/xsd-examples/cxx/tree/custom/calendar/calendar.xsd b/xsd-examples/cxx/tree/custom/calendar/calendar.xsd new file mode 100644 index 0000000..8b36c34 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/calendar/calendar.xsd @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xsd-examples/cxx/tree/custom/calendar/driver.cxx b/xsd-examples/cxx/tree/custom/calendar/driver.cxx new file mode 100644 index 0000000..fdecf57 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/calendar/driver.cxx @@ -0,0 +1,39 @@ +// file : cxx/tree/custom/calendar/driver.cxx +// copyright : not copyrighted - public domain + +#include // std::unique_ptr +#include + +#include "calendar.hxx" + +using std::cerr; +using std::endl; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " calendar.xml" << endl; + return 1; + } + + try + { + using namespace calendar; + + std::unique_ptr e (events_ (argv[1])); + + for (events::event_const_iterator i (e->event ().begin ()); + i != e->event ().end (); ++i) + { + cerr << i->date () << " " << i->title () << endl + << *i << endl; + } + } + catch (const xml_schema::exception& e) + { + cerr << e << endl; + return 1; + } +} diff --git a/xsd-examples/cxx/tree/custom/calendar/xml-schema-custom.cxx b/xsd-examples/cxx/tree/custom/calendar/xml-schema-custom.cxx new file mode 100644 index 0000000..2bfe0f2 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/calendar/xml-schema-custom.cxx @@ -0,0 +1,56 @@ +// file : cxx/tree/custom/calendar/xml-schema-custom.cxx +// copyright : not copyrighted - public domain + +// Include xml-schema.hxx instead of xml-schema-custom.hxx here. +// +#include "xml-schema.hxx" + +#include // xsd::cxx::xml::transcode +#include // xsd::cxx::tree::text_content + +using namespace boost; +using namespace boost::gregorian; + +namespace xml_schema +{ + date:: + date (const xercesc::DOMElement& e, flags f, container* c) + : simple_type (e, f, c), + gregorian::date ( + from_simple_string ( + xsd::cxx::tree::text_content (e))) + { + } + + date:: + date (const xercesc::DOMAttr& a, flags f, container* c) + : simple_type (a, f, c), + gregorian::date ( + from_simple_string ( + xsd::cxx::xml::transcode (a.getValue ()))) + { + } + + date:: + date (const std::string& s, + const xercesc::DOMElement* e, + flags f, + container* c) + : simple_type (s, e, f, c), + gregorian::date (from_simple_string (s)) + { + } + + date:: + date (const date& d, flags f, container* c) + : simple_type (d, f, c), + gregorian::date (d) + { + } + + date* date:: + _clone (flags f, container* c) const + { + return new date (*this, f, c); + } +} diff --git a/xsd-examples/cxx/tree/custom/calendar/xml-schema-custom.hxx b/xsd-examples/cxx/tree/custom/calendar/xml-schema-custom.hxx new file mode 100644 index 0000000..f8f8218 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/calendar/xml-schema-custom.hxx @@ -0,0 +1,33 @@ +// file : cxx/tree/custom/calendar/xml-schema-custom.hxx +// copyright : not copyrighted - public domain + +// Do not include this file directly, use xml-schema.hxx instead. This +// file is included into generated xml-schema.hxx so we do not need to +// guard against multiple inclusions. +// + +#include // boost::gregorian::date + +namespace xml_schema +{ + class date: public simple_type, + public boost::gregorian::date + { + public: + // Parsing c-tors: element, attribute, and list item. + // + date (const xercesc::DOMElement&, flags = 0, container* = 0); + date (const xercesc::DOMAttr&, flags = 0, container* = 0); + date (const std::string&, + const xercesc::DOMElement*, + flags = 0, + container* = 0); + + // Copy c-tor and _clone. + // + date (const date&, flags = 0, container* = 0); + + virtual date* + _clone (flags = 0, container* = 0) const; + }; +} diff --git a/xsd-examples/cxx/tree/custom/comments/.gitignore b/xsd-examples/cxx/tree/custom/comments/.gitignore new file mode 100644 index 0000000..78cfc67 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/comments/.gitignore @@ -0,0 +1,2 @@ +people.?xx +xml-schema.hxx diff --git a/xsd-examples/cxx/tree/custom/comments/README b/xsd-examples/cxx/tree/custom/comments/README new file mode 100644 index 0000000..8fd69d0 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/comments/README @@ -0,0 +1,57 @@ +This example shows how to customize the anyType XML Schema built-in +type to implement preservation of comments stored in XML documents. +Because anyType is a base type for every generated type, you can use +this technique to implement custom functionality that spans the +entire type system. For more information on the C++/Tree mapping +customization see the C++/Tree Mapping Customization Guide[2]. + +[2] http://wiki.codesynthesis.com/Tree/Customization_guide + +The example consists of the following files: + +people.xsd + XML Schema definition for a simple person record vocabulary. + +people.xml + Sample XML instance document. + +xml-schema.hxx + C++ types for XML Schema built-in types. This header file is generated + by XSD using the --generate-xml-schema option. The --custom-type option + is also used to customize the xsd:anyType type. + +people.hxx +people.ixx +people.cxx + C++ types that represent the person record vocabulary, a set of + parsing functions that convert XML instance documents to a tree-like + in-memory object model, and a set of serialization functions that + convert the object model back to XML. These are generated by XSD + from people.xsd with the --extern-xml-schema option in order to + include xml-schema.hxx. + +xml-schema-custom.hxx + Header file which defines our own xml_schema::type class. It is + included at the end of xml-schema.hxx using the --hxx-epilogue + option. + +xml-schema-custom.cxx + Source file which contains the implementation of our xml_schema:type + class. + +dom-parse.hxx +dom-parse.cxx + Definition and implementation of the parse() function that + parses an XML document to a DOM document while preserving + XML comments. + +driver.cxx + Driver for the example. It first calls the above parse() function + to parse the input file to a DOM document. It then parses the DOM + document to the object model and performs a number of modifications + on this object model. Finally, it serializes the modified object + model back to XML, including XML comments. + +To run the example on the sample XML instance document simply execute: + +$ ./driver people.xml diff --git a/xsd-examples/cxx/tree/custom/comments/buildfile b/xsd-examples/cxx/tree/custom/comments/buildfile new file mode 100644 index 0000000..093a6cc --- /dev/null +++ b/xsd-examples/cxx/tree/custom/comments/buildfile @@ -0,0 +1,48 @@ +# file : cxx/tree/custom/comments/buildfile +# license : not copyrighted - public domain + +import libs = libxsd%lib{xsd} +import libs += libxerces-c%lib{xerces-c} + +./: exe{driver} doc{README} + +exe{driver}: {hxx cxx}{* -people -xml-schema} \ + {hxx ixx cxx}{people} \ + {hxx }{xml-schema} \ + $libs + +exe{driver}: xml{people}: test.input = true + +<{hxx ixx cxx}{people}>: xsd{people} $xsd +{{ + diag xsd ($<[0]) # @@ TMP + + $xsd cxx-tree --std c++11 \ + --generate-inline \ + --generate-serialization \ + --extern-xml-schema xml-schema.xsd \ + --output-dir $out_base \ + $path($<[0]) +}} + +hxx{xml-schema}: $xsd +{{ + diag xsd gen ($>[0]) + + # Note that the specified xml-schema.xsd doesn't exist and is only used to + # deduce the generated header name. + # + $xsd cxx-tree --std c++11 \ + --generate-xml-schema \ + --generate-serialization \ + --custom-type anyType=/type_base \ + --hxx-epilogue '#include "xml-schema-custom.hxx"' \ + --output-dir $out_base \ + xml-schema.xsd +}} + +cxx.poptions =+ "-I$out_base" "-I$src_base" + +# Define XSD_CXX11 since we include libxsd headers directly. +# +cxx.poptions += -DXSD_CXX11 diff --git a/xsd-examples/cxx/tree/custom/comments/dom-parse.cxx b/xsd-examples/cxx/tree/custom/comments/dom-parse.cxx new file mode 100644 index 0000000..2fa6a70 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/comments/dom-parse.cxx @@ -0,0 +1,93 @@ +// file : cxx/tree/custom/comments/dom-parse.cxx +// copyright : not copyrighted - public domain + +#include "dom-parse.hxx" + +#include + +#include +#include // chLatin_* +#include + +#include +#include + +#include +#include + +using namespace xercesc; +namespace xml = xsd::cxx::xml; +namespace tree = xsd::cxx::tree; + +xml::dom::unique_ptr +parse (std::istream& is, const std::string& id, bool validate) +{ + const XMLCh ls_id [] = {chLatin_L, chLatin_S, chNull}; + + // Get an implementation of the Load-Store (LS) interface. + // + DOMImplementation* impl ( + DOMImplementationRegistry::getDOMImplementation (ls_id)); + + xml::dom::unique_ptr parser ( + impl->createLSParser (DOMImplementationLS::MODE_SYNCHRONOUS, 0)); + + DOMConfiguration* conf (parser->getDomConfig ()); + + // Preserve comment nodes in the document. + // + conf->setParameter (XMLUni::fgDOMComments, true); + + // Enable datatype normalization. + // + conf->setParameter (XMLUni::fgDOMDatatypeNormalization, true); + + // Do not create EntityReference nodes in the DOM tree. No + // EntityReference nodes will be created, only the nodes + // corresponding to their fully expanded substitution text + // will be created. + // + conf->setParameter (XMLUni::fgDOMEntities, false); + + // Perform namespace processing. + // + conf->setParameter (XMLUni::fgDOMNamespaces, true); + + // Do not include ignorable whitespace in the DOM tree. + // + conf->setParameter (XMLUni::fgDOMElementContentWhitespace, false); + + // Enable/Disable validation. + // + conf->setParameter (XMLUni::fgDOMValidate, validate); + conf->setParameter (XMLUni::fgXercesSchema, validate); + conf->setParameter (XMLUni::fgXercesSchemaFullChecking, false); + + // Xerces-C++ 3.1.0 is the first version with working multi import + // support. + // +#if _XERCES_VERSION >= 30100 + conf->setParameter (XMLUni::fgXercesHandleMultipleImports, true); +#endif + + // We will release the DOM document ourselves. + // + conf->setParameter (XMLUni::fgXercesUserAdoptsDOMDocument, true); + + // Set error handler. + // + tree::error_handler eh; + xml::dom::bits::error_handler_proxy ehp (eh); + conf->setParameter (XMLUni::fgDOMErrorHandler, &ehp); + + // Prepare input stream. + // + xml::sax::std_input_source isrc (is, id); + Wrapper4InputSource wrap (&isrc, false); + + xml::dom::unique_ptr doc (parser->parse (&wrap)); + + eh.throw_if_failed > (); + + return doc; +} diff --git a/xsd-examples/cxx/tree/custom/comments/dom-parse.hxx b/xsd-examples/cxx/tree/custom/comments/dom-parse.hxx new file mode 100644 index 0000000..83c3dd4 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/comments/dom-parse.hxx @@ -0,0 +1,23 @@ +// file : cxx/tree/custom/comments/dom-parse.hxx +// copyright : not copyrighted - public domain + +#ifndef DOM_PARSE +#define DOM_PARSE + +#include +#include + +#include + +#include + +// Parse an XML document from the standard input stream with an +// optional resource id. Resource id is used in diagnostics as +// well as to locate schemas referenced from inside the document. +// +xsd::cxx::xml::dom::unique_ptr +parse (std::istream& is, + const std::string& id, + bool validate); + +#endif // DOM_PARSE diff --git a/xsd-examples/cxx/tree/custom/comments/driver.cxx b/xsd-examples/cxx/tree/custom/comments/driver.cxx new file mode 100644 index 0000000..5588273 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/comments/driver.cxx @@ -0,0 +1,90 @@ +// file : cxx/tree/custom/commens/driver.cxx +// copyright : not copyrighted - public domain + +#include // std::unique_ptr +#include +#include + +#include +#include + +#include "people.hxx" +#include "dom-parse.hxx" + +using namespace std; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " people.xml" << endl; + return 1; + } + + int r (0); + + // We need to initialize the Xerces-C++ runtime because we + // are doing the XML-to-DOM parsing ourselves (see below). + // + xercesc::XMLPlatformUtils::Initialize (); + + try + { + using namespace people; + namespace xml = xsd::cxx::xml; + + ifstream ifs; + ifs.exceptions (ifstream::badbit | ifstream::failbit); + ifs.open (argv[1]); + + // For performance reasons the internal XML to DOM parsing code + // discards comments in the resulting DOM document. To overcome + // this we are going to use our own parse() function from + // dom-parse.hxx that preserves comments in the resulting DOM + // documents. + // + xml_schema::dom::unique_ptr doc ( + parse (ifs, argv[1], true)); + + // Parse the DOM document to the object model. + // + unique_ptr c (catalog_ (*doc)); + + // Change the object model. + // + catalog::person_sequence& ps (c->person ()); + + for (catalog::person_iterator i (ps.begin ()); i != ps.end (); ++i) + { + i->age (i->age () + 1); + } + + person john ("John Doe", 30); + john.comment ("Record for John Doe"); + + ps.push_back (john); + + // Serialize. + // + xml_schema::namespace_infomap map; + + map["ppl"].name = "http://www.codesynthesis.com/people"; + map["ppl"].schema = "people.xsd"; + + catalog_ (std::cout, *c, map); + } + catch (const xml_schema::exception& e) + { + cerr << e << endl; + r = 1; + } + catch (const std::ios_base::failure&) + { + cerr << argv[1] << ": unable to open or read failure" << endl; + r = 1; + } + + xercesc::XMLPlatformUtils::Terminate (); + return r; +} diff --git a/xsd-examples/cxx/tree/custom/comments/people.xml b/xsd-examples/cxx/tree/custom/comments/people.xml new file mode 100644 index 0000000..08d69e9 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/comments/people.xml @@ -0,0 +1,20 @@ + + + + + + + + + Joe Dirt + 28 + + + diff --git a/xsd-examples/cxx/tree/custom/comments/people.xsd b/xsd-examples/cxx/tree/custom/comments/people.xsd new file mode 100644 index 0000000..20f265f --- /dev/null +++ b/xsd-examples/cxx/tree/custom/comments/people.xsd @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/xsd-examples/cxx/tree/custom/comments/xml-schema-custom.cxx b/xsd-examples/cxx/tree/custom/comments/xml-schema-custom.cxx new file mode 100644 index 0000000..265e0cb --- /dev/null +++ b/xsd-examples/cxx/tree/custom/comments/xml-schema-custom.cxx @@ -0,0 +1,117 @@ +// file : cxx/tree/custom/comments/xml-schema-custom.cxx +// copyright : not copyrighted - public domain + +// Include xml-schema.hxx instead of xml-schema-custom.hxx here. +// +#include "xml-schema.hxx" + +#include +#include + +#include // xml::transcode, xml::string + +namespace xml = xsd::cxx::xml; + +namespace xml_schema +{ + type:: + type () + : type_base () + { + } + + type:: + type (const xercesc::DOMElement& e, flags f, container* c) + : type_base (e, f, c) + { + using namespace xercesc; + + // Here we are only handling a comment that is the first + // node in the element's content. + // + const DOMNode* n (e.getFirstChild ()); + + if (n != 0 && n->getNodeType () == DOMNode::COMMENT_NODE) + { + const DOMComment* c (static_cast (n)); + comment_ = xml::transcode (c->getData ()); + } + } + + type:: + type (const xercesc::DOMAttr& a, flags f, container* c) + : type_base (a, f, c) + { + // No comments for attributes. + // + } + + type:: + type (const std::string& s, const xercesc::DOMElement* e, + flags f, container* c) + : type_base (s, e, f, c) + { + // No comments for list items. + // + } + + type:: + type (const type& x, flags f, container* c) + : type_base (x, f, c), comment_ (x.comment_) + { + } + + type* type:: + _clone (flags f, container* c) const + { + return new type (*this, f, c); + } + + // Serialization operators. + // + void + operator<< (xercesc::DOMElement& e, const type& x) + { + // Call our base first. + // + const type_base& b (x); + e << b; + + // Add the comment if any. + // + const std::string s (x.comment ()); + + if (!s.empty ()) + { + using namespace xercesc; + + DOMDocument* doc (e.getOwnerDocument ()); + DOMComment* c (doc->createComment (xml::string (s).c_str ())); + e.appendChild (c); + } + } + + void + operator<< (xercesc::DOMAttr& a, const type& x) + { + // Call our base first. + // + const type_base& b (x); + a << b; + + // No comments for attributes. + // + } + + void + operator<< (xml_schema::list_stream& ls, const type& x) + { + // Call our base first. + // + const type_base& b (x); + ls << b; + + // No comments for list items. + // + } +} diff --git a/xsd-examples/cxx/tree/custom/comments/xml-schema-custom.hxx b/xsd-examples/cxx/tree/custom/comments/xml-schema-custom.hxx new file mode 100644 index 0000000..01a4f9c --- /dev/null +++ b/xsd-examples/cxx/tree/custom/comments/xml-schema-custom.hxx @@ -0,0 +1,60 @@ +// file : cxx/tree/custom/comments/xml-schema-custom.hxx +// copyright : not copyrighted - public domain + +// Do not include this file directly, use xml-schema.hxx instead. This +// file is included into generated xml-schema.hxx so we do not need to +// guard against multiple inclusions. +// + +#include + +namespace xml_schema +{ + // When customizing anyType always inherit from the original type. + // + class type: public type_base + { + public: + type (); + type (const xercesc::DOMElement&, flags = 0, container* = 0); + type (const xercesc::DOMAttr&, flags = 0, container* = 0); + type (const std::string&, const xercesc::DOMElement*, + flags = 0, container* = 0); + type (const type&, flags = 0, container* = 0); + + type& + operator= (const type&) = default; + + virtual type* + _clone (flags = 0, container* = 0) const; + + public: + // Comment manipulation API. + // + const std::string& + comment () const + { + return comment_; + } + + void + comment (const std::string& c) + { + comment_ = c; + } + + private: + std::string comment_; + }; + + // New serialization operators. + // + void + operator<< (xercesc::DOMElement&, const type&); + + void + operator<< (xercesc::DOMAttr&, const type&); + + void + operator<< (xml_schema::list_stream&, const type&); +} diff --git a/xsd-examples/cxx/tree/custom/contacts/.gitignore b/xsd-examples/cxx/tree/custom/contacts/.gitignore new file mode 100644 index 0000000..43c214d --- /dev/null +++ b/xsd-examples/cxx/tree/custom/contacts/.gitignore @@ -0,0 +1 @@ +contacts.?xx diff --git a/xsd-examples/cxx/tree/custom/contacts/README b/xsd-examples/cxx/tree/custom/contacts/README new file mode 100644 index 0000000..072ede3 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/contacts/README @@ -0,0 +1,40 @@ +This example shows how to map a user-defined XML Schema type to a custom +C++ class. It presents the simple case where the customized type is not +used as a base in the same schema. For the complex case see the taxonomy +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: + +contacts.xsd + XML Schema definition for a simple contacts database. + +contacts.xml + Sample XML instance document. + +contacts.hxx +contacts.ixx +contacts.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 contacts.xsd with the + --custom-type option in order to customize the contact type. + +contacts-custom.hxx + Header file which defines our own contact class by inheriting from the + generated contact_base. It is included at the end of contacts.hxx using + the --hxx-epilogue option. + +contacts-custom.cxx + Source file which contains the implementation of our contact class. + +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 contacts to STDERR. + +To run the example on the sample XML instance document simply execute: + +$ ./driver contacts.xml diff --git a/xsd-examples/cxx/tree/custom/contacts/buildfile b/xsd-examples/cxx/tree/custom/contacts/buildfile new file mode 100644 index 0000000..190306c --- /dev/null +++ b/xsd-examples/cxx/tree/custom/contacts/buildfile @@ -0,0 +1,25 @@ +# file : cxx/tree/custom/contacts/buildfile +# license : not copyrighted - public domain + +import libs = libxsd%lib{xsd} +import libs += libxerces-c%lib{xerces-c} + +./: exe{driver} doc{README} + +exe{driver}: {hxx cxx}{* -contacts} {hxx ixx cxx}{contacts} $libs + +exe{driver}: xml{contacts}: test.input = true + +<{hxx ixx cxx}{contacts}>: xsd{contacts} $xsd +{{ + diag xsd ($<[0]) # @@ TMP + + $xsd cxx-tree --std c++11 \ + --generate-inline \ + --custom-type contact=/contact_base \ + --hxx-epilogue '#include "contacts-custom.hxx"' \ + --output-dir $out_base \ + $path($<[0]) +}} + +cxx.poptions =+ "-I$out_base" "-I$src_base" diff --git a/xsd-examples/cxx/tree/custom/contacts/contacts-custom.cxx b/xsd-examples/cxx/tree/custom/contacts/contacts-custom.cxx new file mode 100644 index 0000000..208b00f --- /dev/null +++ b/xsd-examples/cxx/tree/custom/contacts/contacts-custom.cxx @@ -0,0 +1,50 @@ +// file : cxx/tree/custom/contacts/contacts-custom.cxx +// copyright : not copyrighted - public domain + +#include + +// Include contacts.hxx instead of contacts-custom.hxx here. +// +#include "contacts.hxx" + +namespace contacts +{ + // We implement the following constructs by simply forwarding + // to our base. + // + contact:: + contact (const name_type& n, + const email_type& e, + const phone_type& p) + : contact_base (n, e, p) + { + } + + contact:: + contact (const xercesc::DOMElement& e, + xml_schema::flags f, + xml_schema::container* c) + : contact_base (e, f, c) + { + } + + contact:: + contact (const contact& x, + xml_schema::flags f, + xml_schema::container* c) + : contact_base (x, f, c) + { + } + + contact* contact:: + _clone (xml_schema::flags f, xml_schema::container* c) const + { + return new contact (*this, f, c); + } + + void contact:: + print (std::ostream& os) const + { + os << name () << " e| " << email () << " t| " << phone () << std::endl; + } +} diff --git a/xsd-examples/cxx/tree/custom/contacts/contacts-custom.hxx b/xsd-examples/cxx/tree/custom/contacts/contacts-custom.hxx new file mode 100644 index 0000000..a5bc893 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/contacts/contacts-custom.hxx @@ -0,0 +1,43 @@ +// file : cxx/tree/custom/contacts/contacts-custom.hxx +// copyright : not copyrighted - public domain + +// Do not include this file directly, use contacts.hxx instead. This +// file is included into generated contacts.hxx so we do not need to +// guard against multiple inclusions. +// + +#include // std::ostream + +namespace contacts +{ + class contact: public contact_base + { + // The following constructor signatures are copied from + // contact_base except for the copy constructor and the + // _clone function where we had to change the type from + // contact_base to contact. + // + public: + contact (const name_type&, + const email_type&, + const phone_type&); + + contact (const xercesc::DOMElement&, + xml_schema::flags = 0, + xml_schema::container* = 0); + + contact (const contact&, + xml_schema::flags = 0, + xml_schema::container* = 0); + + virtual contact* + _clone (xml_schema::flags = 0, + xml_schema::container* = 0) const; + + // Our customizations. + // + public: + void + print (std::ostream&) const; + }; +} diff --git a/xsd-examples/cxx/tree/custom/contacts/contacts.xml b/xsd-examples/cxx/tree/custom/contacts/contacts.xml new file mode 100644 index 0000000..884c25e --- /dev/null +++ b/xsd-examples/cxx/tree/custom/contacts/contacts.xml @@ -0,0 +1,20 @@ + + + + + + + + Joe Dirt + joe@dirt.com + 555 DIRT + + + diff --git a/xsd-examples/cxx/tree/custom/contacts/contacts.xsd b/xsd-examples/cxx/tree/custom/contacts/contacts.xsd new file mode 100644 index 0000000..5348810 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/contacts/contacts.xsd @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xsd-examples/cxx/tree/custom/contacts/driver.cxx b/xsd-examples/cxx/tree/custom/contacts/driver.cxx new file mode 100644 index 0000000..a0c7510 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/contacts/driver.cxx @@ -0,0 +1,38 @@ +// file : cxx/tree/custom/contacts/driver.cxx +// copyright : not copyrighted - public domain + +#include // std::unique_ptr +#include + +#include "contacts.hxx" + +using std::cerr; +using std::endl; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " contacts.xml" << endl; + return 1; + } + + try + { + using namespace contacts; + + std::unique_ptr c (catalog_ (argv[1])); + + for (catalog::contact_const_iterator i (c->contact ().begin ()); + i != c->contact ().end (); ++i) + { + i->print (cerr); + } + } + catch (const xml_schema::exception& e) + { + cerr << e << endl; + return 1; + } +} diff --git a/xsd-examples/cxx/tree/custom/double/.gitignore b/xsd-examples/cxx/tree/custom/double/.gitignore new file mode 100644 index 0000000..5cc7f75 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/double/.gitignore @@ -0,0 +1,2 @@ +order.?xx +xml-schema.hxx diff --git a/xsd-examples/cxx/tree/custom/double/README b/xsd-examples/cxx/tree/custom/double/README new file mode 100644 index 0000000..15348d2 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/double/README @@ -0,0 +1,62 @@ +This example shows how to customize parsing and serialization code for the +xsd:double XML Schema built-in type using the type customization mechanism +provided by the C++/Tree Mapping. For more information on type customization +see the C++/Tree Mapping Customization Guide, particularly sections 1 and 4: + +http://wiki.codesynthesis.com/Tree/Customization_guide + +In this example our schema uses xsd:double to represent a price. There are +two potential problems with this choice of a price type. First, xsd:double +can be serialized in the scientific notation which would be an unusual way +of representing a price. Second, we would like to limit the number of +fraction digits in our prices to 2. Furthermore, we would like to always +have two fraction digits, even if one or both of them are zeros, for +example: 12.99, 12.90, 12.00. + +In case we can modify the schema, a better approach would be to define the +price type as a restriction of the xsd:decimal type (always fixed notation) +and specify the fractionDigits facet to limit the number of fraction digits +to 2. However, there is no way in XML Schema to specify that there should +always be exactly 2 fraction digits. Therefore, it may still be desirable +to customize this price type to get the required serialization behavior. + +Finally, it is worth noting that the behavior achieved in this example via +type customization can also be achieved by compiling your code with the +following macros defined: + +XSD_TREE_DOUBLE_FIXED +XSD_TREE_DOUBLE_PRECISION 2 + +However, the type customization approach while requiring more work is +cleaner since it does not rely on global macro definitions. + +This example consists of the following files: + +order.xsd + XML Schema definition for a simple order vocabulary. + +double-custom.hxx +double-custom.cxx + Custom parsing and serialization code for the xsd:double types. The + double-custom.hxx file is included at the end of the xml-schema.hxx + file described below. + +xml-schema.hxx + C++ types for XML Schema built-in types. This header file is generated + by the XSD compiler using the --generate-xml-schema option. The + --custom-type option is used to customize the xsd:double type. The + --hxx-epilogue option is used to include the double-custom.hxx file + at the end of this file. + +order.hxx +order.cxx + C++ types generated from order.xsd. The --extern-xml-schema option + is used to include xml-schema.hxx into order.hxx. + +driver.cxx + Test driver for the example. It creates a sample order and then + writes it to XML to test the custom xsd:double serialization code. + +To run the example simply execute: + +$ ./driver diff --git a/xsd-examples/cxx/tree/custom/double/buildfile b/xsd-examples/cxx/tree/custom/double/buildfile new file mode 100644 index 0000000..258191a --- /dev/null +++ b/xsd-examples/cxx/tree/custom/double/buildfile @@ -0,0 +1,46 @@ +# file : cxx/tree/custom/double/buildfile +# license : not copyrighted - public domain + +import libs = libxsd%lib{xsd} +import libs += libxerces-c%lib{xerces-c} + +./: exe{driver} doc{README} + +exe{driver}: {hxx cxx}{* -order -xml-schema} \ + {hxx ixx cxx}{order} \ + {hxx }{xml-schema} \ + $libs + +<{hxx ixx cxx}{order}>: xsd{order} $xsd +{{ + diag xsd ($<[0]) # @@ TMP + + $xsd cxx-tree --std c++11 \ + --generate-inline \ + --generate-serialization \ + --extern-xml-schema xml-schema.xsd \ + --output-dir $out_base \ + $path($<[0]) +}} + +hxx{xml-schema}: $xsd +{{ + diag xsd gen ($>[0]) + + # Note that the specified xml-schema.xsd doesn't exist and is only used to + # deduce the generated header name. + # + $xsd cxx-tree --std c++11 \ + --generate-xml-schema \ + --generate-serialization \ + --custom-type double=double \ + --hxx-epilogue '#include "double-custom.hxx"' \ + --output-dir $out_base \ + xml-schema.xsd +}} + +cxx.poptions =+ "-I$out_base" "-I$src_base" + +# Define XSD_CXX11 since we include libxsd headers directly. +# +cxx.poptions += -DXSD_CXX11 diff --git a/xsd-examples/cxx/tree/custom/double/double-custom.cxx b/xsd-examples/cxx/tree/custom/double/double-custom.cxx new file mode 100644 index 0000000..bfec6e0 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/double/double-custom.cxx @@ -0,0 +1,96 @@ +// file : cxx/tree/custom/double/double-custom.cxx +// copyright : not copyrighted - public domain + +// Include xml-schema.hxx instead of double-custom.hxx here. +// +#include "xml-schema.hxx" + +#include +#include +#include + +#include +#include + +using namespace std; + +// Parsing. +// +namespace xsd +{ + namespace cxx + { + namespace tree + { + double traits:: + create (const std::string& s, + const xercesc::DOMElement*, + flags, + type*) + { + // This type cannot have whitespaces in its values. As result we + // don't need to waste time collapsing whitespaces. All we need to + // do is trim the string representation which can be done without + // copying. + // + ro_string tmp (s); + trim (tmp); + + zc_istream is (tmp); + is.imbue (locale::classic ()); + + double t; + is >> t; + + return t; + } + } + } +} + +// Serialization. +// +namespace XERCES_CPP_NAMESPACE +{ + void + operator<< (xercesc::DOMElement& e, const xml_schema::as_double& d) + { + ostringstream os; + os.imbue (locale::classic ()); + + os.precision (2); + os << fixed << d.x; + + e << os.str (); + } + + void + operator<< (xercesc::DOMAttr& a, const xml_schema::as_double& d) + { + ostringstream os; + os.imbue (locale::classic ()); + + os.precision (2); + os << fixed << d.x; + + a << os.str (); + } +} + +namespace xsd +{ + namespace cxx + { + namespace tree + { + void + operator<< (xml_schema::list_stream& ls, + const xml_schema::as_double& d) + { + ls.os_.imbue (locale::classic ()); + ls.os_.precision (2); + ls.os_ << fixed << d.x; + } + } + } +} diff --git a/xsd-examples/cxx/tree/custom/double/double-custom.hxx b/xsd-examples/cxx/tree/custom/double/double-custom.hxx new file mode 100644 index 0000000..cb74442 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/double/double-custom.hxx @@ -0,0 +1,67 @@ +// file : cxx/tree/custom/double/double-custom.hxx +// copyright : not copyrighted - public domain + +// Do not include this file directly, use xml-schema.hxx instead. This +// file is included into generated xml-schema.hxx so we do not need to +// guard against multiple inclusions. +// + +#include // xml::transcode +#include // text_content + +// Parsing. +// +namespace xsd +{ + namespace cxx + { + namespace tree + { + template<> + struct traits + { + static double + create (const xercesc::DOMElement& e, flags f, type* c) + { + return create (text_content (e), 0, f, c); + } + + static double + create (const xercesc::DOMAttr& a, flags f, type* c) + { + return create (xml::transcode (a.getValue ()), 0, f, c); + } + + static double + create (const std::string& s, + const xercesc::DOMElement*, + flags, + type*); + }; + } + } +} + +// Serialization. +// +namespace XERCES_CPP_NAMESPACE +{ + void + operator<< (xercesc::DOMElement& e, const xml_schema::as_double& d); + + void + operator<< (xercesc::DOMAttr& a, const xml_schema::as_double& d); +} + +namespace xsd +{ + namespace cxx + { + namespace tree + { + void + operator<< (xml_schema::list_stream& ls, + const xml_schema::as_double& d); + } + } +} diff --git a/xsd-examples/cxx/tree/custom/double/driver.cxx b/xsd-examples/cxx/tree/custom/double/driver.cxx new file mode 100644 index 0000000..e3f1800 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/double/driver.cxx @@ -0,0 +1,31 @@ +// file : cxx/tree/custom/double/driver.cxx +// copyright : not copyrighted - public domain + +#include + +#include "order.hxx" + +using std::cerr; +using std::endl; + +int +main () +{ + try + { + // Order one Airbus A380. + // + order o; + o.item ().push_back (item ("Airbus A380", 317000000.90)); + + + // Serialize. + // + order_ (std::cout, o); + } + catch (const xml_schema::exception& e) + { + cerr << e << endl; + return 1; + } +} diff --git a/xsd-examples/cxx/tree/custom/double/order.xsd b/xsd-examples/cxx/tree/custom/double/order.xsd new file mode 100644 index 0000000..8066975 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/double/order.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/xsd-examples/cxx/tree/custom/mixed/.gitignore b/xsd-examples/cxx/tree/custom/mixed/.gitignore new file mode 100644 index 0000000..83d0a51 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/mixed/.gitignore @@ -0,0 +1 @@ +people.?xx diff --git a/xsd-examples/cxx/tree/custom/mixed/README b/xsd-examples/cxx/tree/custom/mixed/README new file mode 100644 index 0000000..7b56812 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/mixed/README @@ -0,0 +1,50 @@ +This example shows how to use type customization to parse and serialize +mixed content. The example achieves this by customizing the type with +the mixed content model to include a DOM document that stores the data +as a raw XML representation. The customized type also provides its own +parsing constructor and serialization operator where the mixed content +is extracted from and inserted back to DOM, respectively. The use of +DOM for mixed content storage is one of the options. You may find other +data structures (e.g., a string) more suitable depending on your situation. + +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 person record vocabulary. Each + record includes the bio element which represents arbitrary XHTML + fragments as mixed content. + +people.xml + Sample XML instance document. + +people.hxx +people.ixx +people.cxx + C++ types that represent the given vocabulary, a set of parsing + functions that convert XML instance documents to a tree-like in-memory + object model, and a set of serialization functions that convert the + object model back to XML. These are generated by XSD from people.xsd + with the --custom-type option in order to customize the bio type. + +people-custom.hxx + Header file which defines our own bio class by inheriting from the + generated bio_base. It is included at the end of people.hxx using + the --hxx-epilogue option. + +people-custom.cxx + Source file which contains the implementation of our bio class. + +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 data to STDERR, including the bio information converted to text. + Finally, the driver serializes the object model back to XML. + +To run the example on the sample XML instance document simply execute: + +$ ./driver people.xml diff --git a/xsd-examples/cxx/tree/custom/mixed/buildfile b/xsd-examples/cxx/tree/custom/mixed/buildfile new file mode 100644 index 0000000..9da936e --- /dev/null +++ b/xsd-examples/cxx/tree/custom/mixed/buildfile @@ -0,0 +1,30 @@ +# file : cxx/tree/custom/mixed/buildfile +# license : not copyrighted - public domain + +import libs = libxsd%lib{xsd} +import libs += libxerces-c%lib{xerces-c} + +./: exe{driver} doc{README} + +exe{driver}: {hxx cxx}{* -people} {hxx ixx cxx}{people} $libs + +exe{driver}: xml{people}: test.input = true + +<{hxx ixx cxx}{people}>: xsd{people} $xsd +{{ + diag xsd ($<[0]) # @@ TMP + + $xsd cxx-tree --std c++11 \ + --generate-inline \ + --generate-serialization \ + --custom-type bio=/bio_base \ + --hxx-epilogue '#include "people-custom.hxx"' \ + --output-dir $out_base \ + $path($<[0]) +}} + +cxx.poptions =+ "-I$out_base" "-I$src_base" + +# Define XSD_CXX11 since we include libxsd headers directly. +# +cxx.poptions += -DXSD_CXX11 diff --git a/xsd-examples/cxx/tree/custom/mixed/driver.cxx b/xsd-examples/cxx/tree/custom/mixed/driver.cxx new file mode 100644 index 0000000..08c83e0 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/mixed/driver.cxx @@ -0,0 +1,122 @@ +// file : cxx/tree/custom/mixed/driver.cxx +// copyright : not copyrighted - public domain + +#include // std::unique_ptr +#include + +#include +#include + +#include "people.hxx" + +// The following transcode() utility function is handy when working with +// Xerces. Include it after the generated header in order to get only char +// or wchar_t version depending on how you compiled your schemas. +// +#include + +using std::cerr; +using std::endl; +using namespace xercesc; + +void +xhtml2txt (const DOMElement*); + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " people.xml" << endl; + return 1; + } + + int r (0); + + // The Xerces-C++ DOM document that will be used to store the XHTML + // fragments "out-live" the call to the parsing function. Therefore + // we need to initialize the Xerces-C++ runtime ourselves. + // + XMLPlatformUtils::Initialize (); + + try + { + using namespace people; + + // Parse. + // + std::unique_ptr d ( + directory_ (argv[1], xml_schema::flags::dont_initialize)); + + // Print what we've got. + // + const directory::person_sequence& s (d->person ()); + + for (directory::person_const_iterator i (s.begin ()); i != s.end (); ++i) + { + cerr << "First : " << i->first_name () << endl + << "Last : " << i->last_name () << endl + << "Gender : " << i->gender () << endl + << "Age : " << i->age () << endl; + + const bio& b (i->bio ()); + const DOMElement* xhtml (b.xhtml ()); + + if (xhtml != 0) + { + cerr << "Bio : " << endl; + xhtml2txt (xhtml); + } + + cerr << endl; + } + + // Serialize. + // + xml_schema::namespace_infomap map; + + map["ppl"].name = "http://www.codesynthesis.com/people"; + map["ppl"].schema = "people.xsd"; + + directory_ ( + std::cout, *d, map, "UTF-8", xml_schema::flags::dont_initialize); + } + catch (const xml_schema::exception& e) + { + cerr << e << endl; + r = 1; + } + + XMLPlatformUtils::Terminate (); + return r; +} + +// Primitive XHTML to text converter that just prints all the text +// nodes and ignores everything else. +// +void +xhtml2txt (const DOMElement* e) +{ + namespace xml = xsd::cxx::xml; + + for (const DOMNode* n (e->getFirstChild ()); + n != 0; + n = n->getNextSibling ()) + { + switch (n->getNodeType ()) + { + case DOMNode::TEXT_NODE: + { + cerr << xml::transcode (n->getTextContent ()); + break; + } + case DOMNode::ELEMENT_NODE: + { + xhtml2txt (static_cast (n)); + break; + } + default: + break; // Ignore all other nodes (e.g., comments, etc). + } + } +} diff --git a/xsd-examples/cxx/tree/custom/mixed/people-custom.cxx b/xsd-examples/cxx/tree/custom/mixed/people-custom.cxx new file mode 100644 index 0000000..bd03fcc --- /dev/null +++ b/xsd-examples/cxx/tree/custom/mixed/people-custom.cxx @@ -0,0 +1,89 @@ +// file : cxx/tree/custom/mixed/people-custom.cxx +// copyright : not copyrighted - public domain + +#include + +// Include people.hxx instead of people-custom.hxx here. +// +#include "people.hxx" + +namespace people +{ + using namespace xercesc; + + const XMLCh ls[] = {chLatin_L, chLatin_S, chNull}; + + bio:: + bio () + : xhtml_ (0) + { + DOMImplementation* impl ( + DOMImplementationRegistry::getDOMImplementation (ls)); + + doc_.reset (impl->createDocument ()); + } + + bio:: + bio (const DOMElement& e, + xml_schema::flags f, + xml_schema::container* c) + : bio_base (e, f, c), xhtml_ (0) + { + DOMImplementation* impl ( + DOMImplementationRegistry::getDOMImplementation (ls)); + + doc_.reset (impl->createDocument ()); + + // Copy the xhtml element. Assume the first child element in + // e is always xhtml. + // + for (DOMNode* n (e.getFirstChild ()); n != 0; n = n->getNextSibling ()) + { + if (n->getNodeType () == DOMNode::ELEMENT_NODE) + { + xhtml_ = static_cast (doc_->importNode (n, true)); + break; + } + } + } + + bio:: + bio (const bio& d, + xml_schema::flags f, + xml_schema::container* c) + : bio_base (d, f, c), xhtml_ (0) + { + DOMImplementation* impl ( + DOMImplementationRegistry::getDOMImplementation (ls)); + + doc_.reset (impl->createDocument ()); + + xhtml_ = static_cast ( + doc_->importNode (const_cast (d.xhtml_), true)); + } + + bio* bio:: + _clone (xml_schema::flags f, xml_schema::container* c) const + { + return new bio (*this, f, c); + } + + void + operator<< (DOMElement& e, const bio& x) + { + // Allow our base to serialize first. + // + const bio_base& b (x); + e << b; + + // Copy the XHTML fragment if we have one. + // + const DOMElement* xhtml (x.xhtml ()); + + if (xhtml != 0) + { + DOMDocument* doc (e.getOwnerDocument ()); + e.appendChild (doc->importNode (const_cast (xhtml), true)); + } + } +} diff --git a/xsd-examples/cxx/tree/custom/mixed/people-custom.hxx b/xsd-examples/cxx/tree/custom/mixed/people-custom.hxx new file mode 100644 index 0000000..2ab949d --- /dev/null +++ b/xsd-examples/cxx/tree/custom/mixed/people-custom.hxx @@ -0,0 +1,83 @@ +// file : cxx/tree/custom/mixed/people-custom.hxx +// 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 +#include + +namespace people +{ + class bio: public bio_base + { + // Standard constructors. + // + public: + bio (); + + bio (const xercesc::DOMElement&, + xml_schema::flags = 0, + xml_schema::container* = 0); + + bio (const bio&, + xml_schema::flags = 0, + xml_schema::container* = 0); + + virtual bio* + _clone (xml_schema::flags = 0, + xml_schema::container* = 0) const; + + // XHTML bio as a DOM document. + // + public: + const xercesc::DOMElement* + xhtml () const + { + return xhtml_; + } + + xercesc::DOMElement* + xhtml () + { + return xhtml_; + } + + // The element should belong to the DOMDocument returned by + // the dom_document() functions. + // + void + xhtml (xercesc::DOMElement* e) + { + assert (e->getOwnerDocument () == doc_.get ()); + + if (xhtml_ != 0) + xhtml_->release (); + + xhtml_ = e; + } + + const xercesc::DOMDocument& + dom_document () const + { + return *doc_; + } + + xercesc::DOMDocument& + dom_document () + { + return *doc_; + } + + private: + xercesc::DOMElement* xhtml_; + xml_schema::dom::unique_ptr doc_; + }; + + // Serialization operator. + // + void + operator<< (xercesc::DOMElement&, const bio&); +} diff --git a/xsd-examples/cxx/tree/custom/mixed/people.xml b/xsd-examples/cxx/tree/custom/mixed/people.xml new file mode 100644 index 0000000..4033f95 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/mixed/people.xml @@ -0,0 +1,38 @@ + + + + + + + + John + Doe + male + 32 + + +

Married to Jane Doe.

+
+
+
+ + + Jane + Doe + female + 28 + + +

Married to John Doe.

+
+
+
+ +
diff --git a/xsd-examples/cxx/tree/custom/mixed/people.xsd b/xsd-examples/cxx/tree/custom/mixed/people.xsd new file mode 100644 index 0000000..739861b --- /dev/null +++ b/xsd-examples/cxx/tree/custom/mixed/people.xsd @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xsd-examples/cxx/tree/custom/taxonomy/.gitignore b/xsd-examples/cxx/tree/custom/taxonomy/.gitignore new file mode 100644 index 0000000..71428ab --- /dev/null +++ b/xsd-examples/cxx/tree/custom/taxonomy/.gitignore @@ -0,0 +1,2 @@ +people.?xx +people-fwd.hxx diff --git a/xsd-examples/cxx/tree/custom/taxonomy/README b/xsd-examples/cxx/tree/custom/taxonomy/README new file mode 100644 index 0000000..c2e425a --- /dev/null +++ b/xsd-examples/cxx/tree/custom/taxonomy/README @@ -0,0 +1,53 @@ +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 customize the person, superman, and + batman types. Generation of the people-fwd.hxx forward declaration + file is requested with the --generate-forward option. Note also that + we use the --generate-polymorphic command line option as well as + --polymorphic-type to mark the type hierarchy starting with the + person type as polymorphic. + +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/xsd-examples/cxx/tree/custom/taxonomy/buildfile b/xsd-examples/cxx/tree/custom/taxonomy/buildfile new file mode 100644 index 0000000..9267c68 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/taxonomy/buildfile @@ -0,0 +1,31 @@ +# file : cxx/tree/custom/taxonomy/buildfile +# license : not copyrighted - public domain + +import libs = libxsd%lib{xsd} +import libs += libxerces-c%lib{xerces-c} + +./: exe{driver} doc{README} + +exe{driver}: {hxx cxx}{* -people} {hxx ixx cxx}{people} hxx{people-fwd} $libs + +exe{driver}: xml{people}: test.input = true + +<{hxx ixx cxx}{people} hxx{people-fwd}>: xsd{people} $xsd +{{ + diag xsd ($<[0]) # @@ TMP + + $xsd cxx-tree --std c++11 \ + --generate-inline \ + --generate-forward \ + --generate-polymorphic \ + --polymorphic-type person \ + --custom-type "person=person_impl/person_base" \ + --custom-type "superman=superman_impl/superman_base" \ + --custom-type "batman=batman_impl/batman_base" \ + --fwd-prologue '#include "people-custom-fwd.hxx"' \ + --hxx-prologue '#include "people-custom.hxx"' \ + --output-dir $out_base \ + $path($<[0]) +}} + +cxx.poptions =+ "-I$out_base" "-I$src_base" diff --git a/xsd-examples/cxx/tree/custom/taxonomy/driver.cxx b/xsd-examples/cxx/tree/custom/taxonomy/driver.cxx new file mode 100644 index 0000000..f719bbb --- /dev/null +++ b/xsd-examples/cxx/tree/custom/taxonomy/driver.cxx @@ -0,0 +1,38 @@ +// file : cxx/tree/custom/taxonomy/driver.cxx +// copyright : not copyrighted - public domain + +#include // std::unique_ptr +#include + +#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::unique_ptr 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/xsd-examples/cxx/tree/custom/taxonomy/people-custom-fwd.hxx b/xsd-examples/cxx/tree/custom/taxonomy/people-custom-fwd.hxx new file mode 100644 index 0000000..1b59a54 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/taxonomy/people-custom-fwd.hxx @@ -0,0 +1,19 @@ +// file : cxx/tree/custom/taxonomy/people-custom-fwd.hxx +// 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 + class person_impl; + + template + class superman_impl; + + template + class batman_impl; +} diff --git a/xsd-examples/cxx/tree/custom/taxonomy/people-custom.cxx b/xsd-examples/cxx/tree/custom/taxonomy/people-custom.cxx new file mode 100644 index 0000000..decc847 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/taxonomy/people-custom.cxx @@ -0,0 +1,156 @@ +// file : cxx/tree/custom/taxonomy/people-custom.cxx +// copyright : not copyrighted - public domain + +#include + +// Include people.hxx instead of people-custom.hxx here. +// +#include "people.hxx" + +namespace people +{ + // person_impl + // + template + person_impl:: + person_impl (const xml_schema::string& name) + : base (name) + { + } + + template + person_impl:: + person_impl (const xercesc::DOMElement& e, + xml_schema::flags f, + xml_schema::container* c) + : base (e, f, c) + { + } + + template + person_impl:: + person_impl (const person_impl& p, + xml_schema::flags f, + xml_schema::container* c) + : base (p, f, c) + { + } + + template + person_impl* person_impl:: + _clone (xml_schema::flags f, xml_schema::container* c) const + { + return new person_impl (*this, f, c); + } + + template + void person_impl:: + print (std::ostream& os) const + { + os << this->name () << std::endl; + } + + // Explicitly instantiate person_impl class template for person_base. + // + template class person_impl; + + + // superman_impl + // + template + superman_impl:: + superman_impl (const xml_schema::string& name, bool can_fly) + : base (name, can_fly) + { + } + + template + superman_impl:: + superman_impl (const xercesc::DOMElement& e, + xml_schema::flags f, + xml_schema::container* c) + : base (e, f, c) + { + } + + template + superman_impl:: + superman_impl (const superman_impl& s, + xml_schema::flags f, + xml_schema::container* c) + : base (s, f, c) + { + } + + template + superman_impl* superman_impl:: + _clone (xml_schema::flags f, xml_schema::container* c) const + { + return new superman_impl (*this, f, c); + } + + template + void superman_impl:: + 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; + + + // batman_impl + // + template + batman_impl:: + batman_impl (const xml_schema::string& name, + bool can_fly, + unsigned int wing_span) + : base (name, can_fly, wing_span) + { + } + + template + batman_impl:: + batman_impl (const xercesc::DOMElement& e, + xml_schema::flags f, + xml_schema::container* c) + : base (e, f, c) + { + } + + template + batman_impl:: + batman_impl (const batman_impl& s, + xml_schema::flags f, + xml_schema::container* c) + : base (s, f, c) + { + } + + template + batman_impl* batman_impl:: + _clone (xml_schema::flags f, xml_schema::container* c) const + { + return new batman_impl (*this, f, c); + } + + template + void batman_impl:: + 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; +} diff --git a/xsd-examples/cxx/tree/custom/taxonomy/people-custom.hxx b/xsd-examples/cxx/tree/custom/taxonomy/people-custom.hxx new file mode 100644 index 0000000..58c94c4 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/taxonomy/people-custom.hxx @@ -0,0 +1,105 @@ +// file : cxx/tree/custom/taxonomy/people-custom.hxx +// 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 // std::ostream + +// Include people-fwd.hxx here so that we can refer to the generated +// types. +// +#include "people-fwd.hxx" + +namespace people +{ + // + // + template + class person_impl: public base + { + public: + person_impl (const 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); + + person_impl& + operator= (const person_impl&) = default; + + virtual person_impl* + _clone (xml_schema::flags = 0, + xml_schema::container* = 0) const; + + public: + virtual void + print (std::ostream&) const; + }; + + + // + // + template + class superman_impl: public base + { + public: + superman_impl (const 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; + + superman_impl& + operator= (const superman_impl&) = default; + + public: + virtual void + print (std::ostream&) const; + }; + + + // + // + template + class batman_impl: public base + { + public: + batman_impl (const 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); + + batman_impl& + operator= (const batman_impl&) = default; + + virtual batman_impl* + _clone (xml_schema::flags = 0, + xml_schema::container* = 0) const; + + public: + virtual void + print (std::ostream&) const; + }; +} diff --git a/xsd-examples/cxx/tree/custom/taxonomy/people.xml b/xsd-examples/cxx/tree/custom/taxonomy/people.xml new file mode 100644 index 0000000..831c547 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/taxonomy/people.xml @@ -0,0 +1,26 @@ + + + + + + + + Joe Dirt + + + + James "007" Bond + + + + Bruce Wayne + + + diff --git a/xsd-examples/cxx/tree/custom/taxonomy/people.xsd b/xsd-examples/cxx/tree/custom/taxonomy/people.xsd new file mode 100644 index 0000000..b07f338 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/taxonomy/people.xsd @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xsd-examples/cxx/tree/custom/wildcard/.gitignore b/xsd-examples/cxx/tree/custom/wildcard/.gitignore new file mode 100644 index 0000000..f32cbe8 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/wildcard/.gitignore @@ -0,0 +1 @@ +wildcard.?xx diff --git a/xsd-examples/cxx/tree/custom/wildcard/README b/xsd-examples/cxx/tree/custom/wildcard/README new file mode 100644 index 0000000..70eaea4 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/wildcard/README @@ -0,0 +1,45 @@ +This example shows how to use type customization to parse and serialize +a specific attribute that is matched by a wildcard (anyAttribute). The +example achieves this by customizing the type to include the data +members and accessors/modifiers that represent the attribute as well as +the parsing constructor and serialization operator where the attribute +value is extracted from and inserted back to DOM, respectively. 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: + +wildcard.xsd + XML Schema definition for simple data type and element. + +wildcard.xml + Sample XML instance document. + +wildcard.hxx +wildcard.ixx +wildcard.cxx + C++ types that represent the given vocabulary, a set of parsing + functions that convert XML instance documents to a tree-like in-memory + object model, and a set of serialization functions that convert the + object model back to XML. These are generated by XSD from wildcard.xsd + with the --custom-type option in order to customize the data type. + +wildcard-custom.hxx + Header file which defines our own data class by inheriting from the + generated data_base. It is included at the end of wildcard.hxx using + the --hxx-epilogue option. + +wildcard-custom.cxx + Source file which contains the implementation of our data class. + +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 data to STDERR, including the extra attribute. Finally, the driver + serializes the object model back to XML. + +To run the example on the sample XML instance document simply execute: + +$ ./driver wildcard.xml diff --git a/xsd-examples/cxx/tree/custom/wildcard/buildfile b/xsd-examples/cxx/tree/custom/wildcard/buildfile new file mode 100644 index 0000000..e386709 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/wildcard/buildfile @@ -0,0 +1,27 @@ +# file : cxx/tree/custom/wildcard/buildfile +# license : not copyrighted - public domain + +import libs = libxsd%lib{xsd} +import libs += libxerces-c%lib{xerces-c} + +./: exe{driver} doc{README} + +exe{driver}: {hxx cxx}{* -wildcard} {hxx ixx cxx}{wildcard} $libs + +exe{driver}: xml{wildcard}: test.input = true + +<{hxx ixx cxx}{wildcard}>: xsd{wildcard} $xsd +{{ + diag xsd ($<[0]) # @@ TMP + + $xsd cxx-tree --std c++11 \ + --generate-inline \ + --generate-serialization \ + --generate-ostream \ + --custom-type data=/data_base \ + --hxx-epilogue '#include "wildcard-custom.hxx"' \ + --output-dir $out_base \ + $path($<[0]) +}} + +cxx.poptions =+ "-I$out_base" "-I$src_base" diff --git a/xsd-examples/cxx/tree/custom/wildcard/driver.cxx b/xsd-examples/cxx/tree/custom/wildcard/driver.cxx new file mode 100644 index 0000000..43fae82 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/wildcard/driver.cxx @@ -0,0 +1,47 @@ +// file : cxx/tree/custom/wildcard/driver.cxx +// copyright : not copyrighted - public domain + +#include // std::unique_ptr +#include + +#include "wildcard.hxx" + +using std::cerr; +using std::endl; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " wildcard.xml" << endl; + return 1; + } + + try + { + using namespace wildcard; + + // Parse. + // + std::unique_ptr d (data_ (argv[1])); + + // Print. + // + cerr << *d << endl; + + // Serialize. + // + xml_schema::namespace_infomap map; + + map["wc"].name = "http://www.codesynthesis.com/wildcard"; + map["wc"].schema = "wildcard.xsd"; + + data_ (std::cout, *d, map); + } + catch (const xml_schema::exception& e) + { + cerr << e << endl; + return 1; + } +} diff --git a/xsd-examples/cxx/tree/custom/wildcard/wildcard-custom.cxx b/xsd-examples/cxx/tree/custom/wildcard/wildcard-custom.cxx new file mode 100644 index 0000000..16798d2 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/wildcard/wildcard-custom.cxx @@ -0,0 +1,84 @@ +// file : cxx/tree/custom/wildcard/wildcard-custom.cxx +// copyright : not copyrighted - public domain + +#include + +// Include wildcard.hxx instead of wildcard-custom.hxx here. +// +#include "wildcard.hxx" + +namespace wildcard +{ + data:: + data (const xml_schema::string& d) + : data_base (d), scope_present_ (false) + { + } + + data:: + data (const xercesc::DOMElement& e, + xml_schema::flags f, + xml_schema::container* c) + : data_base (e, f, c), scope_present_ (false) + { + // Check if we've got the scope attribute. + // + namespace xml = xsd::cxx::xml; + xml::string name ("scope"); + + if (e.hasAttribute (name.c_str ())) + { + scope (xml::transcode (e.getAttribute (name.c_str ()))); + } + } + + data:: + data (const data& d, + xml_schema::flags f, + xml_schema::container* c) + : data_base (d, f, c), + scope_present_ (d.scope_present_), + scope_ (d.scope_) + { + } + + data* data:: + _clone (xml_schema::flags f, xml_schema::container* c) const + { + return new data (*this, f, c); + } + + void + operator<< (xercesc::DOMElement& e, const data& x) + { + // Use our base to serialize data and id. + // + const data_base& b (x); + e << b; + + // Add the scope attribute if present. + // + if (x.scope_present ()) + { + namespace xml = xsd::cxx::xml; + xml::string name ("scope"); + xml::string value (x.scope ()); + + e.setAttribute (name.c_str (), value.c_str ()); + } + } + + std::ostream& + operator<< (std::ostream& os, const data& x) + { + // Use our base to print date and id. + // + const data_base& b (x); + os << b; + + if (x.scope_present ()) + os << std::endl << "scope: " << x.scope (); + + return os; + } +} diff --git a/xsd-examples/cxx/tree/custom/wildcard/wildcard-custom.hxx b/xsd-examples/cxx/tree/custom/wildcard/wildcard-custom.hxx new file mode 100644 index 0000000..e789a86 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/wildcard/wildcard-custom.hxx @@ -0,0 +1,66 @@ +// file : cxx/tree/custom/wildcard/wildcard-custom.hxx +// copyright : not copyrighted - public domain + +// Do not include this file directly, use wildcard.hxx instead. This +// file is included into generated wildcard.hxx so we do not need to +// guard against multiple inclusions. +// + +namespace wildcard +{ + class data: public data_base + { + // Standard constructors. + // + public: + data (const xml_schema::string&); + + data (const xercesc::DOMElement&, + xml_schema::flags = 0, + xml_schema::container* = 0); + + data (const data&, + xml_schema::flags = 0, + xml_schema::container* = 0); + + virtual data* + _clone (xml_schema::flags = 0, + xml_schema::container* = 0) const; + + // Our customizations. + // + public: + bool + scope_present () const + { + return scope_present_; + } + + const xml_schema::string& + scope () const + { + return scope_; + } + + void + scope (const xml_schema::string& s) + { + scope_present_ = true; + scope_ = s; + } + + private: + bool scope_present_; + xml_schema::string scope_; + }; + + // Serialization operator. + // + void + operator<< (xercesc::DOMElement&, const data&); + + // std::ostream insertion operator. + // + std::ostream& + operator<< (std::ostream&, const data&); +} diff --git a/xsd-examples/cxx/tree/custom/wildcard/wildcard.xml b/xsd-examples/cxx/tree/custom/wildcard/wildcard.xml new file mode 100644 index 0000000..8f6ba65 --- /dev/null +++ b/xsd-examples/cxx/tree/custom/wildcard/wildcard.xml @@ -0,0 +1,14 @@ + + + + +abc123 diff --git a/xsd-examples/cxx/tree/custom/wildcard/wildcard.xsd b/xsd-examples/cxx/tree/custom/wildcard/wildcard.xsd new file mode 100644 index 0000000..a19be3f --- /dev/null +++ b/xsd-examples/cxx/tree/custom/wildcard/wildcard.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + -- cgit v1.1