From f0510d2f90467de8e8f260b47d79a9baaf9bef17 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 17 Sep 2009 07:15:29 +0200 Subject: Start tracking XSD with git --- examples/cxx/tree/custom/double/README | 62 +++++++++++++++ examples/cxx/tree/custom/double/double-custom.cxx | 97 +++++++++++++++++++++++ examples/cxx/tree/custom/double/double-custom.hxx | 68 ++++++++++++++++ examples/cxx/tree/custom/double/driver.cxx | 32 ++++++++ examples/cxx/tree/custom/double/makefile | 79 ++++++++++++++++++ examples/cxx/tree/custom/double/order.xsd | 26 ++++++ 6 files changed, 364 insertions(+) create mode 100644 examples/cxx/tree/custom/double/README create mode 100644 examples/cxx/tree/custom/double/double-custom.cxx create mode 100644 examples/cxx/tree/custom/double/double-custom.hxx create mode 100644 examples/cxx/tree/custom/double/driver.cxx create mode 100644 examples/cxx/tree/custom/double/makefile create mode 100644 examples/cxx/tree/custom/double/order.xsd (limited to 'examples/cxx/tree/custom/double') diff --git a/examples/cxx/tree/custom/double/README b/examples/cxx/tree/custom/double/README new file mode 100644 index 0000000..15348d2 --- /dev/null +++ b/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/examples/cxx/tree/custom/double/double-custom.cxx b/examples/cxx/tree/custom/double/double-custom.cxx new file mode 100644 index 0000000..78904a0 --- /dev/null +++ b/examples/cxx/tree/custom/double/double-custom.cxx @@ -0,0 +1,97 @@ +// file : examples/cxx/tree/custom/double/double-custom.cxx +// author : Boris Kolpackov +// 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/examples/cxx/tree/custom/double/double-custom.hxx b/examples/cxx/tree/custom/double/double-custom.hxx new file mode 100644 index 0000000..17d9a44 --- /dev/null +++ b/examples/cxx/tree/custom/double/double-custom.hxx @@ -0,0 +1,68 @@ +// file : examples/cxx/tree/custom/double/double-custom.hxx +// author : Boris Kolpackov +// 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/examples/cxx/tree/custom/double/driver.cxx b/examples/cxx/tree/custom/double/driver.cxx new file mode 100644 index 0000000..2e5b44d --- /dev/null +++ b/examples/cxx/tree/custom/double/driver.cxx @@ -0,0 +1,32 @@ +// file : examples/cxx/tree/custom/double/driver.cxx +// author : Boris Kolpackov +// 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/examples/cxx/tree/custom/double/makefile b/examples/cxx/tree/custom/double/makefile new file mode 100644 index 0000000..249ed01 --- /dev/null +++ b/examples/cxx/tree/custom/double/makefile @@ -0,0 +1,79 @@ +# file : examples/cxx/tree/custom/double/makefile +# author : Boris Kolpackov +# copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../../build/bootstrap.make + +xsd := order.xsd +cxx := driver.cxx double-custom.cxx + +obj := $(addprefix $(out_base)/,$(cxx:.cxx=.o) $(xsd:.xsd=.o)) +dep := $(obj:.o=.o.d) + +driver := $(out_base)/driver +clean := $(out_base)/.clean + + +# Import. +# +$(call import,\ + $(scf_root)/import/libxerces-c/stub.make,\ + l: xerces_c.l,cpp-options: xerces_c.l.cpp-options) + + +# Build. +# +$(driver): $(obj) $(xerces_c.l) + +$(obj) $(dep): cpp_options := -I$(src_root)/libxsd +$(obj) $(dep): $(xerces_c.l.cpp-options) + +$(out_base)/xml-schema.hxx: $(out_root)/xsd/xsd + $(call message,xsd $(src_base)/xml-schema.xsd,\ +$(out_root)/xsd/xsd cxx-tree --output-dir $(out_base) --generate-xml-schema \ +--generate-serialization --custom-type double=double \ +--hxx-epilogue '\#include "double-custom.hxx"' xml-schema.xsd) + +$(out_base)/$(xsd:.xsd=.hxx) \ +$(out_base)/$(xsd:.xsd=.ixx) \ +$(out_base)/$(xsd:.xsd=.cxx): xsd := $(out_root)/xsd/xsd + +$(out_base)/$(xsd:.xsd=.hxx) \ +$(out_base)/$(xsd:.xsd=.ixx) \ +$(out_base)/$(xsd:.xsd=.cxx): xsd_options := \ +--generate-serialization --extern-xml-schema xml-schema.xsd + +$(out_base)/$(xsd:.xsd=.hxx) \ +$(out_base)/$(xsd:.xsd=.ixx) \ +$(out_base)/$(xsd:.xsd=.cxx): $(out_root)/xsd/xsd + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +.PHONY: $(out_base)/ +$(out_base)/: $(driver) + + +# Clean. +# +.PHONY: $(clean) + +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean)) + $(call message,rm $$1,rm -f $$1,$(out_base)/xml-schema.hxx) + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(scf_root)/xsd/tree/xsd-cxx.make) + +# Dependencies. +# +$(call import,$(src_root)/xsd/makefile) diff --git a/examples/cxx/tree/custom/double/order.xsd b/examples/cxx/tree/custom/double/order.xsd new file mode 100644 index 0000000..0d7fe05 --- /dev/null +++ b/examples/cxx/tree/custom/double/order.xsd @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + -- cgit v1.1