summaryrefslogtreecommitdiff
path: root/xsd-examples/cxx/tree/custom/double
diff options
context:
space:
mode:
Diffstat (limited to 'xsd-examples/cxx/tree/custom/double')
-rw-r--r--xsd-examples/cxx/tree/custom/double/.gitignore2
-rw-r--r--xsd-examples/cxx/tree/custom/double/README62
-rw-r--r--xsd-examples/cxx/tree/custom/double/buildfile46
-rw-r--r--xsd-examples/cxx/tree/custom/double/double-custom.cxx96
-rw-r--r--xsd-examples/cxx/tree/custom/double/double-custom.hxx67
-rw-r--r--xsd-examples/cxx/tree/custom/double/driver.cxx31
-rw-r--r--xsd-examples/cxx/tree/custom/double/order.xsd25
7 files changed, 329 insertions, 0 deletions
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 <limits>
+#include <locale>
+#include <sstream>
+
+#include <xsd/cxx/ro-string.hxx>
+#include <xsd/cxx/zc-istream.hxx>
+
+using namespace std;
+
+// Parsing.
+//
+namespace xsd
+{
+ namespace cxx
+ {
+ namespace tree
+ {
+ double traits<double, char, schema_type::double_>::
+ 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<char> tmp (s);
+ trim (tmp);
+
+ zc_istream<char> 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 <xsd/cxx/xml/string.hxx> // xml::transcode
+#include <xsd/cxx/tree/text.hxx> // text_content
+
+// Parsing.
+//
+namespace xsd
+{
+ namespace cxx
+ {
+ namespace tree
+ {
+ template<>
+ struct traits<double, char, schema_type::double_>
+ {
+ static double
+ create (const xercesc::DOMElement& e, flags f, type* c)
+ {
+ return create (text_content<char> (e), 0, f, c);
+ }
+
+ static double
+ create (const xercesc::DOMAttr& a, flags f, type* c)
+ {
+ return create (xml::transcode<char> (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 <iostream>
+
+#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 @@
+<?xml version="1.0"?>
+
+<!--
+
+file : cxx/tree/custom/double/order.xsd
+copyright : not copyrighted - public domain
+
+-->
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <xsd:complexType name="item">
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="price" type="xsd:double" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="order">
+ <xsd:sequence>
+ <xsd:element name="item" type="item" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="order" type="order"/>
+
+</xsd:schema>