From a15cf65c44d5c224169c32ef5495b68c758134b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 18 May 2014 16:08:14 +0200 Subject: Imported Upstream version 3.3.0.2 --- xsd/examples/cxx/tree/messaging/README | 58 +++++++++ xsd/examples/cxx/tree/messaging/balance.xml | 17 +++ xsd/examples/cxx/tree/messaging/deposit.xml | 18 +++ xsd/examples/cxx/tree/messaging/dom-parse.cxx | 125 +++++++++++++++++++ xsd/examples/cxx/tree/messaging/dom-parse.hxx | 23 ++++ xsd/examples/cxx/tree/messaging/dom-serialize.cxx | 89 +++++++++++++ xsd/examples/cxx/tree/messaging/dom-serialize.hxx | 21 ++++ xsd/examples/cxx/tree/messaging/driver.cxx | 145 ++++++++++++++++++++++ xsd/examples/cxx/tree/messaging/makefile | 118 ++++++++++++++++++ xsd/examples/cxx/tree/messaging/protocol.xsd | 54 ++++++++ xsd/examples/cxx/tree/messaging/withdraw.xml | 18 +++ 11 files changed, 686 insertions(+) create mode 100644 xsd/examples/cxx/tree/messaging/README create mode 100644 xsd/examples/cxx/tree/messaging/balance.xml create mode 100644 xsd/examples/cxx/tree/messaging/deposit.xml create mode 100644 xsd/examples/cxx/tree/messaging/dom-parse.cxx create mode 100644 xsd/examples/cxx/tree/messaging/dom-parse.hxx create mode 100644 xsd/examples/cxx/tree/messaging/dom-serialize.cxx create mode 100644 xsd/examples/cxx/tree/messaging/dom-serialize.hxx create mode 100644 xsd/examples/cxx/tree/messaging/driver.cxx create mode 100644 xsd/examples/cxx/tree/messaging/makefile create mode 100644 xsd/examples/cxx/tree/messaging/protocol.xsd create mode 100644 xsd/examples/cxx/tree/messaging/withdraw.xml (limited to 'xsd/examples/cxx/tree/messaging') diff --git a/xsd/examples/cxx/tree/messaging/README b/xsd/examples/cxx/tree/messaging/README new file mode 100644 index 0000000..435a4cf --- /dev/null +++ b/xsd/examples/cxx/tree/messaging/README @@ -0,0 +1,58 @@ +This example shows how to handle XML vocabularies with multiple +root elements using the element type and element map features +of the C++/Tree mapping. The main purpose of element types is +to distinguish object models with the same root type but with +different root elements. The element map allows uniform parsing +and serialization of multiple root elements. + +The example consists of the following files: + +protocol.xsd + XML Schema which defines a simple bank account protocol with + requests such as withdraw and deposit. Note that some request + and response elements are of the same type. + +balance.xml +withdraw.xml +deposit.xml + Sample XML instances for the protocol requests. + +protocol.hxx +protocol.cxx + C++ types that represent the given vocabulary. These are + generated by the XSD compiler from protocol.xsd. Generation of + element types instead of parsing and serialization functions is + requested with the --generate-element-type option. Generation of + the element map is requested with the --generate-element-map + option. + +dom-parse.hxx +dom-parse.cxx + Definition and implementation of the parse() function that + parses an XML document to a DOM document. + +dom-serialize.hxx +dom-serialize.cxx + Definition and implementation of the serialize() function that + serializes a DOM document to XML. + +driver.cxx + Driver for the example. It first calls the above-mentioned parse() + function to parse the input file to a DOM document. It then calls + the parse() function on the element map to parse the root document + element to the object model. The object model is returned as a + pointer to xml_schema::element_type which is a common base type for + all element types. The driver then determines which request it has + received either using RTTI or by comparing the root element names. + Once the request type is determined, information about it is printed + to STDERR and the corresponding response is created. Finally, the + driver serializes the opaque response object to a DOM document + using the element map and then serializes this DOM document to + STDOUT using the above-mentioned serialize() function. + +To run the example on the sample XML request documents simply +execute: + +$ ./driver balance.xml +$ ./driver withdraw.xml +$ ./driver deposit.xml diff --git a/xsd/examples/cxx/tree/messaging/balance.xml b/xsd/examples/cxx/tree/messaging/balance.xml new file mode 100644 index 0000000..57eeaed --- /dev/null +++ b/xsd/examples/cxx/tree/messaging/balance.xml @@ -0,0 +1,17 @@ + + + + + + + 123456789 + + diff --git a/xsd/examples/cxx/tree/messaging/deposit.xml b/xsd/examples/cxx/tree/messaging/deposit.xml new file mode 100644 index 0000000..9da3c59 --- /dev/null +++ b/xsd/examples/cxx/tree/messaging/deposit.xml @@ -0,0 +1,18 @@ + + + + + + + 123456789 + 1000000 + + diff --git a/xsd/examples/cxx/tree/messaging/dom-parse.cxx b/xsd/examples/cxx/tree/messaging/dom-parse.cxx new file mode 100644 index 0000000..e4bc6cc --- /dev/null +++ b/xsd/examples/cxx/tree/messaging/dom-parse.cxx @@ -0,0 +1,125 @@ +// file : examples/cxx/tree/messaging/dom-parse.cxx +// author : Boris Kolpackov +// 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::auto_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)); + +#if _XERCES_VERSION >= 30000 + + // Xerces-C++ 3.0.0 and later. + // + xml::dom::auto_ptr parser ( + impl->createLSParser (DOMImplementationLS::MODE_SYNCHRONOUS, 0)); + + DOMConfiguration* conf (parser->getDomConfig ()); + + // Discard comment nodes in the document. + // + conf->setParameter (XMLUni::fgDOMComments, false); + + // 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); + +#else // _XERCES_VERSION >= 30000 + + // Same as above but for Xerces-C++ 2 series. + // + xml::dom::auto_ptr parser ( + impl->createDOMBuilder (DOMImplementationLS::MODE_SYNCHRONOUS, 0)); + + parser->setFeature (XMLUni::fgDOMComments, false); + parser->setFeature (XMLUni::fgDOMDatatypeNormalization, true); + parser->setFeature (XMLUni::fgDOMEntities, false); + parser->setFeature (XMLUni::fgDOMNamespaces, true); + parser->setFeature (XMLUni::fgDOMWhitespaceInElementContent, false); + parser->setFeature (XMLUni::fgDOMValidation, validate); + parser->setFeature (XMLUni::fgXercesSchema, validate); + parser->setFeature (XMLUni::fgXercesSchemaFullChecking, false); + parser->setFeature (XMLUni::fgXercesUserAdoptsDOMDocument, true); + + tree::error_handler eh; + xml::dom::bits::error_handler_proxy ehp (eh); + parser->setErrorHandler (&ehp); + +#endif // _XERCES_VERSION >= 30000 + + // Prepare input stream. + // + xml::sax::std_input_source isrc (is, id); + Wrapper4InputSource wrap (&isrc, false); + +#if _XERCES_VERSION >= 30000 + xml::dom::auto_ptr doc (parser->parse (&wrap)); +#else + xml::dom::auto_ptr doc (parser->parse (wrap)); +#endif + + eh.throw_if_failed > (); + + return doc; +} diff --git a/xsd/examples/cxx/tree/messaging/dom-parse.hxx b/xsd/examples/cxx/tree/messaging/dom-parse.hxx new file mode 100644 index 0000000..640b28a --- /dev/null +++ b/xsd/examples/cxx/tree/messaging/dom-parse.hxx @@ -0,0 +1,23 @@ +// file : examples/cxx/tree/messaging/dom-parse.hxx +// author : Boris Kolpackov +// 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::auto_ptr +parse (std::istream& is, + const std::string& id, + bool validate); + +#endif // DOM_PARSE diff --git a/xsd/examples/cxx/tree/messaging/dom-serialize.cxx b/xsd/examples/cxx/tree/messaging/dom-serialize.cxx new file mode 100644 index 0000000..c0f4311 --- /dev/null +++ b/xsd/examples/cxx/tree/messaging/dom-serialize.cxx @@ -0,0 +1,89 @@ +// file : examples/cxx/tree/messaging/dom-serialize.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include "dom-serialize.hxx" + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +using namespace xercesc; +namespace xml = xsd::cxx::xml; +namespace tree = xsd::cxx::tree; + +void +serialize (std::ostream& os, + const xercesc::DOMDocument& doc, + const std::string& encoding) +{ + const XMLCh ls_id [] = {chLatin_L, chLatin_S, chNull}; + + // Get an implementation of the Load-Store (LS) interface. + // + DOMImplementation* impl ( + DOMImplementationRegistry::getDOMImplementation (ls_id)); + + tree::error_handler eh; + xml::dom::bits::error_handler_proxy ehp (eh); + + xml::dom::ostream_format_target oft (os); + +#if _XERCES_VERSION >= 30000 + + // Create a DOMSerializer. + // + xml::dom::auto_ptr writer ( + impl->createLSSerializer ()); + + DOMConfiguration* conf (writer->getDomConfig ()); + + // Set error handler. + // + conf->setParameter (XMLUni::fgDOMErrorHandler, &ehp); + + // Set some generally nice features. + // + conf->setParameter (XMLUni::fgDOMWRTDiscardDefaultContent, true); + conf->setParameter (XMLUni::fgDOMWRTFormatPrettyPrint, true); + + xml::dom::auto_ptr out (impl->createLSOutput ()); + out->setEncoding (xml::string (encoding).c_str ()); + out->setByteStream (&oft); + + writer->write (&doc, out.get ()); + +#else + + // Create a DOMWriter. + // + xml::dom::auto_ptr writer (impl->createDOMWriter ()); + + // Set error handler. + // + writer->setErrorHandler (&ehp); + + // Set encoding. + // + writer->setEncoding(xml::string (encoding).c_str ()); + + // Set some generally nice features. + // + writer->setFeature (XMLUni::fgDOMWRTDiscardDefaultContent, true); + writer->setFeature (XMLUni::fgDOMWRTFormatPrettyPrint, true); + + writer->writeNode (&oft, doc); + +#endif + + eh.throw_if_failed > (); +} diff --git a/xsd/examples/cxx/tree/messaging/dom-serialize.hxx b/xsd/examples/cxx/tree/messaging/dom-serialize.hxx new file mode 100644 index 0000000..1a7e855 --- /dev/null +++ b/xsd/examples/cxx/tree/messaging/dom-serialize.hxx @@ -0,0 +1,21 @@ +// file : examples/cxx/tree/messaging/dom-serialize.hxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#ifndef DOM_SERIALIZE +#define DOM_SERIALIZE + +#include +#include + +#include + +// Serialize a DOM document to XML which is written to the standard +// output stream. +// +void +serialize (std::ostream& os, + const xercesc::DOMDocument& doc, + const std::string& encoding = "UTF-8"); + +#endif // DOM_SERIALIZE diff --git a/xsd/examples/cxx/tree/messaging/driver.cxx b/xsd/examples/cxx/tree/messaging/driver.cxx new file mode 100644 index 0000000..4c36aa4 --- /dev/null +++ b/xsd/examples/cxx/tree/messaging/driver.cxx @@ -0,0 +1,145 @@ +// file : examples/cxx/tree/messaging/driver.cxx +// author : Boris Kolpackov +// copyright : not copyrighted - public domain + +#include // std::auto_ptr +#include +#include +#include +#include + +#include +#include + +#include + +#include "dom-parse.hxx" +#include "dom-serialize.hxx" + +#include "protocol.hxx" + +using namespace std; +using namespace protocol; +using namespace xercesc; + +int +main (int argc, char* argv[]) +{ + if (argc != 2) + { + cerr << "usage: " << argv[0] << " request.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. + // + XMLPlatformUtils::Initialize (); + + try + { + ifstream ifs; + ifs.exceptions (ifstream::badbit | ifstream::failbit); + ifs.open (argv[1]); + + auto_ptr req, res; + + // Parse the XML request to a DOM document using the parse() + // function from dom-parse.hxx. + // + { + xml_schema::dom::auto_ptr doc (parse (ifs, argv[1], true)); + DOMElement& root (*doc->getDocumentElement ()); + + req = xml_schema::element_map::parse (root); + } + + // We can test which request we've got either using RTTI or by + // comparing the element names, as shown below. + // + if (balance* b = dynamic_cast (req.get ())) + { + account_t& a (b->value ()); + + cerr << "balance request for acc# " << a.account () << endl; + + res.reset (new success (balance_t (a.account (), 1000))); + } + else if (req->_name () == withdraw::name ()) + { + withdraw& w (static_cast (*req)); + change_t& c (w.value ()); + + wcerr << "withdrawal request for acc# " << c.account () << ", " + << "amount: " << c.amount () << endl; + + if (c.amount () > 1000) + res.reset (new insufficient_funds (balance_t (c.account (), 1000))); + else + res.reset (new success (balance_t (c.account (), 1000 - c.amount ()))); + + } + else if (req->_name () == deposit::name ()) + { + deposit& d (static_cast (*req)); + change_t& c (d.value ()); + + wcerr << "deposit request for acc# " << c.account () << ", " + << "amount: " << c.amount () << endl; + + res.reset (new success (balance_t (c.account (), 1000 + c.amount ()))); + } + + // Serialize the response to a DOM document. + // + namespace xml = xsd::cxx::xml; + + const XMLCh ls_id [] = {chLatin_L, chLatin_S, chNull}; + + DOMImplementation* impl ( + DOMImplementationRegistry::getDOMImplementation (ls_id)); + + const string& name (res->_name ()); + const string& ns (res->_namespace ()); + + xml_schema::dom::auto_ptr doc ( + impl->createDocument ( + xml::string (ns).c_str (), + xml::string ("p:" + name).c_str (), + 0)); + + xml_schema::element_map::serialize (*doc->getDocumentElement (), *res); + + // Serialize the DOM document to XML using the serialize() function + // from dom-serialize.hxx. + // + cout << "response:" << endl + << endl; + + serialize (cout, *doc); + } + catch (const xml_schema::no_element_info& e) + { + // This exception indicates that we tried to parse or serialize + // an unknown element. + // + cerr << "unknown request: " << e.element_namespace () << "#" << + e.element_name () << endl; + r = 1; + } + 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; + } + + XMLPlatformUtils::Terminate (); + return r; +} diff --git a/xsd/examples/cxx/tree/messaging/makefile b/xsd/examples/cxx/tree/messaging/makefile new file mode 100644 index 0000000..b7e0d0a --- /dev/null +++ b/xsd/examples/cxx/tree/messaging/makefile @@ -0,0 +1,118 @@ +# file : examples/cxx/tree/messaging/makefile +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make + +xsd := protocol.xsd +cxx := driver.cxx dom-parse.cxx dom-serialize.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=.o)) +dep := $(obj:.o=.o.d) + +driver := $(out_base)/driver +install := $(out_base)/.install +dist := $(out_base)/.dist +dist-win := $(out_base)/.dist-win +clean := $(out_base)/.clean + + +# Import. +# +$(call import,\ + $(scf_root)/import/libxerces-c/stub.make,\ + l: xerces_c.l,cpp-options: xerces_c.l.cpp-options) + + +# Build. +# +$(driver): $(obj) $(xerces_c.l) + +$(obj) $(dep): cpp_options := -I$(src_root)/libxsd +$(obj) $(dep): $(xerces_c.l.cpp-options) + +genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.ixx) $(xsd:.xsd=.cxx) +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): xsd := $(out_root)/xsd/xsd + +$(gen): xsd_options := --root-element-all \ +--generate-element-type --generate-element-map --generate-serialization + +$(gen): $(out_root)/xsd/xsd + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + + +# Install & Dist. +# +dist-common := $(out_base)/.dist-common + +$(install) $(dist) $(dist-win) $(dist-common): path := $(subst $(src_root)/,,$(src_base)) + +$(install): + $(call install-data,$(src_base)/README,$(install_doc_dir)/xsd/$(path)/README) + $(call install-data,$(src_base)/driver.cxx,$(install_doc_dir)/xsd/$(path)/driver.cxx) + $(call install-data,$(src_base)/protocol.xsd,$(install_doc_dir)/xsd/$(path)/protocol.xsd) + $(call install-data,$(src_base)/balance.xml,$(install_doc_dir)/xsd/$(path)/balance.xml) + $(call install-data,$(src_base)/deposit.xml,$(install_doc_dir)/xsd/$(path)/deposit.xml) + $(call install-data,$(src_base)/withdraw.xml,$(install_doc_dir)/xsd/$(path)/withdraw.xml) + $(call install-data,$(src_base)/dom-parse.hxx,$(install_doc_dir)/xsd/$(path)/dom-parse.hxx) + $(call install-data,$(src_base)/dom-parse.cxx,$(install_doc_dir)/xsd/$(path)/dom-parse.cxx) + $(call install-data,$(src_base)/dom-serialize.hxx,$(install_doc_dir)/xsd/$(path)/dom-serialize.hxx) + $(call install-data,$(src_base)/dom-serialize.cxx,$(install_doc_dir)/xsd/$(path)/dom-serialize.cxx) + +$(dist-common): + $(call install-data,$(src_base)/driver.cxx,$(dist_prefix)/$(path)/driver.cxx) + $(call install-data,$(src_base)/protocol.xsd,$(dist_prefix)/$(path)/protocol.xsd) + $(call install-data,$(src_base)/balance.xml,$(dist_prefix)/$(path)/balance.xml) + $(call install-data,$(src_base)/deposit.xml,$(dist_prefix)/$(path)/deposit.xml) + $(call install-data,$(src_base)/withdraw.xml,$(dist_prefix)/$(path)/withdraw.xml) + $(call install-data,$(src_base)/dom-parse.hxx,$(dist_prefix)/$(path)/dom-parse.hxx) + $(call install-data,$(src_base)/dom-parse.cxx,$(dist_prefix)/$(path)/dom-parse.cxx) + $(call install-data,$(src_base)/dom-serialize.hxx,$(dist_prefix)/$(path)/dom-serialize.hxx) + $(call install-data,$(src_base)/dom-serialize.cxx,$(dist_prefix)/$(path)/dom-serialize.cxx) + +$(dist): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README) + +$(dist-win): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README.txt) + $(call message,,unix2dos $(dist_prefix)/$(path)/README.txt) + + +# Clean. +# +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean)) + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(gen): | $(out_base)/.gitignore +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/install.make) +$(call include,$(scf_root)/xsd/tree/xsd-cxx.make) + +# Dependencies. +# +$(call import,$(src_root)/xsd/makefile) diff --git a/xsd/examples/cxx/tree/messaging/protocol.xsd b/xsd/examples/cxx/tree/messaging/protocol.xsd new file mode 100644 index 0000000..3461133 --- /dev/null +++ b/xsd/examples/cxx/tree/messaging/protocol.xsd @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xsd/examples/cxx/tree/messaging/withdraw.xml b/xsd/examples/cxx/tree/messaging/withdraw.xml new file mode 100644 index 0000000..16a7440 --- /dev/null +++ b/xsd/examples/cxx/tree/messaging/withdraw.xml @@ -0,0 +1,18 @@ + + + + + + + 123456789 + 1000000 + + -- cgit v1.2.3