aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2014-02-25 09:22:06 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2014-02-25 09:22:06 +0200
commit3939c9a6ceebbb237d8bdc041fd11f90ffc3b7ea (patch)
treea9273a78e9406a447976d22a3e2448c8debf5f49 /doc
parent7f2876d1fb227951bf2531847a4f540df7fcbb78 (diff)
Rename documentation/ to doc/
Diffstat (limited to 'doc')
-rw-r--r--doc/cxx/hybrid/guide/figure-1.pngbin0 -> 11933 bytes
-rw-r--r--doc/cxx/hybrid/guide/figure-1.svg217
-rw-r--r--doc/cxx/hybrid/guide/guide.html2ps65
-rw-r--r--doc/cxx/hybrid/guide/index.xhtml6521
-rw-r--r--doc/cxx/hybrid/guide/makefile48
-rw-r--r--doc/cxx/makefile20
-rw-r--r--doc/cxx/parser/guide/figure-1.pngbin0 -> 34195 bytes
-rw-r--r--doc/cxx/parser/guide/figure-1.svg373
-rw-r--r--doc/cxx/parser/guide/guide.html2ps65
-rw-r--r--doc/cxx/parser/guide/index.xhtml5383
-rw-r--r--doc/cxx/parser/guide/makefile48
-rw-r--r--doc/cxx/serializer/guide/figure-1.pngbin0 -> 30198 bytes
-rw-r--r--doc/cxx/serializer/guide/figure-1.svg372
-rw-r--r--doc/cxx/serializer/guide/guide.html2ps65
-rw-r--r--doc/cxx/serializer/guide/index.xhtml6542
-rw-r--r--doc/cxx/serializer/guide/makefile48
-rw-r--r--doc/default.css319
-rw-r--r--doc/makefile158
-rw-r--r--doc/xsde-epilogue.1540
-rw-r--r--doc/xsde-epilogue.xhtml365
-rw-r--r--doc/xsde-hybrid-header.14
-rw-r--r--doc/xsde-hybrid-header.xhtml1
-rw-r--r--doc/xsde-parser-header.14
-rw-r--r--doc/xsde-parser-header.xhtml1
-rw-r--r--doc/xsde-prologue.1171
-rw-r--r--doc/xsde-prologue.xhtml162
-rw-r--r--doc/xsde-serializer-header.14
-rw-r--r--doc/xsde-serializer-header.xhtml1
28 files changed, 21497 insertions, 0 deletions
diff --git a/doc/cxx/hybrid/guide/figure-1.png b/doc/cxx/hybrid/guide/figure-1.png
new file mode 100644
index 0000000..b89cec8
--- /dev/null
+++ b/doc/cxx/hybrid/guide/figure-1.png
Binary files differ
diff --git a/doc/cxx/hybrid/guide/figure-1.svg b/doc/cxx/hybrid/guide/figure-1.svg
new file mode 100644
index 0000000..ccc79cd
--- /dev/null
+++ b/doc/cxx/hybrid/guide/figure-1.svg
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ id="svg2471"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="hybrid.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/boris/hybrid.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs3">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective2477" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:document-units="mm"
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.5980613"
+ inkscape:cx="243.67741"
+ inkscape:cy="741.86348"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1002"
+ inkscape:window-height="853"
+ inkscape:window-x="276"
+ inkscape:window-y="78">
+ <inkscape:grid
+ type="xygrid"
+ id="grid2479" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="opacity:1;fill:#ccdcee;fill-opacity:1;fill-rule:evenodd;stroke:#ccdcee;stroke-width:16.80470467;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect7825"
+ width="203.0603"
+ height="115.96954"
+ x="78.263054"
+ y="236.86377" />
+ <rect
+ style="fill:#6e91bd;fill-opacity:1;fill-rule:evenodd;stroke:#6e91bd;stroke-width:18.24513817;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2489"
+ width="169.64984"
+ height="20.998301"
+ x="95.946136"
+ y="265.48535" />
+ <text
+ xml:space="preserve"
+ style="font-size:10.91242504px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans Mono;-inkscape-font-specification:Bitstream Vera Sans Mono Bold"
+ x="145.5929"
+ y="271.39957"
+ id="text7835"
+ sodipodi:linespacing="100%"
+ transform="scale(0.9741498,1.0265362)"><tspan
+ y="271.39957"
+ x="145.5929"
+ sodipodi:role="line"
+ id="tspan2585">Object Model</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:10.91242504px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans Mono;-inkscape-font-specification:Bitstream Vera Sans Mono Bold"
+ x="151.27502"
+ y="177.57848"
+ id="text2500"
+ sodipodi:linespacing="100%"
+ transform="scale(0.9741498,1.0265362)"><tspan
+ sodipodi:role="line"
+ id="tspan2570"
+ x="151.27502"
+ y="177.57848">Parser</tspan></text>
+ <g
+ id="g2631"
+ transform="matrix(0.7818522,0,0,0.7818522,12.112543,35.072306)">
+ <rect
+ y="355.19925"
+ x="103.22679"
+ height="34.53841"
+ width="84.758575"
+ id="rect2532"
+ style="fill:#6e91bd;fill-opacity:1;fill-rule:evenodd;stroke:#6e91bd;stroke-width:16.53946114;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ transform="scale(0.9741498,1.0265362)"
+ sodipodi:linespacing="100%"
+ id="text2534"
+ y="366.63315"
+ x="124.96281"
+ style="font-size:13.95714664px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans Mono;-inkscape-font-specification:Bitstream Vera Sans Mono Bold"
+ xml:space="preserve"><tspan
+ y="366.63315"
+ x="124.96281"
+ id="tspan2603"
+ sodipodi:role="line">Parser</tspan></text>
+ </g>
+ <g
+ id="g2636"
+ transform="matrix(0.7818522,0,0,0.7818522,18.187466,35.76421)">
+ <rect
+ y="354.78888"
+ x="232.87415"
+ height="34.474037"
+ width="85.579155"
+ id="rect2594"
+ style="fill:#6e91bd;fill-opacity:1;fill-rule:evenodd;stroke:#6e91bd;stroke-width:16.60383415;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ transform="scale(0.9741498,1.0265362)"
+ sodipodi:linespacing="100%"
+ id="text2596"
+ y="367.06186"
+ x="241.66556"
+ style="font-size:13.95714664px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans Mono;-inkscape-font-specification:Bitstream Vera Sans Mono Bold"
+ xml:space="preserve"><tspan
+ y="367.06186"
+ x="241.66556"
+ id="tspan2598"
+ sodipodi:role="line">Serializer</tspan></text>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:10.16407776px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ x="147.14096"
+ y="244.02005"
+ id="text2845"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2610"
+ x="147.14096"
+ y="244.02005">C++/Hybrid</tspan></text>
+ <rect
+ style="opacity:1;fill:#ccdcee;fill-opacity:1;fill-rule:evenodd;stroke:#ccdcee;stroke-width:16.53161621;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2617"
+ width="202.50182"
+ height="30.237684"
+ x="78.263412"
+ y="177.76631" />
+ <text
+ xml:space="preserve"
+ style="font-size:10.16407776px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ x="147.56195"
+ y="196.06781"
+ id="text2619"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2623"
+ x="147.56195"
+ y="196.06781">Application</tspan></text>
+ <rect
+ style="opacity:1;fill:#ccdcee;fill-opacity:1;fill-rule:evenodd;stroke:#ccdcee;stroke-width:15.20303345;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2641"
+ width="85.640442"
+ height="29.708515"
+ x="77.687241"
+ y="382.08945" />
+ <rect
+ style="opacity:1;fill:#ccdcee;fill-opacity:1;fill-rule:evenodd;stroke:#ccdcee;stroke-width:15.19906044;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2643"
+ width="85.584244"
+ height="29.71249"
+ x="195.71512"
+ y="381.7876" />
+ <text
+ xml:space="preserve"
+ style="font-size:10.16407776px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ x="88.750069"
+ y="400.15198"
+ id="text2645"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2653"
+ x="88.750069"
+ y="400.15198">C++/Parser</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:10.16407776px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ x="196.68718"
+ y="400.15198"
+ id="text2649"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan2655"
+ x="196.68718"
+ y="400.15198">C++/Serializer</tspan></text>
+ </g>
+</svg>
diff --git a/doc/cxx/hybrid/guide/guide.html2ps b/doc/cxx/hybrid/guide/guide.html2ps
new file mode 100644
index 0000000..92ef95d
--- /dev/null
+++ b/doc/cxx/hybrid/guide/guide.html2ps
@@ -0,0 +1,65 @@
+@html2ps {
+ option {
+ toc: hb;
+ colour: 1;
+ hyphenate: 1;
+ titlepage: 1;
+ }
+
+ datefmt: "%B %Y";
+
+ titlepage {
+ content: "
+<div align=center>
+ <h1><big>Embedded C++/Hybrid Mapping</big></h1>
+ <h1><big>Getting Started Guide</big></h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+</div>
+ <p>Copyright &copy; 2005-2011 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href='http://www.codesynthesis.com/licenses/fdl-1.2.txt'>GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/index.xhtml'>XHTML</a>,
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/cxx-hybrid-e-guide.pdf'>PDF</a>, and
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/cxx-hybrid-e-guide.ps'>PostScript</a>.</p>";
+ }
+
+ toc {
+ indent: 2em;
+ }
+
+ header {
+ odd-right: $H;
+ even-left: $H;
+ }
+
+ footer {
+ odd-left: $D;
+ odd-center: $T;
+ odd-right: $N;
+
+ even-left: $N;
+ even-center: $T;
+ even-right: $D;
+ }
+}
+
+body {
+ font-size: 12pt;
+ text-align: justify;
+}
+
+pre {
+ font-size: 10pt;
+}
diff --git a/doc/cxx/hybrid/guide/index.xhtml b/doc/cxx/hybrid/guide/index.xhtml
new file mode 100644
index 0000000..9bf3df1
--- /dev/null
+++ b/doc/cxx/hybrid/guide/index.xhtml
@@ -0,0 +1,6521 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<head>
+ <title>Embedded C++/Hybrid Mapping Getting Started Guide</title>
+
+ <meta name="copyright" content="&copy; 2005-2011 Code Synthesis Tools CC"/>
+ <meta name="keywords" content="xsd,xml,schema,c++,mapping,data,binding,parse,serialize,create,modify,write,validation,embedded,mobile"/>
+ <meta name="description" content="Embedded C++/Hybrid Mapping Getting Started Guide"/>
+
+ <link rel="stylesheet" type="text/css" href="../../../default.css" />
+
+<style type="text/css">
+ pre {
+ padding : 0 0 0 0em;
+ margin : 0em 0em 0em 0;
+
+ font-size : 102%
+ }
+
+ body {
+ min-width: 48em;
+ }
+
+ h1 {
+ font-weight: bold;
+ font-size: 200%;
+ line-height: 1.2em;
+ }
+
+ h2 {
+ font-weight : bold;
+ font-size : 150%;
+
+ padding-top : 0.8em;
+ }
+
+ h3 {
+ font-size : 140%;
+ padding-top : 0.8em;
+ }
+
+ /* Adjust indentation for three levels. */
+ #container {
+ max-width: 48em;
+ }
+
+ #content {
+ padding: 0 0.1em 0 4em;
+ /*background-color: red;*/
+ }
+
+ #content h1 {
+ margin-left: -2.06em;
+ }
+
+ #content h2 {
+ margin-left: -1.33em;
+ }
+
+ /* Title page */
+
+ #titlepage {
+ padding: 2em 0 1em 0;
+ border-bottom: 1px solid black;
+ }
+
+ #titlepage .title {
+ font-weight: bold;
+ font-size: 200%;
+ text-align: center;
+ }
+
+ #titlepage #first-title {
+ padding: 1em 0 0.4em 0;
+ }
+
+ #titlepage #second-title {
+ padding: 0.4em 0 2em 0;
+ }
+
+ /* Lists */
+ ul.list li, ol.list li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+ }
+
+ div.img {
+ text-align: center;
+ padding: 2em 0 2em 0;
+ }
+
+ /* */
+ dl dt {
+ padding : 0.8em 0 0 0;
+ }
+
+ /* TOC */
+ table.toc {
+ border-style : none;
+ border-collapse : separate;
+ border-spacing : 0;
+
+ margin : 0.2em 0 0.2em 0;
+ padding : 0 0 0 0;
+ }
+
+ table.toc tr {
+ padding : 0 0 0 0;
+ margin : 0 0 0 0;
+ }
+
+ table.toc * td, table.toc * th {
+ border-style : none;
+ margin : 0 0 0 0;
+ vertical-align : top;
+ }
+
+ table.toc * th {
+ font-weight : normal;
+ padding : 0em 0.1em 0em 0;
+ text-align : left;
+ white-space : nowrap;
+ }
+
+ table.toc * table.toc th {
+ padding-left : 1em;
+ }
+
+ table.toc * td {
+ padding : 0em 0 0em 0.7em;
+ text-align : left;
+ }
+
+ /* Built-in table */
+ #builtin {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+ }
+
+ #builtin th, #builtin td {
+ border: 1px solid;
+ padding : 0.9em 0.9em 0.7em 0.9em;
+ }
+
+ #builtin th {
+ background : #cde8f6;
+ }
+
+ #builtin td {
+ text-align: left;
+ }
+</style>
+
+
+</head>
+
+<body>
+<div id="container">
+ <div id="content">
+
+ <div class="noprint">
+
+ <div id="titlepage">
+ <div class="title" id="first-title">Embedded C++/Hybrid Mapping</div>
+ <div class="title" id="second-title">Getting Started Guide</div>
+
+ <p>Copyright &copy; 2005-2011 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href="http://www.codesynthesis.com/licenses/fdl-1.2.txt">GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/index.xhtml">XHTML</a>,
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/cxx-hybrid-e-guide.pdf">PDF</a>, and
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/cxx-hybrid-e-guide.ps">PostScript</a>.</p>
+
+ </div>
+
+ <h1>Table of Contents</h1>
+
+ <table class="toc">
+ <tr>
+ <th></th><td><a href="#0">Preface</a>
+ <table class="toc">
+ <tr><th></th><td><a href="#0.1">About This Document</a></td></tr>
+ <tr><th></th><td><a href="#0.2">More Information</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>1</th><td><a href="#1">Introduction</a>
+ <table class="toc">
+ <tr><th>1.1</th><td><a href="#1.1">Mapping Overview</a></td></tr>
+ <tr><th>1.2</th><td><a href="#1.2">Benefits</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>2</th><td><a href="#2">Hello World Example</a>
+ <table class="toc">
+ <tr><th>2.1</th><td><a href="#2.1">Writing XML Document and Schema</a></td></tr>
+ <tr><th>2.2</th><td><a href="#2.2">Translating Schema to C++</a></td></tr>
+ <tr><th>2.3</th><td><a href="#2.3">Implementing Application Logic</a></td></tr>
+ <tr><th>2.4</th><td><a href="#2.4">Compiling and Running</a></td></tr>
+ <tr><th>2.5</th><td><a href="#2.5">Adding Serialization</a></td></tr>
+ <tr><th>2.6</th><td><a href="#2.6">A Minimal Version</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>3</th><td><a href="#3">Mapping Configuration</a>
+ <table class="toc">
+ <tr><th>3.1</th><td><a href="#3.1">Standard Template Library</a></td></tr>
+ <tr><th>3.2</th><td><a href="#3.2">Input/Output Stream Library</a></td></tr>
+ <tr><th>3.3</th><td><a href="#3.3">C++ Exceptions</a></td></tr>
+ <tr><th>3.4</th><td><a href="#3.4">XML Schema Validation</a></td></tr>
+ <tr><th>3.5</th><td><a href="#3.5">64-bit Integer Type</a></td></tr>
+ <tr><th>3.6</th><td><a href="#3.6">Parser and Serializer Reuse</a></td></tr>
+ <tr><th>3.7</th><td><a href="#3.7">Support for Polymorphism</a></td></tr>
+ <tr><th>3.8</th><td><a href="#3.8">Custom Allocators</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>4</th><td><a href="#4">Working with Object Models</a>
+ <table class="toc">
+ <tr><th>4.1</th><td><a href="#4.1">Namespaces</a></td></tr>
+ <tr><th>4.2</th><td><a href="#4.2">Memory Management</a></td></tr>
+ <tr><th>4.3</th><td><a href="#4.3">Enumerations</a></td></tr>
+ <tr><th>4.4</th><td><a href="#4.4">Attributes and Elements</a></td></tr>
+ <tr><th>4.5</th><td><a href="#4.5">Compositors</a></td></tr>
+ <tr><th>4.6</th><td><a href="#4.6">Accessing the Object Model</a></td></tr>
+ <tr><th>4.7</th><td><a href="#4.7">Modifying the Object Model</a></td></tr>
+ <tr><th>4.8</th><td><a href="#4.8">Creating the Object Model from Scratch</a></td></tr>
+ <tr><th>4.9</th><td><a href="#4.9">Customizing the Object Model</a></td></tr>
+ <tr><th>4.10</th><td><a href="#4.10">Polymorphic Object Models</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>5</th><td><a href="#5">Mapping for Built-In XML Schema Types</a>
+ <table class="toc">
+ <tr><th>5.1</th><td><a href="#5.1">Mapping for <code>QName</code></a></td></tr>
+ <tr><th>5.2</th><td><a href="#5.2">Mapping for <code>NMTOKENS</code> and <code>IDREFS</code>s</a></td></tr>
+ <tr><th>5.3</th><td><a href="#5.3">Mapping for <code>base54Binary</code> and <code>hexBinary</code>s</a></td></tr>
+ <tr><th>5.4</th><td><a href="#5.4">Time Zone Representation</a></td></tr>
+ <tr><th>5.5</th><td><a href="#5.5">Mapping for <code>date</code></a></td></tr>
+ <tr><th>5.6</th><td><a href="#5.6">Mapping for <code>dateTime</code></a></td></tr>
+ <tr><th>5.7</th><td><a href="#5.7">Mapping for <code>duration</code></a></td></tr>
+ <tr><th>5.8</th><td><a href="#5.8">Mapping for <code>gDay</code></a></td></tr>
+ <tr><th>5.9</th><td><a href="#5.9">Mapping for <code>gMonth</code></a></td></tr>
+ <tr><th>5.10</th><td><a href="#5.10">Mapping for <code>gMonthDay</code></a></td></tr>
+ <tr><th>5.11</th><td><a href="#5.11">Mapping for <code>gYear</code></a></td></tr>
+ <tr><th>5.12</th><td><a href="#5.12">Mapping for <code>gYearMonth</code></a></td></tr>
+ <tr><th>5.13</th><td><a href="#5.13">Mapping for <code>time</code></a></td></tr>
+ <tr><th>5.14</th><td><a href="#5.14">Mapping for <code>anyType</code></a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>6</th><td><a href="#6">Parsing and Serialization</a>
+ <table class="toc">
+ <tr><th>6.1</th><td><a href="#6.1">Customizing Parsers and Serializers</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>7</th><td><a href="#7">Binary Representation</a>
+ <table class="toc">
+ <tr><th>7.1</th><td><a href="#7.1">CDR (Common Data Representation)</a></td></tr>
+ <tr><th>7.2</th><td><a href="#7.2">XDR (eXternal Data Representation)</a></td></tr>
+ <tr><th>7.3</th><td><a href="#7.3">Custom Representations</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ </table>
+ </div>
+
+ <h1><a name="0">Preface</a></h1>
+
+ <h2><a name="0.1">About This Document</a></h2>
+
+ <p>The goal of this document is to provide you with an
+ understanding of the C++/Hybrid programming model and allow you
+ to efficiently evaluate XSD/e against your project's technical
+ requirements. As such, this document is intended for embedded
+ C++ developers and software architects who are looking for an
+ embedded XML processing solution. Prior experience with XML
+ and C++ is required to understand this document. Basic
+ understanding of XML Schema is advantageous but not expected
+ or required.
+ </p>
+
+
+ <h2><a name="0.2">More Information</a></h2>
+
+ <p>Beyond this guide, you may also find the following sources of
+ information useful:</p>
+
+ <ul class="list">
+ <li><a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a></li>
+
+ <li><a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml">Embedded
+ C++/Parser Mapping Getting Started Guide</a>. The C++/Hybrid
+ mapping uses C++/Parser for XML parsing.</li>
+
+ <li><a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml">Embedded
+ C++/Serializer Mapping Getting Started Guide</a>. The C++/Hybrid
+ mapping uses C++/Serializer for XML serialization.</li>
+
+ <li>The <code>INSTALL</code> file in the XSD/e distribution provides
+ build instructions for various platforms.</li>
+
+ <li>The <code>examples/cxx/hybrid/</code> directory in the XSD/e
+ distribution contains a collection of examples and a README
+ file with an overview of each example.</li>
+
+ <li>The <a href="http://www.codesynthesis.com/mailman/listinfo/xsde-users">xsde-users</a>
+ mailing list is the place to ask technical questions about XSD/e and the
+ Embedded C++/Hybrid mapping. Furthermore, the
+ <a href="http://www.codesynthesis.com/pipermail/xsde-users/">archives</a>
+ may already have answers to some of your questions.</li>
+
+ </ul>
+
+ <!-- Introduction -->
+
+ <h1><a name="1">1 Introduction</a></h1>
+
+ <p>Welcome to CodeSynthesis XSD/e and the Embedded C++/Hybrid mapping.
+ XSD/e is a dependency-free W3C XML Schema to C++ compiler for mobile,
+ embedded, and light-weight applications. Embedded C++/Hybrid is an XML
+ Schema to C++ mapping that represents the data stored in XML as a
+ light-weight, statically-typed, in-memory object model.
+ </p>
+
+ <h2><a name="1.1">1.1 Mapping Overview</a></h2>
+
+ <p>Based on a formal description of an XML vocabulary (schema), the
+ C++/Hybrid mapping produces a tree-like data structure suitable
+ for in-memory processing. The core of the mapping consists of C++
+ classes that constitute the object model and are derived from
+ types defined in XML Schema. The C++/Hybrid mapping uses the
+ APIs provided by the
+ <a href="http://www.codesynthesis.com/products/xsde/c++/parser/">Embedded
+ C++/Parser</a> and
+ <a href="http://www.codesynthesis.com/products/xsde/c++/serializer/">Embedded
+ C++/Serializer</a>
+ mappings to perform validation and parsing of XML to the object
+ model and validation and serialization of the object model to
+ XML. The following diagram illustrates the high-level architecture
+ of the C++/Hybrid mapping:</p>
+
+ <!-- align=center is needed for html2ps -->
+ <div class="img" align="center"><img src="figure-1.png"/></div>
+
+ <p>The use of well-defined APIs presented by the C++/Parser and
+ C++/Serializer mappings for XML parsing and serialization
+ allows a number of advanced techniques, for example, customization
+ of parsing and serialization code, filtering of XML during
+ parsing or object model during serialization, as well as the hybrid,
+ partially event-driven, partially in-memory processing
+ where the XML document is delivered to the application as
+ parts of the object model. The last feature combines the
+ ease and convenience of the in-memory processing model
+ with the ability to minimize the use of RAM and process documents
+ that would otherwise not fit into memory.
+ </p>
+
+ <p>Besides reading from and writing to XML, the C++/Hybrid mapping
+ also supports saving the object model to and loading it from a
+ number of predefined as well as custom binary formats. Binary
+ representations contain only the data without any meta information
+ or markup. Consequently, saving to and loading from a binary
+ format can be an order of magnitude faster as well as result
+ in a much smaller application footprint compared to parsing and
+ serializing the same data in XML. Furthermore, the resulting
+ representation is normally several times smaller than the equivalent
+ XML.</p>
+
+ <p>The Embedded C++/Hybrid mapping was specifically designed and
+ optimized for mobile and embedded systems where hardware
+ constraints require high efficiency and economical use of
+ resources. As a result, the generated parsing and serialization
+ code is 2-10 times faster than general-purpose XML processors
+ while at the same time maintaining extremely low static and
+ dynamic memory footprints. For example, an executable that
+ performs validating XML parsing and serialization can be as small
+ as 150KB in size. The size can be further reduced by disabling
+ support for parsing or serialization as well as XML Schema
+ validation.
+ </p>
+
+ <p>The generated code and the runtime library are also highly-portable
+ and, in their minimal configuration, can be used without STL, RTTI,
+ iostream, C++ exceptions, and with the minimal use of C++ templates.</p>
+
+ <p>A typical application that uses the C++/Hybrid mapping for XML
+ processing performs the following three steps: it first
+ reads (parses) an XML document to an in-memory object model, it
+ then performs some useful computations on that object model which
+ may involve modification of the model, and finally it may write
+ (serialize) the modified object model back to XML. The next chapter
+ presents a simple application that performs these three steps. The
+ following chapters describe the Embedded C++/Hybrid mapping in more
+ detail.</p>
+
+ <h2><a name="1.2">1.2 Benefits</a></h2>
+
+ <p>Traditional XML access APIs such as Document Object Model (DOM)
+ or Simple API for XML (SAX) as well as general-purpose XML Schema
+ validators have a number of drawbacks that make them less suitable
+ for creating mobile and embedded XML processing applications. These
+ drawbacks include:
+ </p>
+
+ <ul class="list">
+ <li>Generic representation of XML in terms of elements, attributes,
+ and text forces an application developer to write a substantial
+ amount of bridging code that identifies and transforms pieces
+ of information encoded in XML to a representation more suitable
+ for consumption by the application logic.</li>
+
+ <li>String-based flow control defers error detection to runtime.
+ It also reduces code readability and maintainability.</li>
+
+ <li>Lack of type safety and inefficient use of resources due to
+ the data being represented as text.</li>
+
+ <li>Extra validation code that is not used by the application.</li>
+
+ <li>Resulting applications are hard to debug, change, and
+ maintain.</li>
+ </ul>
+
+ <p>In contrast, a light-weight, statically-typed, vocabulary-specific
+ object model produced by the Embedded C++/Hybrid mapping allows
+ you to operate in your domain terms instead of the generic elements,
+ attributes, and text. Native data types are used to store the XML
+ data (for example, integers are stored as integers, not as text).
+ Validation code is included only for XML Schema constructs that
+ are used in the application. This results in efficient use of
+ resources and compact object code.</p>
+
+ <p>Furthermore, static typing helps catch errors at
+ compile-time rather than at run-time. Automatic code generation
+ frees you for more interesting tasks (such as doing something
+ useful with the information stored in the XML documents) and
+ minimizes the effort needed to adapt your applications to changes
+ in the document structure. To summarize, the C++/Hybrid object
+ model has the following key advantages over generic XML access
+ APIs:</p>
+
+ <ul class="list">
+ <li><b>Ease of use.</b> The generated code hides all the complexity
+ associated with parsing and serializing XML. This includes navigating
+ the structure and converting between the text representation and
+ data types suitable for manipulation by the application logic.</li>
+
+ <li><b>Natural representation.</b> The object representation allows
+ you to access the XML data using your domain vocabulary instead
+ of generic elements, attributes, and text.</li>
+
+ <li><b>Concise code.</b> With the object representation the
+ application implementation is simpler and thus easier
+ to read and understand.</li>
+
+ <li><b>Safety.</b> The generated object model is statically
+ typed and uses functions instead of strings to access the
+ information. This helps catch programming errors at compile-time
+ rather than at runtime.</li>
+
+ <li><b>Maintainability.</b> Automatic code generation minimizes the
+ effort needed to adapt the application to changes in the
+ document structure. With static typing, the C++ compiler
+ can pin-point the places in the client code that need to be
+ changed.</li>
+
+ <li><b>Efficiency.</b> If the application makes repetitive use
+ of the data extracted from XML, then the C++/Hybrid object model
+ is more efficient because the navigation is performed using
+ function calls rather than string comparisons and the XML
+ data is extracted only once. The runtime memory
+ usage is also reduced due to more efficient data storage
+ (for instance, storing numeric data as integers instead of
+ strings) as well as the static knowledge of cardinality
+ constraints.
+
+ <p>Furthermore, the generated XML parsing and serialization code
+ combines validation and data-to-text conversion in a single step.
+ This makes the generated code much more efficient than traditional
+ architectures with separate stages for validation and data
+ conversion.</p>
+ </li>
+ </ul>
+
+ <!-- Hello World Example -->
+
+
+ <h1><a name="2">2 Hello World Example</a></h1>
+
+ <p>In this chapter we will examine how to parse, access, modify, and
+ serialize a very simple XML document using the generated
+ C++/Hybrid object model as well as the XML parser and serializer. The
+ code presented in this chapter is based on the <code>hello</code>
+ example which can be found in the <code>examples/cxx/hybrid/</code>
+ directory of the XSD/e distribution.</p>
+
+ <h2><a name="2.1">2.1 Writing XML Document and Schema</a></h2>
+
+ <p>First, we need to get an idea about the structure
+ of the XML documents we are going to process. Our
+ <code>hello.xml</code>, for example, could look like this:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;hello>
+
+ &lt;greeting>Hello&lt;/greeting>
+
+ &lt;name>sun&lt;/name>
+ &lt;name>moon&lt;/name>
+ &lt;name>world&lt;/name>
+
+&lt;/hello>
+ </pre>
+
+ <p>Then we can write a description of the above XML in the
+ XML Schema language and save it into <code>hello.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="hello">
+ &lt;xs:sequence>
+ &lt;xs:element name="greeting" type="xs:string"/>
+ &lt;xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="hello" type="hello"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Even if you are not familiar with XML Schema, it
+ should be easy to connect declarations in <code>hello.xsd</code>
+ to elements in <code>hello.xml</code>. The <code>hello</code> type
+ is defined as a sequence of the nested <code>greeting</code> and
+ <code>name</code> elements. Note that the term sequence in XML
+ Schema means that elements should appear in a particular order
+ as opposed to appearing multiple times. The <code>name</code>
+ element has its <code>maxOccurs</code> property set to
+ <code>unbounded</code> which means it can appear multiple times
+ in an XML document. Finally, the globally-defined <code>hello</code>
+ element prescribes the root element for our vocabulary. For an
+ easily-approachable introduction to XML Schema refer to
+ <a href="http://www.w3.org/TR/xmlschema-0/">XML Schema Part 0:
+ Primer</a>.</p>
+
+ <p>The above schema is a specification of our XML vocabulary; it tells
+ everybody what valid documents of our XML-based language should look
+ like. The next step is to compile the schema to generate the object
+ model and the parser.</p>
+
+
+ <h2><a name="2.2">2.2 Translating Schema to C++</a></h2>
+
+ <p>Now we are ready to translate our <code>hello.xsd</code> to C++.
+ To do this we invoke the XSD/e compiler from a terminal (UNIX) or
+ a command prompt (Windows):
+ </p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --generate-parser --generate-aggregate hello.xsd
+ </pre>
+
+ <p>This invocation of the XSD/e compiler produces three pairs of C++ files:
+ <code>hello.hxx</code> and <code>hello.cxx</code>,
+ <code>hello-pskel.hxx</code> and <code>hello-pskel.cxx</code>, as well as
+ <code>hello-pimpl.hxx</code> and <code>hello-pimpl.cxx</code>. The
+ first pair contains the object model classes. The second pair contains
+ parser skeletons. Parser skeletons are generated by the C++/Parser
+ mapping which is automatically invoked by C++/Hybrid.
+ For now we can ignore parser skeletons except that we need to compile
+ them and link the result to our application. The last pair of files
+ contains parser implementations. They implement the parser skeletons
+ to create and populate the object model types from XML data. The generation
+ of parser skeletons and parser implementations is requested with the
+ <code>--generate-parser</code> XSD/e compiler option.</p>
+
+ <p>You may be wondering what is the <code>--generate-aggregate</code>
+ option for. This option instructs the XSD/e compiler to generate
+ parser and, as we will see later, serializer aggregates. The
+ generated parser implementation files mentioned above contain
+ a separate parser implementation class for each type defined
+ in XML Schema. These parser implementations need to be
+ instantiated and connected before we can use them to parse an XML document.
+ When you specify the <code>--generate-aggregate</code> option,
+ the XSD/e compiler generates a class (in the parser implementation
+ files), called parser aggregate, for each global element defined
+ in the schema (you can also generate a parser aggregate for a type
+ as well as control for which global elements parser aggregates
+ are generated, see the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a> for more information). A parser
+ aggregate instantiates and connects all the necessary parser
+ implementations needed to parse an XML document with a given root
+ element. We will see how to use the parser aggregate for the
+ <code>hello</code> root element in the next section.</p>
+
+ <p>The following code fragment is taken from <code>hello.hxx</code>; it
+ shows what the C++ object model for our "Hello World" XML vocabulary
+ looks like:
+ </p>
+
+ <pre class="c++">
+class hello
+{
+public:
+ hello ();
+
+ // greeting
+ //
+ const std::string&amp;
+ greeting () const;
+
+ std::string&amp;
+ greeting ();
+
+ void
+ greeting (const std::string&amp;);
+
+ // name
+ //
+ typedef xml_schema::string_sequence name_sequence;
+ typedef name_sequence::iterator name_iterator;
+ typedef name_sequence::const_iterator name_const_iterator;
+
+ const name_sequence&amp;
+ name () const;
+
+ name_sequence&amp;
+ name ();
+
+private:
+ ...
+};
+ </pre>
+
+ <p>The <code>hello</code> C++ class corresponds to the
+ <code>hello</code> XML Schema type. For each element
+ in this type a set of accessor and modifier functions
+ are generated inside the <code>hello</code> class. Note
+ that the member functions for the <code>greeting</code> and
+ <code>name</code> elements are different because of the
+ different cardinalities these two elements have
+ (<code>greeting</code> is a required single element and
+ <code>name</code> is a sequence of elements).</p>
+
+ <p>It is also evident that the built-in XML Schema type
+ <code>string</code> is mapped to <code>std::string</code>.
+ The <code>string_sequence</code> class that is used in
+ the <code>name_sequence</code> type definition
+ has an interface similar to <code>std::vector</code>. The
+ mapping between the built-in XML Schema types and C++ types
+ is described in more detail in <a href="#5">Chapter 5,
+ "Mapping for Built-in XML Schema Types"</a>.</p>
+
+
+ <h2><a name="2.3">2.3 Implementing Application Logic</a></h2>
+
+ <p>At this point we have all the parts we need to do something useful
+ with the information stored in our XML document:
+ </p>
+
+ <pre class="c++">
+#include &lt;iostream>
+
+#include "hello.hxx"
+#include "hello-pimpl.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ // Parse.
+ //
+ hello_paggr hello_p;
+ xml_schema::document_pimpl doc_p (hello_p.root_parser (),
+ hello_p.root_name ());
+ hello_p.pre ();
+ doc_p.parse (argv[1]);
+ hello* h = hello_p.post ();
+
+ // Print what we've got.
+ //
+ for (hello::name_const_iterator i = h->name ().begin ();
+ i != h->name ().end ();
+ ++i)
+ {
+ cout &lt;&lt; h->greeting () &lt;&lt; ", " &lt;&lt; *i &lt;&lt; "!" &lt;&lt; endl;
+ }
+
+ delete h;
+ }
+ catch (const xml_schema::parser_exception&amp; e)
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>The first part of our application creates a document parser
+ and parses the XML file specified in the command line to the
+ object model. The <code>hello_paggr</code> class is the parser
+ aggregate class we discussed earlier. Parsing is covered in more
+ detail in <a href="#6">Chapter 6, "Parsing and Serialization"</a>.
+ The second part uses the returned object model to iterate over
+ names and print a greeting line for each of them. We also catch
+ and print the <code>xml_schema::parser_exception</code> exception
+ in case something goes wrong.
+ </p>
+
+ <h2><a name="2.4">2.4 Compiling and Running</a></h2>
+
+ <p>After saving our application from the previous section in
+ <code>driver.cxx</code>, we are ready to compile our first
+ program and run it on the test XML document. On UNIX
+ this can be done with the following commands:
+ </p>
+
+ <pre class="terminal">
+$ c++ -I.../libxsde -c driver.cxx hello.cxx hello-pskel.cxx \
+ hello-pimpl.cxx
+
+$ c++ -o driver driver.o hello.o hello-pskel.o hello-pimpl.o \
+ .../libxsde/xsde/libxsde.a
+
+$ ./driver hello.xml
+Hello, sun!
+Hello, moon!
+Hello, world!
+ </pre>
+
+ <p>Here <code>.../libxsde</code> represents the path to the
+ <code>libxsde</code> directory in the XSD/e distribution.</p>
+
+ <p>We can also test the error handling. To test XML well-formedness
+ checking, we can try to parse <code>hello.hxx</code>:</p>
+
+ <pre class="terminal">
+$ ./driver hello.hxx
+hello.hxx:1:0: not well-formed (invalid token)
+ </pre>
+
+ <p>We can also try to parse a valid XML but not from our
+ vocabulary, for example <code>hello.xsd</code>:</p>
+
+ <pre class="terminal">
+$ ./driver hello.xsd
+hello.xsd:2:57: unexpected element encountered
+ </pre>
+
+ <h2><a name="2.5">2.5 Adding Serialization</a></h2>
+
+ <p>While parsing and accessing the XML data may be everything
+ you need, there are applications that require creating new
+ or modifying existing XML documents. To request the generation
+ of serialization support we will need to add the
+ <code>--generate-serializer</code> option to our XSD/e
+ compiler invocation:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+ --generate-aggregate hello.xsd
+ </pre>
+
+ <p>This will result in two additional pairs of C++ files:
+ <code>hello-sskel.hxx</code> and <code>hello-sskel.cxx</code>, as well as
+ <code>hello-simpl.hxx</code> and <code>hello-simpl.cxx</code>.
+ Similar to the parser files, the first pair contains serializer
+ skeletons (generated by the C++/Serializer mapping) and the second
+ pair contains serializer implementations as well as the serializer
+ aggregate for the <code>hello</code> root element.</p>
+
+ <p>Let us first examine an application that modifies an existing
+ object model and serializes it back to XML:</p>
+
+ <pre class="c++">
+#include &lt;iostream>
+
+#include "hello.hxx"
+#include "hello-pimpl.hxx"
+#include "hello-simpl.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ // Parse.
+ //
+ hello_paggr hello_p;
+ xml_schema::document_pimpl doc_p (hello_p.root_parser (),
+ hello_p.root_name ());
+ hello_p.pre ();
+ doc_p.parse (argv[1]);
+ hello* h = hello_p.post ();
+
+ // Change the greeting phrase.
+ //
+ h->greeting ("Hi");
+
+ // Add another entry to the name sequence.
+ //
+ h->name ().push_back ("mars");
+
+ // Serialize the modified object model to XML.
+ //
+ hello_saggr hello_s;
+ xml_schema::document_simpl doc_s (hello_s.root_serializer (),
+ hello_s.root_name ());
+ hello_s.pre (*h);
+ doc_s.serialize (cout, xml_schema::document_simpl::pretty_print);
+ hello_s.post ();
+
+ delete h;
+ }
+ catch (const xml_schema::parser_exception&amp; e)
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+ catch (const xml_schema::serializer_exception&amp; e)
+ {
+ cerr &lt;&lt; "error: " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>First, our application parses an XML document and obtains its
+ object model as in the previous example. Then it changes the
+ greeting string and adds another entry to the list of names.
+ Finally, it creates a document serializer and serializes the
+ object model back to XML. The <code>hello_saggr</code> class
+ is the serializer aggregate class we discussed earlier.</p>
+
+ <p>The resulting XML is written to the standard output (<code>cout</code>)
+ for us to inspect. We could have also written the result to a
+ file or memory buffer by creating an instance of <code>std::ofstream</code>
+ or <code>std::ostringstream</code> and passing it to
+ <code>serialize()</code> instead of <code>cout</code>.
+ The second argument in the call to
+ <code>serialize()</code> is a flag that requests pretty-printing
+ of the resulting XML document. You would normally specify this flag
+ during testing to obtain easily-readable XML and remove it
+ in production to get faster serialization and smaller documents.
+ Serialization is covered in more detail in <a href="#6">Chapter 6,
+ "Parsing and Serialization"</a>.</p>
+
+ <p>If we now compile and run this application (don't forget to
+ compile and link <code>hello-sskel.cxx</code> and
+ <code>hello-simpl.cxx</code>), we will see the
+ output as shown in the following listing:</p>
+
+ <pre class="xml">
+&lt;hello>
+ &lt;greeting>Hi&lt;/greeting>
+ &lt;name>sun&lt;/name>
+ &lt;name>moon&lt;/name>
+ &lt;name>world&lt;/name>
+ &lt;name>mars&lt;/name>
+&lt;/hello>
+ </pre>
+
+ <p>
+ We can also test XML Schema validation. We can "accidently"
+ remove all the names from the object model by adding the following
+ after: <code>push_back ("mars")</code>:</p>
+
+ <pre class="c++">
+h->name ().clear ();
+ </pre>
+
+ <p>This will violate our vocabulary specification which requires
+ at least one <code>name</code> element to be present. If we
+ make the above change and recompile our application, we will
+ get the following output:</p>
+
+ <pre class="terminal">
+$ ./driver hello.xml
+error: expected element not encountered
+ </pre>
+
+ <p>It is also possible to create and serialize an object model from
+ scratch as shown in the following example. For this case we
+ can remove the <code>--generate-parser</code> option since
+ we don't need support for XML parsing.</p>
+
+ <pre class="c++">
+#include &lt;sstream>
+#include &lt;iostream>
+
+#include "hello.hxx"
+#include "hello-simpl.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ hello h;
+ h.greeting ("Hi");
+
+ hello::name_sequence&amp; ns = h.name ();
+ ns.push_back ("Jane");
+ ns.push_back ("John");
+
+ // Serialize the object model to XML.
+ //
+ hello_saggr hello_s;
+ xml_schema::document_simpl doc_s (hello_s.root_serializer (),
+ hello_s.root_name ());
+ ostringstream ostr;
+
+ hello_s.pre (h);
+ doc_s.serialize (ostr, xml_schema::document_simpl::pretty_print);
+ hello_s.post ();
+
+ cout &lt;&lt; ostr.str () &lt;&lt; endl;
+ }
+ catch (const xml_schema::serializer_exception&amp; e)
+ {
+ cerr &lt;&lt; "error: " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>In this example we used the generated default constructor to
+ create an empty instance of type <code>hello</code>. We then
+ set greeting and, to reduce typing, we obtained a reference to
+ the name sequence which we used to add a few names. The
+ serialization part is identical to the previous example except
+ this time we first save the XML representation into a string.
+ If we compile and run this program, it produces the following
+ output:</p>
+
+ <pre class="xml">
+&lt;hello>
+ &lt;greeting>Hi&lt;/greeting>
+ &lt;name>Jane&lt;/name>
+ &lt;name>John&lt;/name>
+&lt;/hello>
+ </pre>
+
+ <h2><a name="2.6">2.6 A Minimal Version</a></h2>
+
+ <p>The previous sections showed a number of examples that relied
+ on STL for strings, iostream of input/output and C++ exceptions
+ for error handling.
+ As was mentioned in the introduction and will be discussed
+ in further detail in the next chapter, the C++/Hybrid mapping
+ can be configured only to rely on the minimal subset of C++.
+ In this section we will implement an example that parses,
+ prints, modifies and serializes the object model without
+ relying on STL, iostream, or C++ exceptions.</p>
+
+ <p>The first step is to instruct the XSD/e compiler not to use
+ any of the above features in the generated code. You may also
+ need to re-configure and rebuild the XSD/e runtime library
+ (<code>libxsde.a</code>) to disable STL, iostream, and
+ exceptions.</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --no-stl --no-iostream --no-exceptions \
+ --generate-parser --generate-serializer --generate-aggregate \
+ hello.xsd
+ </pre>
+
+ <p>If you now study the generated <code>hello.hxx</code> file,
+ you will notice that the use of <code>std::string</code> type
+ is replaced with <code>char*</code>. When STL is disabled,
+ built-in XML Schema type <code>string</code> is mapped to a
+ C string. The following listing presents the content of
+ <code>driver.cxx</code> in full:</p>
+
+ <pre class="c++">
+#include &lt;stdio.h>
+
+#include "people.hxx"
+
+#include "people-pimpl.hxx"
+#include "people-simpl.hxx"
+
+using namespace std;
+
+struct writer: xml_schema::writer
+{
+ virtual bool
+ write (const char* s, size_t n)
+ {
+ return fwrite (s, n, 1, stdout) == 1;
+ }
+
+ virtual bool
+ flush ()
+ {
+ return fflush (stdout) == 0;
+ }
+};
+
+int
+main (int argc, char* argv[])
+{
+ // Open the file or use STDIN.
+ //
+ FILE* f = fopen (argv[1], "rb");
+
+ if (f == 0)
+ {
+ fprintf (stderr, "%s: unable to open\n", argc);
+ return 1;
+ }
+
+ // Parse.
+ //
+ using xml_schema::parser_error;
+
+ parser_error pe;
+ bool io_error = false;
+ hello* h = 0;
+
+ do
+ {
+ hello_paggr hello_p;
+ xml_schema::document_pimpl doc_p (hello_p.root_parser (),
+ hello_p.root_name ());
+ if (pe = doc_p._error ())
+ break;
+
+ hello_p.pre ();
+
+ if (pe = hello_p._error ())
+ break;
+
+ char buf[4096];
+
+ do
+ {
+ size_t s = fread (buf, 1, sizeof (buf), f);
+
+ if (s != sizeof (buf) &amp;&amp; ferror (f))
+ {
+ io_error = true;
+ break;
+ }
+
+ doc_p.parse (buf, s, feof (f) != 0);
+ pe = doc_p._error ();
+
+ } while (!pe &amp;&amp; !feof (f));
+
+ if (io_error || pe)
+ break;
+
+ h = hello_p.post ();
+ pe = hello_p._error ();
+
+ } while (false);
+
+ fclose (f);
+
+ // Handle parsing errors.
+ //
+ if (io_error)
+ {
+ fprintf (stderr, "%s: read failure\n", argc);
+ return 1;
+ }
+
+ if (pe)
+ {
+ switch (pe.type ())
+ {
+ case parser_error::sys:
+ {
+ fprintf (stderr, "%s: %s\n", argc, pe.sys_text ());
+ break;
+ }
+ case parser_error::xml:
+ {
+ fprintf (stderr, "%s:%lu:%lu: %s\n",
+ argc, pe.line (), pe.column (), pe.xml_text ());
+ break;
+ }
+ case parser_error::schema:
+ {
+ fprintf (stderr, "%s:%lu:%lu: %s\n",
+ argc, pe.line (), pe.column (), pe.schema_text ());
+ break;
+ }
+ default:
+ break;
+ }
+
+ return 1;
+ }
+
+ // Print what we've got.
+ //
+ for (hello::name_const_iterator i = h->name ().begin ();
+ i != h->name ().end ();
+ ++i)
+ {
+ printf ("%s, %s!\n", h->greeting (), *i);
+ }
+
+ using xml_schema::strdupx;
+
+ // Change the greeting phrase.
+ //
+ char* str = strdupx ("Hi");
+
+ if (str == 0)
+ {
+ fprintf (stderr, "error: no memory\n");
+ delete h;
+ return 1;
+ }
+
+ h->greeting (str);
+
+ // Add another entry to the name sequence.
+ //
+ str = strdupx ("mars");
+
+ if (str == 0)
+ {
+ fprintf (stderr, "error: no memory\n");
+ delete h;
+ return 1;
+ }
+
+ if (h->name ().push_back (str) != 0)
+ {
+ // The sequence has already freed str.
+ //
+ fprintf (stderr, "error: no memory\n");
+ delete h;
+ return 1;
+ }
+
+ // Serialize.
+ //
+ using xml_schema::serializer_error;
+
+ serializer_error se;
+ writer w;
+
+ do
+ {
+ hello_saggr hello_s;
+ xml_schema::document_simpl doc_s (hello_s.root_serializer (),
+ hello_s.root_name ());
+ if (se = doc_s._error ())
+ break;
+
+ hello_s.pre (*h);
+
+ if (se = hello_s._error ())
+ break;
+
+ doc_s.serialize (w, xml_schema::document_simpl::pretty_print);
+
+ if (se = doc_s._error ())
+ break;
+
+ hello_s.post ();
+
+ se = hello_s._error ();
+
+ } while (false);
+
+ delete h;
+
+ // Handle serializer errors.
+ //
+ if (se)
+ {
+ switch (se.type ())
+ {
+ case serializer_error::sys:
+ {
+ fprintf (stderr, "error: %s\n", se.sys_text ());
+ break;
+ }
+ case serializer_error::xml:
+ {
+ fprintf (stderr, "error: %s\n", se.xml_text ());
+ break;
+ }
+ case serializer_error::schema:
+ {
+ fprintf (stderr, "error: %s\n", se.schema_text ());
+ break;
+ }
+ default:
+ break;
+ }
+
+ return 1;
+ }
+}
+ </pre>
+
+ <p>The parsing and serialization parts of the above example got
+ quite a bit more complex due to the lack of exceptions and iostream
+ support. For more information on what's going on there, refer to
+ <a href="#6">Chapter 6, "Parsing and Serialization"</a>. On the other
+ hand, the access and modification of the object model stayed
+ relatively unchanged. The only noticeable change is the use
+ of the <code>xml_schema::strdupx</code> function to create
+ C strings from string literals. We have to use this function
+ because the object model assumes ownership of the strings
+ passed. We also cannot use the standard C <code>strdup</code>
+ because the object model expects the strings to be allocated
+ with C++ operator <code>new[]</code> while C <code>strdup</code>
+ uses <code>malloc</code> (on most implementations operator
+ <code>new</code> is implemented in terms of <code>malloc</code>
+ so you can probably use <code>strdup</code> if you really
+ want to).</p>
+
+
+ <!-- Mapping Configuration -->
+
+
+ <h1><a name="3">3 Mapping Configuration</a></h1>
+
+ <p>The Embedded C++/Hybrid mapping has a number of configuration
+ parameters that determine the overall properties and behavior
+ of the generated code, such as the use of Standard Template
+ Library (STL), Input/Output Stream Library (iostream), C++
+ exceptions, XML Schema validation, 64-bit integer types, as well as
+ parser and serializer implementation reuse styles. In the previous
+ chapter we have already got an overview of the changes to the
+ generated code that happen when we disable STL, iostream, and C++
+ exceptions. In this chapter we will discuss these and other
+ configuration parameters in more detail.</p>
+
+ <p>In order to enable or disable a particular feature, the corresponding
+ configuration parameter should be set accordingly in the XSD/e runtime
+ library as well as specified during schema compilation with the XSD/e
+ command line options as described in the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a>.
+ </p>
+
+ <p>While the XML documents can use various encodings, the C++/Hybrid
+ object model always stores character data in the same encoding,
+ called application encoding. The application encoding can either be
+ UTF-8 (default) or ISO-8859-1. To select a particular encoding, configure
+ the XSD/e runtime library accordingly and pass the <code>--char-encoding</code>
+ option to the XSD/e compiler when translating your schemas.</p>
+
+ <p>When using ISO-8859-1 as the application encoding, XML documents
+ being parsed may contain characters with Unicode values greater
+ than 0xFF which are unrepresentable in the ISO-8859-1 encoding.
+ By default, in such situations parsing will terminate with
+ an error. However, you can suppress the error by providing a
+ replacement character that should be used instead of
+ unrepresentable characters, for example:</p>
+
+ <pre class="c++">
+xml_schema::iso8859_1::unrep_char ('?');
+ </pre>
+
+ <p>To revert to the default behavior, set the replacement character
+ to <code>'\0'</code>.</p>
+
+ <p>The underlying XML parser used by the mapping includes built-in
+ support for XML documents encoded in UTF-8, UTF-16, ISO-8859-1,
+ and US-ASCII. Other encodings can be supported by providing
+ application-specific decoder functions. The underlying XML
+ serializer used by C++/Hybrid produces the resulting
+ XML documents in the UTF-8 encoding.</p>
+
+ <h2><a name="3.1">3.1 Standard Template Library</a></h2>
+
+ <p>To disable the use of STL you will need to configure the XSD/e
+ runtime without support for STL as well as pass the
+ <code>--no-stl</code> option to the XSD/e compiler when
+ translating your schemas.</p>
+
+ <p>When STL is disabled, all string-based XML Schema types
+ (see <a href="#5">Chapter 5, "Mapping for Built-In XML Schema
+ Types"</a>) are mapped to C-style <code>char*</code> instead of
+ <code>std::string</code>. In this configuration when you set an
+ element or attribute value of a string-based type, the object
+ model assumes ownership of the string and expects that it was
+ allocated with operator <code>new[]</code>. To simplify
+ creation of such strings from string literals, the generated
+ code provides the <code>strdupx</code> and <code>strndupx</code>
+ functions in the <code>xml_schema</code> namespace. These functions
+ are similar to C <code>strdup</code> and <code>strndup</code> except
+ that they use operator <code>new[]</code> instead of <code>malloc</code>
+ to allocate the string:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ char*
+ strdupx (const char*);
+
+ char*
+ strndupx (const char*, size_t);
+}
+ </pre>
+
+ <h2><a name="3.2">3.2 Input/Output Stream Library</a></h2>
+
+ <p>To disable the use of iostream you will need to configure the
+ XSD/e runtime library without support for iostream as well as
+ pass the <code>--no-iostream</code> option to the XSD/e compiler
+ when translating your schemas. When iostream is disabled, a
+ number of overloaded <code>parse()</code> and <code>serialize()</code>
+ functions in the document parser (<code>xml_schema::document_pimpl</code>)
+ and document serializer (<code>xml_schema::document_simpl</code>) become
+ unavailable. See
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml#7">Chapter 7,
+ "Document Parser and Error Handling"</a> in the Embedded
+ C++/Parser Mapping Getting Started Guide and
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml#8">Chapter 8,
+ "Document Serializer and Error Handling"</a> in the Embedded
+ C++/Serializer Mapping Getting Started Guide for details.
+ </p>
+
+ <h2><a name="3.3">3.3 C++ Exceptions</a></h2>
+
+ <p>To disable the use of C++ exceptions, you will need to configure
+ the XSD/e runtime without support for exceptions as well as pass
+ the <code>--no-exceptions</code> option to the XSD/e compiler
+ when translating your schemas. When C++ exceptions are disabled,
+ the error conditions that may arise while parsing, serializing,
+ and modifying the object model are indicated with error codes
+ instead of exceptions. For more information on error handling
+ during parsing, see
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml#7">Chapter 7,
+ "Document Parser and Error Handling"</a> in the Embedded C++/Parser
+ Mapping Getting Started Guide. For more information on error handling
+ during serialization, see
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml#8">Chapter 8,
+ "Document Serializer and Error Handling"</a> in the Embedded
+ C++/Serializer Mapping Getting Started Guide. For more information on
+ error handling in the object model, see <a href="#4">Chapter 4, "Working
+ with Object Models"</a> below.
+ </p>
+
+ <h2><a name="3.4">3.4 XML Schema Validation</a></h2>
+
+ <p>By default, XML Schema validation is enabled during both parsing
+ and serialization. To disable validation during parsing, you will
+ need to configure the XSD/e runtime to disable support for validation
+ in the C++/Parser mapping as well as pass the <code>--suppress-parser-val</code>
+ option to the XSD/e compiler when translating your schemas. To disable
+ validation during serialization, you will need to configure the XSD/e
+ runtime to disable support for validation in the C++/Serializer mapping
+ as well as pass the <code>--suppress-serializer-val</code>
+ option to the XSD/e compiler when translating your schemas. If you
+ are disabling validation during both parsing and serialization, you
+ can use the <code>--suppress-validation</code> option instead of the
+ two options mentioned above.</p>
+
+ <p>Disabling XML Schema validation allows to further increase the
+ parsing and serialization performance as well as reduce footprint in
+ cases where the data being parsed and/or serialized is known
+ to be valid.</p>
+
+ <h2><a name="3.5">3.5 64-bit Integer Type</a></h2>
+
+ <p>By default the 64-bit <code>long</code> and <code>unsignedLong</code>
+ built-in XML Schema types are mapped to the 64-bit <code>long long</code>
+ and <code>unsigned long long</code> fundamental C++ types. To
+ disable the use of these types in the mapping you will need to
+ configure the XSD/e runtime accordingly as well as pass
+ the <code>--no-long-long</code> option to the XSD/e compiler
+ when translating your schemas. When the use of 64-bit integral
+ C++ types is disabled the <code>long</code> and
+ <code>unsignedLong</code> XML Schema built-in types are mapped
+ to <code>long</code> and <code>unsigned long</code> fundamental
+ C++ types.</p>
+
+ <h2><a name="3.6">3.6 Parser and Serializer Reuse</a></h2>
+
+ <p>When one type in XML Schema inherits from another, it is
+ often desirable to be able to reuse the parser and serializer
+ implementations corresponding to the base type in the parser
+ and serializer implementations corresponding to the derived type.
+ XSD/e provides support for two reuse styles: the so-called <em>mixin</em>
+ (generated when the <code>--reuse-style-mixin</code> option
+ is specified) and <em>tiein</em> (generated by default) styles.
+ The XSD/e runtime should be configured in accordance with the
+ reuse style used in the generated code. See <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml#5.6">Section 5.6,
+ "Parser Reuse"</a> in the Embedded C++/Parser Mapping Getting Started
+ Guide and
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml#6.6">Section 6.6,
+ "Serializer Reuse"</a> in the Embedded C++/Serializer Mapping Getting
+ Started Guide for details.</p>
+
+ <h2><a name="3.7">3.7 Support for Polymorphism</a></h2>
+
+ <p>By default the XSD/e compiler generates non-polymorphic code. If your
+ vocabulary uses XML Schema polymorphism in the form of <code>xsi:type</code>
+ and/or substitution groups, then you will need to configure the XSD/e
+ runtime with support for polymorphism, compile your schemas with the
+ <code>--generate-polymorphic</code> option to produce polymorphism-aware
+ code, as well as pass <code>true</code> as the last argument to the
+ <code>xml_schema::document_pimpl</code> and
+ <code>xml_schema::document_simpl</code> constructors (see
+ <a href="#6">Chapter 6, "Parsing and Serialization"</a> for details).
+ If some of your schemas do not require support for polymorphism then
+ you can compile them with the <code>--runtime-polymorphic</code> option
+ and still use the XSD/e runtime configured with polymorphism support.
+ </p>
+
+ <p>The XSD/e compiler can often automatically determine which types are
+ polymorphic based on the substitution group declarations. However,
+ if your XML vocabulary is not using substitution groups or if
+ substitution groups are defined in a separate schema, then you will
+ need to use the <code>--polymorphic-type</code> option to specify
+ which types are polymorphic. When using this option you only need
+ to specify the root of a polymorphic type hierarchy and the XSD/e
+ compiler will assume that all the derived types are also polymorphic.
+ Also note that you need to specify this option when compiling every
+ schema file that references the polymorphic type. Consider the following
+ two schemas as an example:</p>
+
+ <pre class="xml">
+&lt;!-- base.xsd -->
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="base">
+ &lt;xs:sequence>
+ &lt;xs:element name="b" type="xs:int"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;!-- substitution group root -->
+ &lt;xs:element name="base" type="base"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <pre class="xml">
+&lt;!-- derived.xsd -->
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;include schemaLocation="base.xsd"/>
+
+ &lt;xs:complexType name="derived">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="base">
+ &lt;xs:sequence>
+ &lt;xs:element name="d" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="derived" type="derived" substitutionGroup="base"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>In this example we need to specify "<code>--polymorphic-type base</code>"
+ when compiling both schemas because the substitution group is declared
+ in a schema other than the one defining type <code>base</code>.</p>
+
+ <p>Another issue that may arise when compiling polymorphic schemas is
+ the situation where the XSD/e compiler is unaware of all the
+ derivations of a polymorphic type while generating parser and
+ serializer aggregates. As a result, the generated code may not
+ be able to parse and serialize these "invisible" to the compiler
+ types. The following example will help illustrate this case.
+ Consider a modified version of <code>base.xsd</code> from the
+ above example:</p>
+
+ <pre class="xml">
+&lt;!-- base.xsd -->
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="base">
+ &lt;xs:sequence>
+ &lt;xs:element name="b" type="xs:int"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;!-- substitution group root -->
+ &lt;xs:element name="base" type="base"/>
+
+ &lt;xs:complexType name="root">
+ &lt;xs:sequence>
+ &lt;xs:element ref="base" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;!-- document root -->
+ &lt;xs:element name="root" type="root"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Suppose we compile this schema as follows:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+--generate-polymorphic --polymorphic-type base \
+--generate-aggregate --root-element root base.xsd
+ </pre>
+
+ <p>The resulting parser and serializer aggregates for the <code>root</code>
+ element will not include the parser and serializer for the
+ <code>derived</code> type that can be used instead of the
+ <code>base</code> type. This is because the XSD/e compiler
+ has no knowledge of the <code>derived</code>'s existence when
+ compiling <code>base.xsd</code>.</p>
+
+ <p>There are two ways to overcome this problem. The easier but
+ potentially slower approach is to compile all your schemas
+ at once, for example:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+--generate-polymorphic --polymorphic-type base \
+--generate-aggregate --root-element root base.xsd derived.xsd
+ </pre>
+
+ <p>This will make sure the XSD/e compiler "sees" all the derivations
+ of the polymorphic types. The other approach allows
+ you to explicitly specify, with the <code>--polymorphic-schema</code>
+ option, additional schemas that may contain derivations of the
+ polymorphic types. Using this approach we would compile
+ <code>base.xsd</code> and <code>derived.xsd</code> like this:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+--generate-polymorphic --polymorphic-type base \
+--generate-aggregate --root-element root \
+--polymorphic-schema derived.xsd base.xsd
+
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+--generate-polymorphic --polymorphic-type base derived.xsd
+ </pre>
+
+ <p>For information on how to use object models with polymorphic types,
+ refer to <a href="#4.10">Section 4.10, "Polymorphic Object Models"</a>.</p>
+
+ <h2><a name="3.8">3.8 Custom Allocators</a></h2>
+
+ <p>By default the XSD/e runtime and generated code use
+ the standard operators <code>new</code> and <code>delete</code>
+ to manage dynamic memory. However, it is possible to instead
+ use custom allocator functions provided by your application.
+ To achieve this, configure the XSD/e runtime library to use
+ custom allocator functions as well as pass the
+ <code>--custom-allocator</code> option to the XSD/e compiler
+ when translating your schemas. The signatures of the custom
+ allocator functions that should be provided by your application
+ are listed below. Their semantics should be equivalent to the
+ standard C <code>malloc()</code>, <code>realloc()</code>, and
+ <code>free()</code> functions.</p>
+
+ <pre class="c++">
+extern "C" void*
+xsde_alloc (size_t);
+
+extern "C" void*
+xsde_realloc (void*, size_t);
+
+extern "C" void
+xsde_free (void*);
+ </pre>
+
+ <p>Note also that when custom allocators are enabled, any
+ dynamically-allocated object of which the XSD/e runtime
+ or generated code assume ownership should be allocated
+ using the custom allocation function. Similarly, if your
+ application assumes ownership of any dynamically-allocated
+ object returned by the XSD/e runtime or the generated code,
+ then such an object should be disposed of using the custom
+ deallocation function. To help with these tasks the generated
+ <code>xml_schema</code> namespace defines the following two
+ helper functions and, if C++ exceptions are enabled, automatic
+ pointer class:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ void*
+ alloc (size_t);
+
+ void
+ free (void*);
+
+ struct alloc_guard
+ {
+ alloc_guard (void*);
+ ~alloc_guard ();
+
+ void*
+ get () const;
+
+ void
+ release ();
+
+ private:
+ ...
+ };
+}
+ </pre>
+
+ <p>If C++ exceptions are disabled, these functions are equivalent
+ to <code>xsde_alloc()</code> and <code>xsde_free()</code>.
+ If exceptions are enabled, <code>xml_schema::alloc()</code>
+ throws <code>std::bad_alloc</code> on memory allocation failure.</p>
+
+ <p>The following code fragment shows how to create and destroy a
+ dynamically-allocated object with custom allocators when C++
+ exceptions are disabled:</p>
+
+ <pre class="c++">
+void* v = xml_schema::alloc (sizeof (type));
+
+if (v == 0)
+{
+ // Handle out of memory condition.
+}
+
+type* x = new (v) type (1, 2);
+
+...
+
+if (x)
+{
+ x->~type ();
+ xml_schema::free (x);
+}
+ </pre>
+
+ <p>The equivalent code fragment for configurations with C++ exceptions
+ enabled is shown below:</p>
+
+ <pre class="c++">
+xml_schema::alloc_guard g (xml_schema::alloc (sizeof (type)));
+type* x = new (g.get ()) type (1, 2);
+g.release ();
+
+...
+
+if (x)
+{
+ x->~type ();
+ xml_schema::free (x);
+}
+ </pre>
+
+ <p>For a complete example that shows how to use custom allocators, see
+ the <code>allocator</code> example which can be found in the
+ <code>examples/cxx/hybrid/</code> directory of the XSD/e distribution.</p>
+
+ <!-- Chapater 4 -->
+
+
+ <h1><a name="4">4 Working with Object Models</a></h1>
+
+ <p>As we have seen in the previous chapters, the XSD/e compiler generates
+ a C++ class for each type defined in XML Schema. Together these classes
+ constitute an object model for an XML vocabulary. In this chapter we
+ will take a closer look at different parts that comprise an
+ object model class as well as how to create, access, and modify
+ object models.</p>
+
+ <p>In this chapter we will use the following schema that describes a
+ collection of person records. We save it in <code>people.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:simpleType name="gender">
+ &lt;xs:restriction base="xs:string">
+ &lt;xs:enumeration value="male"/>
+ &lt;xs:enumeration value="female"/>
+ &lt;/xs:restriction>
+ &lt;/xs:simpleType>
+
+ &lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="middle-name" type="xs:string" minOccurs="0"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;xs:element name="gender" type="gender"/>
+ &lt;xs:element name="age" type="xs:unsignedShort"/>
+ &lt;/xs:sequence>
+ &lt;xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+ &lt;/xs:complexType>
+
+ &lt;xs:complexType name="people">
+ &lt;xs:sequence>
+ &lt;xs:element name="person" type="person" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="people" type="people"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>A sample XML instance to go along with this schema is saved
+ in <code>people.xml</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;people>
+
+ &lt;person id="1">
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+
+ &lt;person id="2">
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;middle-name>Mary&lt;/middle-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+
+&lt;/people>
+ </pre>
+
+ <p>Compiling <code>people.xsd</code> with the XSD/e compiler results
+ in three generated object model classes: <code>gender</code>,
+ <code>person</code> and <code>people</code>. Here is how they
+ look with STL enabled:</p>
+
+ <pre class="c++">
+// gender (fixed-length)
+//
+class gender
+{
+public:
+ enum value_type
+ {
+ male,
+ female
+ };
+
+ gender ();
+ gender (value_type);
+ gender (const gender&amp;);
+ gender&amp; operator= (const gender&amp;);
+
+ void
+ value (value_type);
+
+ operator value_type () const;
+
+ const char*
+ string () const;
+
+private:
+ ...
+};
+
+// person (fixed-length)
+//
+class person
+{
+public:
+ person ();
+ person (const person&amp;);
+ person&amp; operator= (const person&amp;);
+
+ // id
+ //
+ unsigned int
+ id () const;
+
+ unsigned int&amp;
+ id ();
+
+ void
+ id (unsigned int);
+
+ // first-name
+ //
+ const std::string&amp;
+ first_name () const;
+
+ std::string&amp;
+ first_name ();
+
+ void
+ first_name (const std::string&amp;);
+
+ // middle-name
+ //
+ bool
+ middle_name_present () const;
+
+ void
+ middle_name_present (bool);
+
+ const std::string&amp;
+ middle_name () const;
+
+ std::string&amp;
+ middle_name ();
+
+ void
+ middle_name (const std::string&amp;);
+
+ // last-name
+ //
+ const std::string&amp;
+ last_name () const;
+
+ std::string&amp;
+ last_name ();
+
+ void
+ last_name (const std::string&amp;);
+
+ // gender
+ //
+ const ::gender&amp;
+ gender () const;
+
+ ::gender&amp;
+ gender ();
+
+ void
+ gender (const ::gender&amp;);
+
+ // age
+ //
+ unsigned short
+ age () const;
+
+ unsigned short&amp;
+ age ();
+
+ void
+ age (unsigned short);
+
+private:
+ ...
+};
+
+// people (variable-length)
+//
+class people
+{
+public:
+ people ();
+
+private:
+ people (const people&amp;);
+ people&amp; operator= (const people&amp;);
+
+public:
+ // person
+ //
+ typedef xml_schema::fix_sequence&lt;person> person_sequence;
+ typedef person_sequence::iterator person_iterator;
+ typedef person_sequence::const_iterator person_const_iterator;
+
+ const person_sequence&amp;
+ person () const;
+
+ person_sequence&amp;
+ person ();
+
+private:
+ ...
+};
+ </pre>
+
+ <p>We will examine these classes in detail in the subsequent
+ sections.</p>
+
+ <h2><a name="4.1">4.1 Namespaces</a></h2>
+
+ <p>XSD/e maps XML namespaces specified in the <code>targetNamespace</code>
+ attribute in XML Schema to one or more nested C++ namespaces. By
+ default, a namespace URI is mapped to a sequence of C++ namespace
+ names by removing the protocol and host parts and splitting the
+ rest into a sequence of names with <code>'/'</code> as the name
+ separator. For example, the <code>http://www.codesynthesis.com/cs/my</code>
+ XML namespace is mapped to the <code>cs::my</code> C++ namespace.</p>
+
+ <p>The default mapping of namespace URIs to C++ namespaces
+ can be altered using the <code>--namespace-map</code> and
+ <code>--namespace-regex</code> compiler options. For example,
+ to map the <code>http://www.codesynthesis.com/my</code> XML
+ namespace to the <code>cs::my</code> C++ namespace, we can use
+ the following option:</p>
+
+ <pre class="terminal">
+--namespace-map http://www.codesynthesis.com/my=cs::my
+ </pre>
+
+ <p>A vocabulary without a namespace is mapped to the global scope. This
+ also can be altered with the above options by using an empty name
+ for the XML namespace. For example, we could place the generated
+ object model classes for the <code>people.xsd</code> schema
+ into the <code>records</code> C++ namespace by adding the following
+ option:</p>
+
+ <pre class="terminal">
+--namespace-map =records
+ </pre>
+
+
+ <h2><a name="4.2">4.2 Memory Management</a></h2>
+
+ <p>To ensure that objects are allocated and passed efficiently,
+ the C++/Hybrid mapping divides all object model types into
+ fixed-length and variable-length. A type is variable-length
+ if any of the following is true:</p>
+
+ <ol class="list">
+ <li>it is an XML Schema <code>list</code> type</li>
+
+ <li>it is an XML Schema <code>union</code> type and STL is disabled</li>
+
+ <li>it derives from a variable-length type</li>
+
+ <li>it contains an element or attribute of a variable-length type</li>
+
+ <li>it contains an element or compositor (<code>sequence</code>
+ or <code>choice</code>) with <code>maxOccurs</code>
+ greater than one</li>
+
+ <li>it is recursive (that is, one of its elements contains
+ a reference, directly or indirectly, to the type itself)</li>
+
+ <li>it is polymorphic (see <a href="#4.10">Section 4.10, "Polymorphic
+ Object Models"</a> for details)</li>
+ </ol>
+
+ <p>The following build-in XML Schema types are variable-length:
+ <code>base64Binary</code>, <code>hexBinary</code>, <code>NMTOKENS</code>,
+ and <code>IDREFS</code>. Furthermore, if STL is disabled, all
+ string-based build-in XML Schema types are variable-length,
+ namely: <code>string</code>, <code>normalizedString</code>,
+ <code>token</code>, <code>Name</code>, <code>NMTOKEN</code>,
+ <code>NCName</code>, <code>language</code>, <code>QName</code>,
+ <code>ID</code>, <code>IDFER</code>, and <code>anyURI</code>.</p>
+
+ <p>Otherwise, a type is fixed-length. As you might have noticed from
+ the previous code listings, the XSD/e compiler adds a comment before
+ each generated object model class that states whether it is fixed or
+ variable-length. For example, the <code>people</code> type is
+ variable-length because it contains a sequence of <code>person</code>
+ elements (<code>maxOccurs="unbounded"</code>). If we recompile
+ the <code>people.xsd</code> schema with the <code>--no-stl</code>
+ option, the <code>person</code> type will also become variable-length
+ since it contains elements of the <code>string</code> built-in type.
+ And when STL is disabled, <code>string</code> is variable-length.</p>
+
+ <p>The object model uses different methods for storing and passing
+ around fixed-length and variable-length types. Instances of
+ fixed-length types are stored and passed by value since it is
+ cheaper to copy than to allocate them dynamically (in the
+ STL case, the <code>std::string</code> is expected to support the
+ referenced-counted copy-on-write optimization, which makes
+ copying cheap).</p>
+
+ <p>Variable-length types are always allocated dynamically and
+ are stored and passed as pointers. Because copying an instance
+ of a variable-length type can be expensive, such types make
+ their copy constructor and copy assignment operators unavailable.</p>
+
+ <p>When you set a value of an element or attribute of a
+ variable-length type, the object model assumes ownership of
+ the pointed to object. Unless you are using custom allocators
+ (see <a href="#3.8">Section 3.8, "Custom Allocators"</a>),
+ the object model expects you to allocate such an object with
+ operator <code>new</code> and will eventually delete it
+ with operator <code>delete</code>.</p>
+
+ <p>If you wish to make copies of variable-length objects, then
+ you can request the generation of the object cloning functions
+ with the <code>--generate-clone</code> compiler
+ option. When this option is specified, each variable-length
+ type implements the <code>_clone()</code> function which returns
+ a dynamically-allocated copy of the object or <code>NULL</code>
+ if the allocation failed and C++ exceptions are disabled (see
+ <a href="#3.3">Section 3.3, "C++ Exceptions"</a>). </p>
+
+ <p>You can also request generation of detach functions with the
+ <code>--generate-detach</code> compiler option. These functions
+ allow you to detach a variable-length object from the object model.
+ As an example, let us extend
+ our <code>people.xsd</code> schema with the following type:</p>
+
+ <pre class="xml">
+&lt;xs:complexType name="staff">
+ &lt;xs:sequence>
+ &lt;xs:element name="permanent" type="people"/>
+ &lt;xs:element name="contract" type="people"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>If we compile it with XSD/e and specify the
+ <code>--generate-clone</code> and <code>--generate-detach</code>
+ options, we will get the following C++ class:</p>
+
+ <pre class="c++">
+// staff (variable-length)
+//
+class staff
+{
+public:
+ staff ();
+
+ staff*
+ _clone () const;
+
+private:
+ staff (const staff&amp;);
+ staff&amp; operator= (const staff&amp;);
+
+public:
+ // permanent
+ //
+ const people&amp;
+ permanent () const;
+
+ people&amp;
+ permanent ();
+
+ void
+ permanent (people*);
+
+ people*
+ permanent_detach ();
+
+ // contract
+ //
+ const people&amp;
+ contract () const;
+
+ people&amp;
+ contract ();
+
+ void
+ contract (people*);
+
+ people*
+ contract_detach ();
+
+private:
+ ...
+};
+ </pre>
+
+ <p>Notice that unlike, say, the <code>first_name()</code> modifier
+ function in the <code>person</code> class, the <code>permanent()</code>
+ and <code>contract()</code> modifiers expect a pointer to the
+ <code>people</code> object. The following listing shows how
+ we can create and populate an instance of the <code>staff</code>
+ class. The use of smart pointers to hold the results of dynamic
+ allocations is omitted for brevity:</p>
+
+ <pre class="c++">
+people* per = new people;
+people* con = new people;
+
+// Populate per and con.
+
+staff s;
+s->permanent (per) // Assumes ownership of per.
+s->contract (con) // Assumes ownership of con.
+ </pre>
+
+ <h2><a name="4.3">4.3 Enumerations</a></h2>
+
+ <p>By default, string-based types that use XML Schema restriction by
+ enumeration are mapped to C++ classes with semantics similar to
+ C++ enum (you can suppress this mapping and instead get the plain
+ inheritance by specifying the <code>--suppress-enum</code> compiler
+ option). The following code fragment again shows the C++ class that
+ was generated for the <code>gender</code> XML Schema type presented
+ at the beginning of this chapter:</p>
+
+ <pre class="c++">
+// gender (fixed-length)
+//
+class gender
+{
+public:
+ enum value_type
+ {
+ male,
+ female
+ };
+
+ gender ();
+ gender (value_type);
+ gender (const gender&amp;);
+ gender&amp; operator= (const gender&amp;);
+
+ void
+ value (value_type);
+
+ operator value_type () const;
+
+ const char*
+ string () const;
+
+private:
+ value_type v_;
+};
+</pre>
+
+ <p>The <code>gender</code> class defines the underlying C++ enum type
+ (<code>value_type</code>) with enumerators corresponding to the
+ <code>enumeration</code> elements in XML Schema. The class also
+ defines the default constructor, copy constructor, constructor
+ with the underlying enum type as its argument, and the assignment
+ operator. The <code>gender</code> class also supports the implicit
+ conversion to the underlying enum type and the explicit conversion
+ to string via the <code>string()</code> function. Finally, it
+ provides the <code>value()</code> modifier function which allows you
+ to set the underlying enum value explicitly. Note also that such an
+ enumeration class is always fixed-length since it only contains the
+ C++ enum value. The following example shows how we can use the
+ <code>gender</code> class:</p>
+
+ <pre class="c++">
+gender g = gender::male;
+g = gender::female;
+g.value (gender::female); // Same as above.
+
+cerr &lt;&lt; g.string () &lt;&lt; endl;
+
+if (g != gender::male)
+ ...
+
+switch (g)
+{
+case gender::male:
+ ...
+case gender::female:
+ ...
+}
+ </pre>
+
+
+ <h2><a name="4.4">4.4 Attributes and Elements</a></h2>
+
+ <p>As we have seen before, XSD/e generates a different
+ set of member functions for elements with different cardinalities.
+ The C++/Hybrid mapping divides all the possible element and attribute
+ cardinalities into three cardinality classes:
+ <em>one</em>, <em>optional</em>, and <em>sequence</em>.</p>
+
+ <p>The <em>one</em> cardinality class covers all elements that should
+ occur exactly once as well as the required attributes. In our
+ example, the <code>first-name</code>, <code>last-name</code>,
+ <code>gender</code>, and <code>age</code> elements as well as
+ the <code>id</code> attribute belong to this cardinality class.
+ The following code fragment again shows the accessor and modifier
+ functions that are generated for the <code>first-name</code> element
+ in the <code>person</code> class:</p>
+
+ <pre class="c++">
+class person
+{
+ // first-name
+ //
+ const std::string&amp;
+ first_name () const;
+
+ std::string&amp;
+ first_name ();
+
+ void
+ first_name (const std::string&amp;);
+};
+ </pre>
+
+ <p>The first two accessor functions return read-only (constant) and
+ read-write references to the element's value, respectively. The
+ modifier function sets the new value for the element. Note that
+ the signature of the modifier function varies depending on
+ whether the element or attribute is of a fixed or variable-length
+ type, as was discussed in the previous section.</p>
+
+ <p>The <em>optional</em> cardinality class covers all elements that
+ can occur zero or one time as well as optional attributes. In our
+ example, the <code>middle-name</code> element belongs to this
+ cardinality class. The following code fragment again shows the
+ accessor and modifier functions that are generated for this element
+ in the <code>person</code> class:</p>
+
+ <pre class="c++">
+class person
+{
+ // middle-name
+ //
+ bool
+ middle_name_present () const;
+
+ void
+ middle_name_present (bool);
+
+ const std::string&amp;
+ middle_name () const;
+
+ std::string&amp;
+ middle_name ();
+
+ void
+ middle_name (const std::string&amp;);
+};
+ </pre>
+
+ <p>Compared to the <em>one</em> cardinality class, <em>optional</em> adds
+ functions for querying and modifying the member's presence status.
+ The following example shows how we can use these functions:</p>
+
+ <pre class="c++">
+person&amp; p = ...
+
+if (p.middle_name_present ())
+{
+ cout &lt;&lt; p.middle_name () &lt;&lt; endl;
+ p.middle_name_present (false); // Reset to the "not present" state.
+}
+ </pre>
+
+ <p>If an optional member is of a variable-length type, then the second
+ <code>_present()</code> function is omitted. This is done to help
+ detect programming errors that result from a type becoming
+ variable-length due to schema changes. In this situation, before
+ the type becomes variable-length, calling the presence function
+ with <code>true</code> as its argument and then accessing the
+ member is valid. Once the type becomes variable-length, the
+ same sequence of calls would lead to a runtime error. By
+ omitting the second <code>_present()</code> function for
+ variable-length types, this kind of errors can be detected
+ at compile time. To reset an optional member of a variable-length
+ type you can call the member modifier function with <code>NULL</code>
+ as its argument. For example, if the <code>middle_name</code>
+ member was of a variable-length type, then the above code fragment
+ would look like this:</p>
+
+ <pre class="c++">
+person&amp; p = ...
+
+if (p.middle_name_present ())
+{
+ cout &lt;&lt; *p.middle_name () &lt;&lt; endl;
+ p.middle_name (0); // Reset to the "not present" state.
+}
+ </pre>
+
+
+ <p>There are two cases in the <em>optional</em> cardinality class that
+ are handled differently. These are optional attributes with default
+ and fixed values. When an optional attribute declaration in XML Schema
+ specifies a default or fixed value and such an attribute is not present
+ in the XML document, the attribute is assumed to have the default or
+ fixed value, respectively. Furthermore, if an attribute with the
+ fixed value is set in the XML document, then the attribute value
+ should be the same as its fixed value.</p>
+
+ <p>For an optional attribute with a default value, the functions for
+ querying and modifying the attribute's presence status are replaced
+ with functions that allow you to determine whether the attribute has
+ the default value. The accessor functions can be called at any time
+ since an optional attribute with a default value always has some
+ value. Also an extra static function is provided to allow you to
+ obtain the default value. Consider the following modification to
+ the <code>person</code> type which adds the <code>verified</code>
+ attribute with the default value:</p>
+
+ <pre class="xml">
+&lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ ...
+ &lt;/xs:sequence>
+ &lt;xs:attribute name="id" type="xs:unsignedInt" use="required"/>
+ &lt;xs:attribute name="verified" type="xs:boolean" default="false"/>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The code fragment below shows the accessor and modifier functions
+ that are generated for this new attribute in the <code>person</code>
+ class:</p>
+
+ <pre class="c++">
+class person
+{
+ // verified
+ //
+ bool
+ verified_default () const;
+
+ void
+ verified_default (bool);
+
+ bool
+ verified () const;
+
+ bool&amp;
+ verified ();
+
+ void
+ verified (bool);
+
+ static bool
+ verified_default_value ();
+};
+ </pre>
+
+ <p>When we create an object of the <code>person</code> class, the
+ <code>verified</code> member is automatically initialized to the
+ default value. The following example shows how we can manipulate
+ the <code>verified</code> attribute value:</p>
+
+ <pre class="c++">
+person p; // verified is set to the default value (false).
+
+if (p.verified_default ())
+ p.verified (true);
+else
+ p.verified_default (true); // Revert to the default value.
+
+bool v = p.verified (); // Ok, can always be called.
+bool vd = person::verified_default_value ();
+ </pre>
+
+ <p>Note that modifying an attribute of a variable-length type via
+ the reference when the attribute is set to the default value is
+ illegal since this will modify the default value shared by all
+ instances. For example:</p>
+
+ <pre class="c++">
+type&amp; x = ...
+
+if (x.foo_default ())
+{
+ foo&amp; f = x.foo (); // foo is variable-length, for example NMTOKENS
+ f.push_back ("aaa"); // Illegal.
+}
+
+if (x.foo_default ())
+{
+ foo* f = new foo;
+ f->push_back ("aaa");
+ x.foo (f); // Ok.
+}
+ </pre>
+
+ <p>Because an attribute with a fixed value can only be set to that
+ value, only the read-only (constant) accessor and the static
+ function for obtaining the fixed value are provided for such
+ attributes. Similar to the default values, members with fixed
+ values of a newly created object are automatically initialized
+ to their respective fixed values. Consider the following
+ modification to the <code>verified</code> attribute from the
+ schema above:</p>
+
+ <pre class="xml">
+&lt;xs:complexType name="person">
+ ...
+ &lt;xs:attribute name="verified" type="xs:boolean" fixed="true"/>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The code fragment below shows the accessor functions that are
+ generated for this attribute in the <code>person</code>
+ class:</p>
+
+ <pre class="c++">
+class person
+{
+ // verified
+ //
+ bool
+ verified () const;
+
+ static bool
+ verified_fixed_value ();
+};
+ </pre>
+
+ <p>During serialization, attributes that are set to default and fixed
+ values are explicitly specified in the resulting XML document.
+ You can use the <code>--omit-default-attributes</code> XSD/e
+ compiler option to omit such attributes from the serialized XML.</p>
+
+ <p>The <em>sequence</em> cardinality class covers all elements
+ that can occur more than once. In our example, the
+ <code>person</code> element in the <code>people</code> type
+ belongs to this cardinality class. The following code fragment shows
+ again the type definitions as well as the accessor and modifier
+ functions that are generated for this element in the <code>people</code>
+ class:</p>
+
+ <pre class="c++">
+class people
+{
+ // person
+ //
+ typedef xml_schema::fix_sequence&lt;person> person_sequence;
+ typedef person_sequence::iterator person_iterator;
+ typedef person_sequence::const_iterator person_const_iterator;
+
+ const person_sequence&amp;
+ person () const;
+
+ person_sequence&amp;
+ person ();
+};
+ </pre>
+
+ <p>The <code>person_sequence</code> type is a sequence container for the
+ element's values. It has an interface similar to <code>std::vector</code>
+ and we will discuss it in more detail shortly. The <code>person_iterator</code>
+ and <code>person_const_iterator</code> types are read-write and read-only
+ (constant) iterators for the <code>person_sequence</code>
+ container.</p>
+
+ <p>Unlike other two cardinality classes, the <em>sequence</em> class
+ only provides accessor functions that return read-only (constant)
+ and read-write references to the sequence container. The
+ modification of the element values is performed my manipulating
+ the returned sequence container and elements that it contains.</p>
+
+ <p>In the remainder of this section we will examine the interfaces
+ of the sequence containers which differ slightly depending on
+ whether the element type is fixed or variable-length and whether
+ C++ exceptions are enabled. Also, when STL is disabled, string
+ sequences have a special interface which is also discussed
+ below.</p>
+
+ <p>When exceptions are enabled, the fixed-length type sequences
+ are implemented in terms of the following class template:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ template &lt;typename T>
+ class fix_sequence
+ {
+ public:
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T&amp; reference;
+ typedef const T&amp; const_reference;
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef T* iterator;
+ typedef const T* const_iterator;
+
+ public:
+ fix_sequence ();
+
+ void
+ swap (fix_sequence&amp;);
+
+ private:
+ fix_sequence (const fix_sequence&amp;);
+
+ fix_sequence&amp;
+ operator= (fix_sequence&amp;);
+
+ public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ T&amp;
+ front ();
+
+ const T&amp;
+ front () const;
+
+ T&amp;
+ back ();
+
+ const T&amp;
+ back () const;
+
+ T&amp;
+ operator[] (size_t);
+
+ const T&amp;
+ operator[] (size_t) const;
+
+ public:
+ bool
+ empty () const;
+
+ size_t
+ size () const;
+
+ size_t
+ capacity () const;
+
+ size_t
+ max_size () const;
+
+ public:
+ void
+ clear ();
+
+ void
+ pop_back ();
+
+ iterator
+ erase (iterator);
+
+ void
+ push_back (const T&amp;);
+
+ iterator
+ insert (iterator, const T&amp;);
+
+ void
+ reserve (size_t);
+
+ void
+ assign (const T* src, size_t n);
+ };
+}
+ </pre>
+
+ <p>When C++ exceptions are disabled, the signatures of the
+ <code>push_back()</code>, <code>insert()</code>,
+ <code>reserve()</code>, and <code>assign()</code> functions
+ change as follows:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ template &lt;typename T>
+ class fix_sequence
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ ...
+
+ public:
+ error
+ push_back (const T&amp;);
+
+ error
+ insert (iterator, const T&amp;);
+
+ error
+ insert (iterator, const T&amp;, iterator&amp; result);
+
+ error
+ reserve (size_t);
+
+ error
+ assign (const T* src, size_t n);
+ };
+}
+ </pre>
+
+ <p>That is, the functions that may require memory allocation
+ now return an error code that you will need to check in
+ order to detect the out of memory condition.</p>
+
+ <p>When exceptions are enabled, the variable-length type sequences
+ are implemented in terms of the following class template:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ template &lt;typename T>
+ class var_sequence
+ {
+ public:
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T&amp; reference;
+ typedef const T&amp; const_reference;
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef &lt;implementation details> iterator;
+ typedef &lt;implementation details> const_iterator;
+
+ public:
+ var_sequence ();
+
+ void
+ swap (var_sequence&amp;);
+
+ private:
+ var_sequence (const var_sequence&amp;);
+
+ var_sequence&amp;
+ operator= (var_sequence&amp;);
+
+ public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ T&amp;
+ front ();
+
+ const T&amp;
+ front () const;
+
+ T&amp;
+ back ();
+
+ const T&amp;
+ back () const;
+
+ T&amp;
+ operator[] (size_t);
+
+ const T&amp;
+ operator[] (size_t) const;
+
+ public:
+ bool
+ empty () const;
+
+ size_t
+ size () const;
+
+ size_t
+ capacity () const;
+
+ size_t
+ max_size () const;
+
+ public:
+ void
+ clear ();
+
+ void
+ push_back (T*);
+
+ iterator
+ insert (iterator, T*);
+
+ void
+ pop_back ();
+
+ iterator
+ erase (iterator);
+
+ void
+ reserve (size_t);
+
+ T*
+ detach (iterator);
+
+ void
+ attach (iterator, T*);
+ };
+}
+ </pre>
+
+ <p>Most of this interface is identical to the fixed-length type
+ version except for the <code>push_back()</code>, and
+ <code>insert()</code> functions. Similar to the modifier
+ functions for elements and attributes of variable-length
+ types, these two functions expect a pointer to the
+ dynamically-allocated instance of the type and assume
+ ownership of the passed object. To simplify error handling,
+ these two functions delete the passed object if the reallocation
+ of the underlying sequence buffer fails. The <code>var_sequence</code>
+ class template also provides the <code>detach()</code> and <code>attach()</code>
+ functions. The <code>detach()</code> function allows you to detach
+ the contained object at the specified position. A detached object
+ should eventually be deallocated with operator <code>delete</code>.
+ Similarly, the <code>attach()</code> function allows you to attach
+ a new object at the specified position.</p>
+
+ <p>When C++ exceptions are disabled, the <code>push_back()</code>,
+ <code>insert()</code>, and <code>reserve()</code> functions
+ return an error code to signal the out of memory condition:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ template &lt;typename T>
+ class var_sequence
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ ...
+
+ public:
+ error
+ push_back (T*);
+
+ error
+ insert (iterator, T*);
+
+ error
+ insert (iterator, T*, iterator&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+
+ <p>When STL is enabled, the <code>string_sequence</code> class has
+ the same interface as <code>fix_sequence&lt;std::string></code>. When
+ STL is disabled and strings are mapped to <code>char*</code>,
+ <code>string_sequence</code> has a special interface. When C++
+ exceptions are enabled, it has the following definition:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ typedef char* value_type;
+ typedef char** pointer;
+ typedef const char** const_pointer;
+ typedef char* reference;
+ typedef const char* const_reference;
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef char** iterator;
+ typedef const char* const* const_iterator;
+
+ string_sequence ();
+
+ void
+ swap (string_sequence&amp;);
+
+ private:
+ string_sequence (string_sequence&amp;);
+
+ string_sequence&amp;
+ operator= (string_sequence&amp;);
+
+ public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ char*
+ front ();
+
+ const char*
+ front () const;
+
+ char*
+ back ();
+
+ const char*
+ back () const;
+
+ char*
+ operator[] (size_t);
+
+ const char*
+ operator[] (size_t) const;
+
+ public:
+ bool
+ empty () const;
+
+ size_t
+ size () const;
+
+ size_t
+ capacity () const;
+
+ size_t
+ max_size () const;
+
+ public:
+ void
+ clear ();
+
+ void
+ pop_back ();
+
+ iterator
+ erase (iterator);
+
+ void
+ push_back (char*);
+
+ void
+ push_back_copy (const char*);
+
+ iterator
+ insert (iterator, char*);
+
+ void
+ reserve (size_t);
+
+ char*
+ detach (iterator);
+
+ void
+ attach (iterator, char*);
+ };
+}
+ </pre>
+
+ <p>The <code>push_back()</code> and <code>insert()</code> functions
+ assume ownership of the passed string which should be allocated
+ with operator <code>new[]</code> and will be deallocated
+ with operator <code>delete[]</code> by the <code>string_sequence</code>
+ object. Similar to <code>var_sequence</code>, these two functions
+ free the passed string if the reallocation of the underlying
+ sequence buffer fails. The <code>push_back_copy()</code>
+ function makes a copy of the passed string.
+ The <code>string_sequence</code> class also provides the
+ <code>detach()</code> and <code>attach()</code> functions.
+ The <code>detach()</code> function allows you to detach
+ the contained string at the specified position. A detached string
+ should eventually be deallocated with operator <code>delete[]</code>.
+ Similarly, the <code>attach()</code> function allows you to attach
+ a new string at the specified position.</p>
+
+ <p>When C++ exceptions are disabled, the signatures of the
+ <code>push_back()</code>, <code>push_back_copy()</code>,
+ <code>insert()</code>, and <code>reserve()</code> functions
+ in the <code>string_sequence</code> class change as follows:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ ...
+
+ public:
+ error
+ push_back (char*);
+
+ error
+ push_back_copy (const char*);
+
+ error
+ insert (iterator, char*);
+
+ error
+ insert (iterator, char*, iterator&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+ <h2><a name="4.5">4.5 Compositors</a></h2>
+
+ <p>The XML Schema language provides three compositor constructs that
+ are used to group elements: <code>all</code>, <code>sequence</code>,
+ and <code>choice</code>. If a compositor has an <em>optional</em>
+ or <em>sequence</em> cardinality class (see <a href="#4.4">Section
+ 4.4, "Attributes and Elements"</a>) or if a compositor is
+ inside <code>choice</code>, then the C++/Hybrid mapping generates
+ a nested class for such a compositor as well as a set of accessor
+ and modifier functions similar to the ones defined for elements
+ and attributes. Otherwise, the member functions, corresponding
+ to elements defined in a compositor, are generated directly in
+ the containing class.</p>
+
+ <p>Compositor classes are either fixed or variable-length and
+ obey the same storage and passing rules as object model
+ classes corresponding to XML Schema types (see <a href="#4.2">Section
+ 4.2, "Memory Management"</a>). Consider the following schema
+ fragment as an example:</p>
+
+ <pre class="xml">
+&lt;complexType name="type">
+ &lt;sequence>
+ &lt;sequence minOccurs="0">
+ &lt;element name="a" type="int"/>
+ &lt;element name="b" type="string" maxOccurs="unbounded"/>
+ &lt;/sequence>
+ &lt;sequence maxOccurs="unbounded">
+ &lt;element name="c" type="int"/>
+ &lt;element name="d" type="string"/>
+ &lt;/sequence>
+ &lt;/sequence>
+&lt;/complexType>
+ </pre>
+
+ <p>The corresponding object model class is shown below:</p>
+
+ <pre class="c++">
+// type (variable-length)
+//
+class type
+{
+public:
+ type ();
+
+private:
+ type (const type&amp;);
+ type&amp; operator= (const type&amp;);
+
+public:
+ // sequence (variable-length)
+ //
+ class sequence_type
+ {
+ public:
+ sequence_type ();
+
+ private:
+ sequence_type (const sequence_type&amp;);
+ sequence_type&amp; operator= (const sequence_type&amp;);
+
+ public:
+ // a
+ //
+ int
+ a () const;
+
+ int&amp;
+ a ();
+
+ void
+ a (int);
+
+ // b
+ //
+ typedef xml_schema::string_sequence b_sequence;
+ typedef b_sequence::iterator b_iterator;
+ typedef b_sequence::const_iterator b_const_iterator;
+
+ const b_sequence&amp;
+ b () const;
+
+ b_sequence&amp;
+ b ();
+
+ private:
+ ...
+ };
+
+ bool
+ sequence_present () const;
+
+ const sequence_type&amp;
+ sequence () const;
+
+ sequence_type&amp;
+ sequence ();
+
+ void
+ sequence (sequence_type*);
+
+ // sequence1 (fixed-length)
+ //
+ class sequence1_type
+ {
+ public:
+ sequence1_type ();
+ sequence1_type (const sequence1_type&amp;);
+ sequence1_type&amp; operator= (const sequence1_type&amp;);
+
+ // c
+ //
+ int
+ c () const;
+
+ int&amp;
+ c ();
+
+ void
+ c (int);
+
+ // d
+ //
+ const std::string&amp;
+ d () const;
+
+ std::string&amp;
+ d ();
+
+ void
+ d (const std::string&amp;);
+
+ private:
+ ...
+ };
+
+ typedef xml_schema::fix_sequence&lt;sequence1_type> sequence1_sequence;
+ typedef sequence1_sequence::iterator sequence1_iterator;
+ typedef sequence1_sequence::const_iterator sequence1_const_iterator;
+
+ const sequence1_sequence&amp;
+ sequence1 () const;
+
+ sequence1_sequence&amp;
+ sequence1 ();
+
+private:
+ ...
+};
+ </pre>
+
+ <p>The content of the outer <code>sequence</code> compositor is
+ generated in-line since this compositor belongs to the <em>one</em>
+ cardinality class. The first nested <code>sequence</code> compositor
+ is optional (<code>minOccurs="0"</code>), which results in a corresponding
+ nested class. Notice that the <code>sequence_type</code> is
+ variable-length and the accessor and modifier functions corresponding
+ to this <code>sequence</code> compositor are the same as for an
+ optional element or attribute. Similarly, the second nested
+ compositor is of the <em>sequence</em> cardinality class
+ (<code>maxOccurs="unbounded"</code>), which also results in a
+ nested class and a set of accessor functions.</p>
+
+ <p>Generated code corresponding to an <code>all</code> and
+ <code>sequence</code> compositor, whether in-line or as a
+ nested class, simply define accessor and modifier functions
+ for the elements that this compositor contains. For the
+ <code>choice</code> compositor, on the other hand,
+ additional types and functions are generated to support
+ querying and selecting the choice arm that is in effect.
+ Consider the following simple example:</p>
+
+ <pre class="xml">
+&lt;complexType name="type">
+ &lt;choice>
+ &lt;element name="a" type="int"/>
+ &lt;element name="b" type="string"/>
+ &lt;element name="c" type="boolean"/>
+ &lt;/choice>
+&lt;/complexType>
+ </pre>
+
+
+ <p>The corresponding object model class is shown next:</p>
+
+ <pre class="c++">
+// type (fixed-length)
+//
+class type
+{
+public:
+ type ();
+ type (const type&amp;);
+ type&amp; operator= (const type&amp;);
+
+ // choice
+ //
+ enum choice_arm_tag
+ {
+ a_tag,
+ b_tag,
+ c_tag
+ };
+
+ choice_arm_tag
+ choice_arm () const;
+
+ void
+ choice_arm (choice_arm_tag);
+
+ // a
+ //
+ int
+ a () const;
+
+ int&amp;
+ a ();
+
+ void
+ a (int);
+
+ // b
+ //
+ const std::string&amp;
+ b () const;
+
+ std::string&amp;
+ b ();
+
+ void
+ b (const std::string&amp;);
+
+ // c
+ //
+ bool
+ c () const;
+
+ bool&amp;
+ c ();
+
+ void
+ c (bool);
+
+private:
+ ...
+};
+ </pre>
+
+ <p>The extra type is the <code>choice_arm_tag</code> enumeration
+ which defines a set of tags corresponding to each choice arm.
+ There are also the <code>choice_arm()</code> accessor and modifier
+ functions that can be used to query and set the current choice arm.
+ The following code fragment shows how we can use this class:</p>
+
+ <pre class="c++">
+type&amp; x = ...
+
+switch (x.choice_arm ())
+{
+case type::a_tag:
+ {
+ cout &lt;&lt; "a: " &lt;&lt; x.a () &lt;&lt; endl;
+ break;
+ }
+case type::b_tag:
+ {
+ cout &lt;&lt; "b: " &lt;&lt; x.b () &lt;&lt; endl;
+ break;
+ }
+case type::c_tag:
+ {
+ cout &lt;&lt; "c: " &lt;&lt; x.c () &lt;&lt; endl;
+ break;
+ }
+}
+
+// Modifiers automatically set the corresponding arm.
+//
+x.a (10);
+
+// For accessors we need to select the arm explicitly.
+//
+x.choice_arm (type::b_tag);
+x.b () = "b";
+ </pre>
+
+ <p>The following slightly more complex example triggers the generation of
+ nested classes for the <code>choice</code> compositor as well as for
+ the <code>sequence</code> compositor inside <code>choice</code>.
+ Notice that the nested class for <code>sequence</code> is generated
+ because it is in <code>choice</code> even though its cardinality
+ class is <em>one</em>.</p>
+
+ <pre class="xml">
+&lt;complexType name="type">
+ &lt;choice maxOccurs="unbounded">
+ &lt;sequence>
+ &lt;element name="a" type="int"/>
+ &lt;element name="b" type="string"/>
+ &lt;/sequence>
+ &lt;element name="c" type="boolean"/>
+ &lt;/choice>
+&lt;/complexType>
+ </pre>
+
+ <p>The corresponding object model class is shown next:</p>
+
+ <pre class="c++">
+// type (variable-length)
+//
+class type
+{
+public:
+ type ();
+
+private:
+ type (const type&amp;);
+ type&amp; operator= (const type&amp;);
+
+public:
+ // choice (fixed-length)
+ //
+ class choice_type
+ {
+ public:
+ choice_type ();
+ choice_type (const choice_type&amp;);
+ choice_type&amp; operator= (const choice_type&amp;);
+
+ enum choice_arm_tag
+ {
+ sequence_tag,
+ c_tag
+ };
+
+ choice_arm_tag
+ choice_arm () const;
+
+ void
+ choice_arm (choice_arm_tag);
+
+ // sequence (fixed-length)
+ //
+ class sequence_type
+ {
+ public:
+ sequence_type ();
+ sequence_type (const sequence_type&amp;);
+ sequence_type&amp; operator= (const sequence_type&amp;);
+
+ // a
+ //
+ int
+ a () const;
+
+ int&amp;
+ a ();
+
+ void
+ a (int);
+
+ // b
+ //
+ const std::string&amp;
+ b () const;
+
+ std::string&amp;
+ b ();
+
+ void
+ b (const std::string&amp;);
+
+ private:
+ ...
+ };
+
+ const sequence_type&amp;
+ sequence () const;
+
+ sequence_type&amp;
+ sequence ();
+
+ void
+ sequence (const sequence_type&amp;);
+
+ // c
+ //
+ bool
+ c () const;
+
+ bool&amp;
+ c ();
+
+ void
+ c (bool);
+
+ private:
+ ...
+ };
+
+ typedef xml_schema::fix_sequence&lt;choice_type> choice_sequence;
+ typedef choice_sequence::iterator choice_iterator;
+ typedef choice_sequence::const_iterator choice_const_iterator;
+
+ const choice_sequence&amp;
+ choice () const;
+
+ choice_sequence&amp;
+ choice ();
+
+private:
+ ...
+};
+ </pre>
+
+ <h2><a name="4.6">4.6 Accessing the Object Model</a></h2>
+
+ <p>In this section we will examine how to get to the information
+ stored in the object model for the person records vocabulary
+ introduced at the beginning of this chapter. The following
+ application accesses and prints the contents of the
+ <code>people.xml</code> file:</p>
+
+ <pre class="c++">
+#include &lt;memory>
+#include &lt;iostream>
+
+#include "people.hxx"
+#include "people-pimpl.hxx"
+
+using namespace std;
+
+int
+main ()
+{
+ // Parse.
+ //
+ people_paggr people_p;
+ xml_schema::document_pimpl doc_p (people_p.root_parser (),
+ people_p.root_name ());
+ people_p.pre ();
+ doc_p.parse ("people.xml");
+ auto_ptr&lt;people> ppl (people_p.post ());
+
+ // Iterate over individual person records.
+ //
+ people::person_sequence&amp; ps = ppl->person ();
+
+ for (people::person_iterator i = ps.begin (); i != ps.end (); ++i)
+ {
+ person&amp; p = *i;
+
+ // Print names: first-name and last-name are required elements,
+ // middle-name is optional.
+ //
+ cout &lt;&lt; "name: " &lt;&lt; p.first_name () &lt;&lt; " ";
+
+ if (p.middle_name_present ())
+ cout &lt;&lt; p.middle_name () &lt;&lt; " ";
+
+ cout &lt;&lt; p.last_name () &lt;&lt; endl;
+
+ // Print gender, age, and id which are all required.
+ //
+ cout &lt;&lt; "gender: " &lt;&lt; p.gender ().string () &lt;&lt; endl
+ &lt;&lt; "age: " &lt;&lt; p.age () &lt;&lt; endl
+ &lt;&lt; "id: " &lt;&lt; p.id () &lt;&lt; endl
+ &lt;&lt; endl;
+ }
+}
+ </pre>
+
+ <p>This code shows common patterns of accessing elements and attributes
+ with different cardinality classes. For the sequence element
+ (<code>person</code> in the <code>people</code> type) we first obtain a
+ reference to the container and then iterate over individual
+ records. The values of elements and attributes with the
+ <em>one</em> cardinality class (<code>first-name</code>,
+ <code>last-name</code>, <code>gender</code>, <code>age</code>,
+ and <code>id</code>) can be obtained directly by calling the
+ corresponding accessor functions. For the optional
+ <code>middle-name</code> element we first check if the value is present
+ and only then call the corresponding accessor to retrieve it.</p>
+
+ <p>Note that when we want to reduce typing by creating a variable
+ representing a fragment of the object model that we are currently
+ working with (<code>ps</code> and <code>p</code> above), we obtain
+ a reference to that fragment instead of making a copy. This is
+ generally a good rule to follow when creating efficient
+ applications.</p>
+
+ <p>If we run the above application on our sample
+ <code>people.xml</code>, the output looks as follows:</p>
+
+ <pre class="terminal">
+name: John Doe
+gender: male
+age: 32
+id: 1
+
+name: Jane Mary Doe
+gender: female
+age: 28
+id: 2
+ </pre>
+
+
+ <h2><a name="4.7">4.7 Modifying the Object Model</a></h2>
+
+ <p>In this section we will examine how to modify the information
+ stored in the object model for our person records vocabulary.
+ The following application changes the contents of the
+ <code>people.xml</code> file:</p>
+
+ <pre class="c++">
+#include &lt;memory>
+#include &lt;iostream>
+
+#include "people.hxx"
+#include "people-pimpl.hxx"
+#include "people-simpl.hxx"
+
+using namespace std;
+
+int
+main ()
+{
+ // Parse.
+ //
+ people_paggr people_p;
+ xml_schema::document_pimpl doc_p (people_p.root_parser (),
+ people_p.root_name ());
+ people_p.pre ();
+ doc_p.parse ("people.xml");
+ auto_ptr&lt;people> ppl (people_p.post ());
+
+ // Iterate over individual person records and increment
+ // the age.
+ //
+ people::person_sequence&amp; ps = ppl->person ();
+
+ for (people::person_iterator i = ps.begin (); i != ps.end (); ++i)
+ {
+ i->age ()++; // Alternative way: i->age (i->age () + 1)
+ }
+
+ // Add middle-name to the first record and remove it from
+ // the second.
+ //
+ person&amp; john = ps[0];
+ person&amp; jane = ps[1];
+
+ john.middle_name ("Mary");
+ jane.middle_name_present (false);
+
+ // Add another John record.
+ //
+ ps.push_back (john);
+
+ // Serialize the modified object model to XML.
+ //
+ people_saggr people_s;
+ xml_schema::document_simpl doc_s (people_s.root_serializer (),
+ people_s.root_name ());
+ people_s.pre (*ppl);
+ doc_s.serialize (cout, xml_schema::document_simpl::pretty_print);
+ people_s.post ();
+}
+ </pre>
+
+ <p>The first modification the above application performs is iterating
+ over person records and incrementing the age value. This code
+ fragment shows how to modify the value of a required attribute
+ or element. The next modification shows how to set a new value
+ for the optional <code>middle-name</code> element as well
+ as clear its value. Finally, the example adds a copy of the
+ John Doe record to the <code>person</code> element sequence.</p>
+
+ <p>Note that in this case using references for the <code>ps</code>,
+ <code>john</code>, and <code>jane</code> variables is no longer
+ a performance improvement but a requirement for the application
+ to function correctly. If we hadn't used references, all our changes
+ would have been made on copies without affecting the object model.</p>
+
+ <p>If we run the above application on our sample <code>people.xml</code>,
+ the output looks as follows:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;people>
+
+ &lt;person id="1">
+ &lt;first-name>John&lt;/first-name>
+ &lt;middle-name>Mary&lt;/middle-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>33&lt;/age>
+ &lt;/person>
+
+ &lt;person id="2">
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>29&lt;/age>
+ &lt;/person>
+
+ &lt;person id="1">
+ &lt;first-name>John&lt;/first-name>
+ &lt;middle-name>Mary&lt;/middle-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>33&lt;/age>
+ &lt;/person>
+
+&lt;/people>
+ </pre>
+
+ <h2><a name="4.8">4.8 Creating the Object Model from Scratch</a></h2>
+
+ <p>In this section we will examine how to create a new object model
+ for our person records vocabulary. The following application
+ recreates the content of the original <code>people.xml</code>
+ file:</p>
+
+ <pre class="c++">
+#include &lt;iostream>
+
+#include "people.hxx"
+#include "people-simpl.hxx"
+
+using namespace std;
+
+int
+main ()
+{
+ people ppl;
+ people::person_sequence&amp; ps = ppl.person ();
+
+ // John
+ //
+ {
+ person p;
+ p.first_name ("John");
+ p.last_name ("Doe");
+ p.gender (gender::male);
+ p.age (32);
+ p.id (1);
+
+ ps.push_back (p);
+ }
+
+ // Jane
+ //
+ {
+ person p;
+ p.first_name ("Jane");
+ p.middle_name ("Mary");
+ p.last_name ("Doe");
+ p.gender (gender::female);
+ p.age (28);
+ p.id (2);
+
+ ps.push_back (p);
+ }
+
+ // Serialize the object model to XML.
+ //
+ people_saggr people_s;
+ xml_schema::document_simpl doc_s (people_s.root_serializer (),
+ people_s.root_name ());
+ people_s.pre (ppl);
+ doc_s.serialize (cout, xml_schema::document_simpl::pretty_print);
+ people_s.post ();
+}
+ </pre>
+
+ <p>The only new part in the above application is the calls
+ to the <code>people</code> and <code>person</code>
+ constructors. As a general rule, a newly created instance
+ does not assign any values to its elements and attributes.
+ That is, members with the <em>one</em> cardinality
+ class are left uninitialized, members with the <em>optional</em>
+ cardinality class are set to the "not present" state,
+ and members with the <em>sequence</em> cardinality class
+ have empty containers. After the instance has been
+ created, we can set its element and attribute values
+ using the modifier functions.</p>
+
+ <p>The above application produces the following output:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0" ?>
+&lt;people>
+
+ &lt;person id="1">
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+
+ &lt;person id="2">
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;middle-name>Mary&lt;/middle-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+
+&lt;/people>
+ </pre>
+
+ <h2><a name="4.9">4.9 Customizing the Object Model</a></h2>
+
+ <p>Sometimes it is desirable to add extra, application-specific
+ data or functionality to some object model classes or
+ nested compositor classes. Cases where this may be required
+ include handling of typeless content matched by XML Schema
+ wildcards as well as a need for an application to pass extra
+ data or provide custom functions as part of the object model.
+ The C++/Hybrid mapping provides two mechanisms for accomplishing
+ this: custom data and custom types. Custom data is a light-weight
+ mechanism for storing application-specific data by allowing you
+ to add a sequence of opaque objects, stored as <code>void*</code>,
+ to select generated classes. Type customization is a more
+ powerful mechanism that allows you to provide custom implementations
+ for select object model classes. You have the option of either extending
+ the generated version of the class (for example, by adding extra data
+ members and/or functions) or providing your own implementation from
+ scratch. The latter approach essentially allows you to change the
+ mapping of XML Schema to C++ on a case by case basis.</p>
+
+ <p>It is also possible to customize the parsing and serialization code,
+ for example, to populate the custom data sequence or custom data
+ members during parsing and later serialize them to XML. See
+ <a href="#6.1">Section 6.1, "Customizing Parsers and
+ Serializers"</a> for details. The remainder of this section discusses
+ the custom data and custom types mechanisms in more detail.</p>
+
+ <p>To instruct the XSD/e compiler to include custom data
+ in a specific object model class, we need to use the
+ <code>--custom-data</code> option with the corresponding
+ XML Schema type name as its argument. To include custom
+ data into a nested compositor class, use its qualified
+ name starting with the XML Schema type, for example
+ <code>type::sequence1</code>. If we would like to
+ add the ability to store custom data in the generated
+ <code>person</code> class from our person records
+ vocabulary, we can compile <code>people.xsd</code>
+ like this:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --custom-data person people.xsd
+ </pre>
+
+ <p>The resulting <code>person</code> class will have the
+ following extra set of type definitions and functions:</p>
+
+
+ <pre class="c++">
+// person (variable-length)
+//
+class person
+{
+public:
+
+ ...
+
+ // Custom data.
+ //
+ typedef xml_schema::data_sequence custom_data_sequence;
+ typedef custom_data_sequence::iterator custom_data_iterator;
+ typedef custom_data_sequence::const_iterator custom_data_const_iterator;
+
+ const custom_data_sequence&amp;
+ custom_data () const;
+
+ custom_data_sequence&amp;
+ custom_data ();
+};
+ </pre>
+
+ <p>Notice also that the <code>person</code> class is now variable-length
+ since it contains a sequence. When C++ exceptions are enabled, the
+ custom data sequence has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class data_sequence
+ {
+ public:
+ typedef void* value_type;
+ typedef void** pointer;
+ typedef const void** const_pointer;
+ typedef void* reference;
+ typedef const void* const_reference;
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef void** iterator;
+ typedef const void* const* const_iterator;
+
+ typedef void (*destroy_func) (void* data, size_t pos);
+ typedef void* (*clone_func) (void* data, size_t pos);
+
+ public:
+ data_sequence ();
+
+ void
+ destructor (destroy_func);
+
+ void
+ clone (clone_func);
+
+ void
+ swap (data_sequence&amp;);
+
+ private:
+ data_sequence (const data_sequence&amp;);
+
+ data_sequence&amp;
+ operator= (data_sequence&amp;);
+
+ public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ void*
+ front ();
+
+ const void*
+ front () const;
+
+ void*
+ back ();
+
+ const void*
+ back () const;
+
+ void*
+ operator[] (size_t);
+
+ const void*
+ operator[] (size_t) const;
+
+ public:
+ bool
+ empty () const;
+
+ size_t
+ size () const;
+
+ size_t
+ capacity () const;
+
+ size_t
+ max_size () const;
+
+ public:
+ void
+ clear ();
+
+ void
+ pop_back ();
+
+ iterator
+ erase (iterator);
+
+ void
+ push_back (void*);
+
+ iterator
+ insert (iterator, void*);
+
+ void
+ reserve (size_t);
+ };
+}
+ </pre>
+
+ <p>The <code>destructor()</code> modifier allows you to specify
+ the clean up function used to free the sequence elements.
+ Similarly, the <code>clone()</code> modifier allows you to specify
+ the cloning function used to copy the sequence elements.
+ The second argument in these functions is the position
+ of the element in the sequence. This allows you to store objects
+ of different types in the same custom
+ data sequence.</p>
+
+ <p>The <code>push_back()</code> and <code>insert()</code> functions
+ free the passed object if the reallocation of the underlying
+ sequence buffer fails. When exceptions are disabled, the
+ <code>push_back()</code>,
+ <code>insert()</code>, and <code>reserve()</code> functions
+ return an error code to signal the out of memory condition:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class data_sequence
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ ...
+
+ public:
+ error
+ push_back (void*);
+
+ error
+ insert (iterator, void*);
+
+ error
+ insert (iterator, void*, iterator&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+ <p>The following code fragment shows how we can store and retrieve
+ custom data in the <code>person</code> class:</p>
+
+ <pre class="c++">
+class data
+{
+ ...
+};
+
+void
+destroy_data (void* p, size_t)
+{
+ delete static_cast&lt;data*> (p);
+}
+
+person&amp; = ...;
+person::custom_data_sequence&amp; cd = p.custom_data ();
+
+cd.destructor (&amp;destroy_data);
+
+// Store.
+//
+data* d = new data;
+cd.push_back (d);
+
+// Retrieve.
+//
+for (person::custom_data_iterator i = cd.begin (); i != cd.end (); ++i)
+{
+ data* d = static_cast&lt;data*> (*i);
+}
+ </pre>
+
+ <p>To instruct the XSD/e compiler to use a custom implementation
+ for a specific object model class, we need to use the
+ <code>--custom-type</code> option. The argument format for this
+ option is <code>name[=[flags][/[type][/[base][/include]]]]</code>.
+ The <code><i>name</i></code> component is the XML Schema type name being
+ customized. Optional <code><i>flags</i></code> allow you to specify whether
+ the custom class is fixed or variable-length since customization can
+ alter this property, normally from fixed-length to
+ variable-length. The <code>f</code> flag indicates the type is
+ fixed-length and the <code>v</code> flag indicates the type is
+ variable-length. If omitted, the default rules are used to determine
+ the type length (see <a href="#4.2">Section 4.2, "Memory Management"</a>).
+
+ Optional <code><i>type</i></code> is a C++ type name, potentially qualified,
+ that should be used as a custom implementation. If specified, the
+ object model type is defined as a <code>typedef</code> alias for
+ this C++ type. Optional <code><i>base</i></code> is a C++ name that should
+ be given to the generated version. It is normally used as a base for
+ the custom implementation. Optional <code><i>include</i></code> is the header
+ file that defines the custom implementation. It is <code>#include</code>'ed
+ into the generated code immediately after (if <code><i>base</i></code> is
+ specified) or instead of the generated version. The following
+ examples show how we can use this option:</p>
+
+ <pre class="terminal">
+--custom-type foo
+--custom-type foo=///foo.hxx
+--custom-type foo=v///foo.hxx
+--custom-type foo=f/int
+--custom-type foo=//foo_base/my/foo.hxx
+--custom-type foo=v/wrapper&lt;foo_base>/foo_base
+ </pre>
+
+ <p>The first version instructs the XSD/e compiler not to generate
+ the object model class for the <code>foo</code> XML Schema
+ type. The generated code simply forward-declares <code>foo</code>
+ as a class and leaves it to you to provide the implementation.
+
+ The second version is similar to the first, except now we specify
+ the header file which defines the custom implementation.
+ This file is automatically included into the generated header
+ file instead of the standard implementation.
+
+ The third version is similar to the second, except now we specify
+ that the <code>foo</code> type is variable-length. In the previous
+ two cases the type length was determined automatically based on the
+ type definition in the schema.
+
+ In the fourth version we specify that schema type <code>foo</code>
+ is fixed-length and should be mapped to <code>int</code>.
+
+ The fifth version instructs the XSD/e compiler to generate
+ the object model class for type <code>foo</code> but call it
+ <code>foo_base</code>. It also tells the compiler to generate
+ the <code>#include</code> directive with the <code>my/foo.hxx</code>
+ file (which presumably defines <code>foo</code>) right after the
+ <code>foo_base</code> class.
+
+ Finally, the last version specifies that schema type <code>foo</code>
+ is variable-length and should be mapped to <code>wrapper&lt;foo_base></code>.
+ The compiler is also instructed to generate the standard object
+ model class for type <code>foo</code> but call it <code>foo_base</code>.
+
+ If you omit the last component (<code><i>include</i></code>), as in the
+ final version, then you can provide the custom type definitions using
+ one of the prologue or epilogue XSD/e compiler options. See the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a> for details.</p>
+
+ <p>Note also that if the type length you specified with the
+ <code>--custom-type</code> option differs from the default type
+ length that would have been determined by the XSD/e compiler,
+ then you need to specify this <code>--custom-type</code> option
+ when compiling every schema file that includes or imports the
+ schema that defines the type being customized.</p>
+
+ <p>As an example, let us add a flag to the <code>person</code> class
+ from our person records vocabulary. This flag can be used by the
+ application to keep track of whether a particular person record
+ has been verified. To customize the <code>person</code> type we
+ can compile <code>people.xsd</code> like this:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --custom-type person=//person_base/person.hxx \
+people.xsd
+ </pre>
+
+ <p>The relevant code fragment from the generated header file
+ looks like this:</p>
+
+ <pre class="c++">
+// person_base (fixed-length)
+//
+class person_base
+{
+ ...
+};
+
+#include "person.hxx"
+
+// people (variable-length)
+//
+class people
+{
+ ...
+
+ // person
+ //
+ typedef xml_schema::fix_sequence&lt;person> person_sequence;
+ typedef person_sequence::iterator person_iterator;
+ typedef person_sequence::const_iterator person_const_iterator;
+
+ const person_sequence&amp;
+ person () const;
+
+ person_sequence&amp;
+ person ();
+
+private:
+ ...
+};
+ </pre>
+
+ <p>We base our custom implementation of the <code>person</code>
+ class on generated <code>person_base</code> and save it to
+ <code>person.hxx</code>:</p>
+
+ <pre class="c++">
+class person: public person_base
+{
+public:
+ person ()
+ : verified_ (false)
+ {
+ }
+
+ bool
+ verified () const
+ {
+ return verified_;
+ }
+
+ void
+ verified (bool v)
+ {
+ verified_ = v;
+ }
+
+private:
+ bool verified_;
+};
+ </pre>
+
+ <p>The client code can use our custom implementation as if the
+ flag was part of the vocabulary:</p>
+
+ <pre class="c++">
+people::person_sequence&amp; ps = ...;
+
+for (people::person_iterator i = ps.begin (); i != ps.end (); ++i)
+{
+ if (!i->verified ())
+ {
+ // Verify the record.
+
+ ...
+
+ i->verified (true);
+ }
+}
+ </pre>
+
+
+ <h2><a name="4.10">4.10 Polymorphic Object Models</a></h2>
+
+ <p>When generating polymorphism-aware code (see <a href="#3.7">Section
+ 3.7, "Support for Polymorphism"</a>), some objects
+ in the resulting object model will be polymorphic. By polymorphic
+ we mean that the object's (static) type as specified in the
+ object model's interface may differ from the object's actual
+ (dynamic) type. Because of this, it may be necessary to discover
+ the object's actual type at runtime and cast it to this type to
+ gain access to the object's extended interface. Consider the
+ following schema as an example:</p>
+
+ <pre class="xml">
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="name" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;!-- substitution group root -->
+ &lt;xs:element name="person" type="person"/>
+
+ &lt;xs:complexType name="superman">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="person">
+ &lt;xs:attribute name="can-fly" type="xs:boolean"/>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="superman"
+ type="superman"
+ substitutionGroup="person"/>
+
+ &lt;xs:complexType name="batman">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="superman">
+ &lt;xs:attribute name="wing-span" type="xs:unsignedInt"/>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="batman"
+ type="batman"
+ substitutionGroup="superman"/>
+
+ &lt;xs:complexType name="supermen">
+ &lt;xs:sequence>
+ &lt;xs:element ref="person" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="supermen" type="supermen"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Conforming XML documents can use the <code>superman</code>
+ and <code>batman</code> types in place of the <code>person</code>
+ type either by specifying the type with the <code>xsi:type</code>
+ attributes or by using the elements from the substitution
+ group, for instance:</p>
+
+
+ <pre class="xml">
+&lt;supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ &lt;person>
+ &lt;name>John Doe&lt;/name>
+ &lt;/person>
+
+ &lt;superman can-fly="false">
+ &lt;name>James "007" Bond&lt;/name>
+ &lt;/superman>
+
+ &lt;superman can-fly="true" wing-span="10" xsi:type="batman">
+ &lt;name>Bruce Wayne&lt;/name>
+ &lt;/superman>
+
+&lt;/supermen>
+ </pre>
+
+ <p>When compiling the schema above with the
+ <code>--generate-polymorphic</code> option, the XSD/e compiler
+ automatically detects that the type hierarchy starting with
+ the <code>person</code> type is polymorphic. A polymorphic
+ type is always variable-length which means objects of polymorphic
+ types are allocated dynamically and are stored and passed around
+ as pointers or references. A polymorphic type also defines a
+ virtual <code>_clone()</code> function (see <a href="#4.2">Section 4.2,
+ "Memory Management"</a>) and a virtual destructor
+ which allow you to copy and delete an instance of a
+ polymorphic type via a pointer to its base. The following code
+ fragment shows how we can parse, access, modify, and serialize
+ the above XML document:</p>
+
+ <pre class="c++">
+// Parse.
+//
+supermen_paggr supermen_p;
+
+// The last argument to the document's constructor indicates that we
+// are parsing polymorphic XML documents.
+//
+xml_schema::document_pimpl doc_p (
+ supermen_p.root_parser (),
+ supermen_p.root_name (),
+ true);
+
+supermen_p.pre ();
+doc_p.parse ("supermen.xml");
+auto_ptr&lt;supermen> sm (supermen_p.post ());
+
+// Print what we've got.
+//
+for (supermen::person_iterator i = sm->person ().begin ();
+ i != sm->person ().end ();
+ ++i)
+{
+ person&amp; p = *i;
+
+ if (batman* b = dynamic_cast&lt;batman*> (&amp;p))
+ {
+ cerr &lt;&lt; b->name () &lt;&lt; ", batman, wing span " &lt;&lt;
+ b->wing_span () &lt;&lt; endl;
+ }
+ else if (superman* s = dynamic_cast&lt;superman*> (&amp;p))
+ {
+ cerr &lt;&lt; s->name () &lt;&lt; ", ";
+
+ if (s->can_fly ())
+ cerr &lt;&lt; "flying ";
+
+ cerr &lt;&lt; "superman" &lt;&lt; endl;
+ }
+ else
+ {
+ cerr &lt;&lt; p.name () &lt;&lt; ", ordinary person" &lt;&lt; endl;
+ }
+}
+
+// Add another superman entry.
+//
+auto_ptr&lt;superman> s (new superman);
+s->name ("Clark Kent");
+s->can_fly (true);
+sm->person ().push_back (s.release ());
+
+// Serialize.
+//
+supermen_saggr supermen_s;
+
+// The last argument to the document's constructor indicates that we
+// are serializing polymorphic XML documents.
+//
+xml_schema::document_simpl doc_s (
+ supermen_s.root_serializer (),
+ supermen_s.root_name (),
+ true);
+
+doc_s.add_no_namespace_schema ("supermen.xsd");
+
+supermen_s.pre (*sm);
+doc_s.serialize (cout, xml_schema::document_simpl::pretty_print);
+supermen_s.post ();
+ </pre>
+
+ <p>In the example above we used the standard C++ RTTI mechanism
+ to detect the object's actual (dynamic) type. If RTTI is not
+ available on your platform, then you can request the generation
+ of custom runtime type information for polymorphic types
+ with the <code>--generate-typeinfo</code> XSD/e compiler
+ option. When this option is specified, each polymorphic
+ type provides the following two public functions:</p>
+
+ <pre class="c++">
+virtual const std::string&amp;
+_dynamic_type () const;
+
+static const std::string&amp;
+_static_type ();
+ </pre>
+
+ <p>Or, if STL is disabled (<a href="#3.1">Section 3.1, "Standard Template
+ Library"</a>), the following two functions:</p>
+
+ <pre class="c++">
+virtual const char*
+_dynamic_type () const;
+
+static const char*
+_static_type ();
+ </pre>
+
+ <p>The <code>_dynamic_type()</code> function returns the object's
+ dynamic type id. The <code>_static_type()</code> function
+ returns the type's static id that can be compared to the
+ dynamic id. The following code fragment shows how
+ we can change the previous example to use custom type information
+ instead of C++ RTTI:</p>
+
+ <pre class="c++">
+for (supermen::person_iterator i = sm->person ().begin ();
+ i != sm->person ().end ();
+ ++i)
+{
+ person&amp; p = *i;
+ const string&amp; dt = p._dynamic_type ();
+
+ if (dt == batman::_static_type ())
+ {
+ batman&amp; b = static_cast&lt;batman&amp;> (p)
+ cerr &lt;&lt; b.name () &lt;&lt; ", batman, wing span " &lt;&lt;
+ b.wing_span () &lt;&lt; endl;
+ }
+ else if (dt == superman::_static_type ())
+ {
+ superman&amp; s = static_cast&lt;superman&amp;> (p)
+ cerr &lt;&lt; s.name () &lt;&lt; ", ";
+
+ if (s.can_fly ())
+ cerr &lt;&lt; "flying ";
+
+ cerr &lt;&lt; "superman" &lt;&lt; endl;
+ }
+ else
+ {
+ cerr &lt;&lt; p.name () &lt;&lt; ", ordinary person" &lt;&lt; endl;
+ }
+}
+ </pre>
+
+ <p>Most of the code presented in this section is taken from the
+ <code>polymorphism</code> example which can be found in the
+ <code>examples/cxx/hybrid/</code> directory of the XSD/e distribution.
+ Handling of <code>xsi:type</code> and substitution groups when used
+ on root elements requires a number of special actions as shown in
+ the <code>polyroot</code> example.</p>
+
+
+ <!-- Built-in XML Schema Type Parsers -->
+
+
+ <h1><a name="5">5 Mapping for Built-In XML Schema Types</a></h1>
+
+ <p>In XML Schema, built-in types, such as <code>int</code>,
+ <code>string</code>, etc., are defined in the XML Schema namespace.
+ By default this namespace is mapped to C++ namespace
+ <code>xml_schema</code> (this mapping can be altered
+ with the <code>--namespace-map</code> option). The following table
+ summarizes the mapping of XML Schema built-in types to C++ types
+ in the C++/Hybrid mapping. Declarations for these types are
+ automatically included into each generated header file.</p>
+
+ <!-- border="1" is necessary for html2ps -->
+ <table id="builtin" border="1">
+ <tr>
+ <th>XML Schema type</th>
+ <th>Alias in the <code>xml_schema</code> namespace</th>
+ <th>C++ type</th>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-length integral types</th>
+ </tr>
+ <!-- 8-bit -->
+ <tr>
+ <td><code>byte</code></td>
+ <td><code>byte</code></td>
+ <td><code>signed&nbsp;char</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedByte</code></td>
+ <td><code>unsigned_byte</code></td>
+ <td><code>unsigned&nbsp;char</code></td>
+ </tr>
+
+ <!-- 16-bit -->
+ <tr>
+ <td><code>short</code></td>
+ <td><code>short_</code></td>
+ <td><code>short</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedShort</code></td>
+ <td><code>unsigned_short</code></td>
+ <td><code>unsigned&nbsp;short</code></td>
+ </tr>
+
+ <!-- 32-bit -->
+ <tr>
+ <td><code>int</code></td>
+ <td><code>int_</code></td>
+ <td><code>int</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedInt</code></td>
+ <td><code>unsigned_int</code></td>
+ <td><code>unsigned&nbsp;int</code></td>
+ </tr>
+
+ <!-- 64-bit -->
+ <tr>
+ <td><code>long</code></td>
+ <td><code>long_</code></td>
+ <td><code>long</code> or<br/> <code>long&nbsp;long</code><br/>
+ <a href="#3.5">Section 3.5, "64-bit Integer Type"</a></td>
+ </tr>
+ <tr>
+ <td><code>unsignedLong</code></td>
+ <td><code>unsigned_long</code></td>
+ <td><code>unsigned&nbsp;long</code> or
+ <code>unsigned&nbsp;long&nbsp;long</code><br/>
+ <a href="#3.5">Section 3.5, "64-bit Integer Type"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-length integral types</th>
+ </tr>
+ <tr>
+ <td><code>integer</code></td>
+ <td><code>integer</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonPositiveInteger</code></td>
+ <td><code>non_positive_integer</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonNegativeInteger</code></td>
+ <td><code>non_negative_integer</code></td>
+ <td><code>unsigned long</code></td>
+ </tr>
+ <tr>
+ <td><code>positiveInteger</code></td>
+ <td><code>positive_integer</code></td>
+ <td><code>unsigned long</code></td>
+ </tr>
+ <tr>
+ <td><code>negativeInteger</code></td>
+ <td><code>negative_integer</code></td>
+ <td><code>long</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">boolean types</th>
+ </tr>
+ <tr>
+ <td><code>boolean</code></td>
+ <td><code>boolean</code></td>
+ <td><code>bool</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>float</code></td>
+ <td><code>float_</code></td>
+ <td><code>float</code></td>
+ </tr>
+ <tr>
+ <td><code>double</code></td>
+ <td><code>double_</code></td>
+ <td><code>double</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>decimal</code></td>
+ <td><code>decimal</code></td>
+ <td><code>double</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">string types</th>
+ </tr>
+ <tr>
+ <td><code>string</code></td>
+ <td><code>string</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>normalizedString</code></td>
+ <td><code>normalized_string</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>token</code></td>
+ <td><code>token</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>Name</code></td>
+ <td><code>name</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>NMTOKEN</code></td>
+ <td><code>nmtoken</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>NMTOKENS</code></td>
+ <td><code>nmtokens</code></td>
+ <td><a href="#5.2">Section 5.2, "Mapping for <code>NMTOKENS</code> and <code>IDREFS</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>NCName</code></td>
+ <td><code>ncname</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>language</code></td>
+ <td><code>language</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">qualified name</th>
+ </tr>
+ <tr>
+ <td><code>QName</code></td>
+ <td><code>qname</code></td>
+ <td><a href="#5.1">Section 5.1, "Mapping for <code>QName</code>"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">ID/IDREF types</th>
+ </tr>
+ <tr>
+ <td><code>ID</code></td>
+ <td><code>id</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREF</code></td>
+ <td><code>idref</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREFS</code></td>
+ <td><code>idrefs</code></td>
+ <td><a href="#5.2">Section 5.2, "Mapping for <code>NMTOKENS</code> and <code>IDREFS</code>"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">URI types</th>
+ </tr>
+ <tr>
+ <td><code>anyURI</code></td>
+ <td><code>uri</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">binary types</th>
+ </tr>
+ <tr>
+ <td><code>base64Binary</code></td>
+ <td><code>base64_binary</code></td>
+ <td><a href="#5.3">Section 5.3, "Mapping for <code>base64Binary</code> and <code>hexBinary</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>hexBinary</code></td>
+ <td><code>hex_binary</code></td>
+ <td><a href="#5.3">Section 5.3, "Mapping for <code>base64Binary</code> and <code>hexBinary</code>"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">date/time types</th>
+ </tr>
+ <tr>
+ <td><code>date</code></td>
+ <td><code>date</code></td>
+ <td><a href="#5.5">Section 5.5, "Mapping for <code>date</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>dateTime</code></td>
+ <td><code>date_time</code></td>
+ <td><a href="#5.6">Section 5.6, "Mapping for <code>dateTime</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>duration</code></td>
+ <td><code>duration</code></td>
+ <td><a href="#5.7">Section 5.7, "Mapping for <code>duration</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>gDay</code></td>
+ <td><code>gday</code></td>
+ <td><a href="#5.8">Section 5.8, "Mapping for <code>gDay</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonth</code></td>
+ <td><code>gmonth</code></td>
+ <td><a href="#5.9">Section 5.9, "Mapping for <code>gMonth</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonthDay</code></td>
+ <td><code>gmonth_day</code></td>
+ <td><a href="#5.10">Section 5.10, "Mapping for <code>gMonthDay</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYear</code></td>
+ <td><code>gyear</code></td>
+ <td><a href="#5.11">Section 5.11, "Mapping for <code>gYear</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYearMonth</code></td>
+ <td><code>gyear_month</code></td>
+ <td><a href="#5.12">Section 5.12, "Mapping for <code>gYearMonth</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>time</code></td>
+ <td><code>time</code></td>
+ <td><a href="#5.13">Section 5.13, "Mapping for <code>time</code>"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">anyType and anySimpleType</th>
+ </tr>
+ <tr>
+ <td><code>anyType</code></td>
+ <td><code>any_type</code></td>
+ <td><a href="#5.14">Section 5.14, "Mapping for <code>anyType</code>"</a></td>
+ </tr>
+ <tr>
+ <td><code>anySimpleType</code></td>
+ <td><code>any_simple_type</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#3.1">Section 3.1, "Standard Template Library"</a></td>
+ </tr>
+ </table>
+
+ <p>As you can see from the table above a number of built-in
+ XML Schema types are mapped to fundamental C++ types such
+ as <code>int</code> or <code>bool</code>. All string-based
+ XML Schema types are mapped to either <code>std::string</code>
+ or <code>char*</code>, depending on whether the use of STL is
+ enabled or not. A number of built-in types, such as
+ <code>QName</code>, the binary types, and the date/time types,
+ do not have suitable fundamental or standard C++ types to map to.
+ These types are implemented from scratch in the XSD/e runtime
+ and are discussed in more detail in the subsequent sections.</p>
+
+ <p>In cases where the schema calls for an inheritance from a built-in
+ type which is mapped to a fundamental C++ type, a special base
+ type corresponding to the fundamental type and defined in the
+ <code>xml_schema</code> namespace is used (C++ does not allow
+ inheritance from fundamental types). For example:</p>
+
+ <pre class="xml">
+&lt;complexType name="measure">
+ &lt;simpleContent>
+ &lt;extension base="int">
+ &lt;attribute name="unit" type="string" use="required"/>
+ &lt;/extension>
+ &lt;/simpleContent>
+&lt;/complexType>
+ </pre>
+
+ <p>The corresponding object model class is shown below:</p>
+
+ <pre class="c++">
+// measure (fixed-length)
+//
+class measure: public xml_schema::int_base
+{
+public:
+ measure ();
+ measure (const measure&amp;);
+ measure&amp; operator= (const measure&amp;);
+
+ // unit
+ //
+ const std::string&amp;
+ unit () const;
+
+ std::string&amp;
+ unit ();
+
+ void
+ unit (const std::string&amp;);
+
+private:
+ ...
+};
+ </pre>
+
+ <p>The <code>xml_schema::int_base</code> class has the following
+ interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class int_base
+ {
+ public:
+ int_base ();
+
+ int_base&amp;
+ operator= (int);
+
+ public:
+ int
+ base_value () const;
+
+ int&amp;
+ base_value ();
+
+ void
+ base_value (int);
+
+ operator const int&amp; () const;
+ operator int&amp; ();
+ };
+}
+ </pre>
+
+ <p>All other base types for fundamental C++ types have similar
+ interfaces. The only exception is the base type for string
+ types when STL is disabled:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_base
+ {
+ public:
+ string_base ();
+
+ string_base&amp;
+ operator= (char* x)
+
+ public:
+ const char*
+ base_value () const;
+
+ char*
+ base_value ();
+
+ void
+ base_value (char* x);
+
+ char*
+ base_value_detach ();
+
+ operator const char* () const;
+ operator char* ();
+ };
+}
+ </pre>
+
+ <p>Note that the <code>string_base</code> object assumes ownership
+ of the strings passed to the assignment operator and the
+ <code>base_value()</code> modifier. If you detach the
+ string value then it should eventually be deallocated with
+ operator <code>delete[]</code>.</p>
+
+ <h2><a name="5.1">5.1 Mapping for <code>QName</code></a></h2>
+
+ <p>The <code>QName</code> built-in XML Schema type is mapped to the
+ <code>qname</code> class which represents an XML qualified name.
+ With STL enabled (<a href="#3.1">Section 3.1, "Standard Template
+ Library"</a>), it has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (const std::string&amp; name);
+ qname (const std::string&amp; prefix, const std::string&amp; name);
+
+ void
+ swap (qname&amp;);
+
+ const std::string&amp;
+ prefix () const;
+
+ std::string&amp;
+ prefix ();
+
+ void
+ prefix (const std::string&amp;);
+
+ const std::string&amp;
+ name () const;
+
+ std::string&amp;
+ name ();
+
+ void
+ name (const std::string&amp;);
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <p>When STL is disabled and C++ exceptions are enabled
+ (<a href="#3.3">Section 3.3, "C++ Exceptions"</a>), the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (char* name);
+ qname (char* prefix, char* name);
+
+ void
+ swap (qname&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ public:
+ char*
+ prefix ();
+
+ const char*
+ prefix () const;
+
+ void
+ prefix (char*);
+
+ void
+ prefix_copy (const char*);
+
+ char*
+ prefix_detach ();
+
+ public:
+ char*
+ name ();
+
+ const char*
+ name () const;
+
+ void
+ name (char*);
+
+ void
+ name_copy (const char*);
+
+ char*
+ name_detach ();
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+</pre>
+
+ <p>The modifier functions and constructors that have the <code>char*</code>
+ argument assume ownership of the passed strings which should be allocated
+ with operator <code>new char[]</code> and will be deallocated with
+ operator <code>delete[]</code> by the <code>qname</code> object.
+ If you detach the underlying prefix or name strings, then they
+ should eventually be deallocated with operator <code>delete[]</code>.
+ </p>
+
+ <p>Finally, if both STL and C++ exceptions are disabled, the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (char* name);
+ qname (char* prefix, char* name);
+
+ void
+ swap (qname&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ public:
+ char*
+ prefix ();
+
+ const char*
+ prefix () const;
+
+ void
+ prefix (char*);
+
+ error
+ prefix_copy (const char*);
+
+ char*
+ prefix_detach ();
+
+ public:
+ char*
+ name ();
+
+ const char*
+ name () const;
+
+ void
+ name (char*);
+
+ error
+ name_copy (const char*);
+
+ char*
+ name_detach ();
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <h2><a name="5.2">5.2 Mapping for <code>NMTOKENS</code> and <code>IDREFS</code></a></h2>
+
+ <p>The <code>NMTOKENS</code> and <code>IDREFS</code> built-in
+ XML Schema types are mapped to the string sequence type which
+ is discussed in <a href="#4.4">Section 4.4, "Attributes and
+ Elements"</a>.</p>
+
+ <h2><a name="5.3">5.3 Mapping for <code>base64Binary</code> and <code>hexBinary</code></a></h2>
+
+ <p>The <code>base64Binary</code> and <code>hexBinary</code> built-in
+ XML Schema types are mapped to the <code>buffer</code> class.
+ With C++ exceptions enabled (<a href="#3.3">Section 3.3, "C++
+ Exceptions"</a>), it has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class buffer
+ {
+ public:
+ class bounds {}; // Out of bounds exception.
+
+ public:
+ buffer ();
+
+ explicit
+ buffer (size_t size);
+ buffer (size_t size, size_t capacity);
+ buffer (const void* data, size_t size);
+ buffer (const void* data, size_t size, size_t capacity);
+
+ enum ownership_value { assume_ownership };
+
+ // This constructor assumes ownership of the memory passed.
+ //
+ buffer (void* data, size_t size, size_t capacity, ownership_value);
+
+ private:
+ buffer (const buffer&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ void
+ assign (void* data, size_t size);
+
+ void
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+
+ void
+ swap (buffer&amp;);
+
+ public:
+ size_t
+ capacity () const;
+
+ bool
+ capacity (size_t);
+
+ public:
+ size_t
+ size () const;
+
+ bool
+ size (size_t);
+
+ public:
+ const char*
+ data () const;
+
+ char*
+ data ();
+
+ const char*
+ begin () const;
+
+ char*
+ begin ();
+
+ const char*
+ end () const;
+
+ char*
+ end ();
+ };
+
+ bool
+ operator== (const buffer&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <p>The last constructor and the <code>attach()</code> member function
+ make the <code>buffer</code> instance assume the ownership of the
+ memory block pointed to by the <code>data</code> argument and
+ eventually release it by calling <code>operator delete()</code>.
+ The <code>detach()</code> member function detaches and returns the
+ underlying memory block which should eventually be released by
+ calling <code>operator delete()</code>.
+ </p>
+
+ <p>The <code>capacity()</code> and <code>size()</code> modifier functions
+ return <code>true</code> if the underlying buffer has moved. The
+ <code>bounds</code> exception is thrown if the constructor or
+ <code>attach()</code> member function arguments violate the
+ <code>(size&nbsp;&lt;=&nbsp;capacity)</code> constraint.</p>
+
+ <p>If C++ exceptions are disabled, the <code>buffer</code> class has
+ the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class buffer
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_bounds,
+ error_no_memory
+ };
+
+ buffer ();
+
+ private:
+ buffer (const buffer&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ error
+ assign (void* data, size_t size);
+
+ error
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+ void
+ swap (buffer&amp;);
+
+ public:
+ size_t
+ capacity () const;
+
+ error
+ capacity (size_t);
+
+ error
+ capacity (size_t, bool&amp; moved);
+
+ public:
+ size_t
+ size () const;
+
+ error
+ size (size_t);
+
+ error
+ size (size_t, bool&amp; moved);
+
+ public:
+ const char*
+ data () const;
+
+ char*
+ data ();
+
+ const char*
+ begin () const;
+
+ char*
+ begin ();
+
+ const char*
+ end () const;
+
+ char*
+ end ();
+ };
+
+ bool
+ operator== (const buffer&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <h2><a name="5.4">5.4 Time Zone Representation</a></h2>
+
+ <p>The <code>date</code>, <code>dateTime</code>, <code>gDay</code>,
+ <code>gMonth</code>, <code>gMonthDay</code>, <code>gYear</code>,
+ <code>gYearMonth</code>, and <code>time</code> XML Schema built-in
+ types all include an optional time zone component. The following
+ <code>time_zone</code> base class is used to represent this
+ information:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class time_zone
+ {
+ public:
+ time_zone ();
+ time_zone (short hours, short minutes);
+
+ bool
+ zone_present () const;
+
+ void
+ zone_reset ();
+
+ short
+ zone_hours () const;
+
+ void
+ zone_hours (short);
+
+ short
+ zone_minutes () const;
+
+ void
+ zone_minutes (short);
+ };
+
+ bool
+ operator== (const time_zone&amp;, const time_zone&amp;);
+
+ bool
+ operator!= (const time_zone&amp;, const time_zone&amp;);
+}
+ </pre>
+
+ <p>The <code>zone_present()</code> accessor function returns <code>true</code>
+ if the time zone is specified. The <code>zone_reset()</code> modifier
+ function resets the time zone object to the "not specified"
+ state. If the time zone offset is negative then both hours and
+ minutes components should be negative.</p>
+
+ <h2><a name="5.5">5.5 Mapping for <code>date</code></a></h2>
+
+ <p>The <code>date</code> built-in XML Schema type is mapped to the
+ <code>date</code> class which represents a year, a day, and a month
+ with an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class date: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ date ();
+
+ date (int year, unsigned short month, unsigned short day);
+
+ date (int year, unsigned short month, unsigned short day,
+ short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+ };
+
+ bool
+ operator== (const date&amp;, const date&amp;);
+
+ bool
+ operator!= (const date&amp;, const date&amp;);
+}
+ </pre>
+
+ <h2><a name="5.6">5.6 Mapping for <code>dateTime</code></a></h2>
+
+ <p>The <code>dateTime</code> built-in XML Schema type is mapped to the
+ <code>date_time</code> class which represents a year, a month, a day,
+ hours, minutes, and seconds with an optional time zone. Its interface
+ is presented below. For more information on the base
+ <code>xml_schema::time_zone</code> class refer to <a href="#5.4">Section
+ 5.4, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class date_time: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ date_time ();
+
+ date_time (int year, unsigned short month, unsigned short day,
+ unsigned short hours, unsigned short minutes,
+ double seconds);
+
+ date_time (int year, unsigned short month, unsigned short day,
+ unsigned short hours, unsigned short minutes,
+ double seconds, short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+
+ unsigned short
+ hours () const;
+
+ void
+ hours (unsigned short);
+
+ unsigned short
+ minutes () const;
+
+ void
+ minutes (unsigned short);
+
+ double
+ seconds () const;
+
+ void
+ seconds (double);
+ };
+
+ bool
+ operator== (const date_time&amp;, const date_time&amp;);
+
+ bool
+ operator!= (const date_time&amp;, const date_time&amp;);
+}
+ </pre>
+
+ <h2><a name="5.7">5.7 Mapping for <code>duration</code></a></h2>
+
+ <p>The <code>duration</code> built-in XML Schema type is mapped to the
+ <code>duration</code> class which represents a potentially
+ negative duration in the form of years, months, days, hours, minutes,
+ and seconds. Its interface is presented below.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class duration
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ duration ();
+
+ duration (bool negative,
+ unsigned int years, unsigned int months, unsigned int days,
+ unsigned int hours, unsigned int minutes, double seconds);
+
+ bool
+ negative () const;
+
+ void
+ negative (bool);
+
+ unsigned int
+ years () const;
+
+ void
+ years (unsigned int);
+
+ unsigned int
+ months () const;
+
+ void
+ months (unsigned int);
+
+ unsigned int
+ days () const;
+
+ void
+ days (unsigned int);
+
+ unsigned int
+ hours () const;
+
+ void
+ hours (unsigned int);
+
+ unsigned int
+ minutes () const;
+
+ void
+ minutes (unsigned int);
+
+ double
+ seconds () const;
+
+ void
+ seconds (double);
+ };
+
+ bool
+ operator== (const duration&amp;, const duration&amp;);
+
+ bool
+ operator!= (const duration&amp;, const duration&amp;);
+}
+ </pre>
+
+
+ <h2><a name="5.8">5.8 Mapping for <code>gDay</code></a></h2>
+
+ <p>The <code>gDay</code> built-in XML Schema type is mapped to the
+ <code>gday</code> class which represents a day of the month with
+ an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gday: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gday ();
+
+ explicit
+ gday (unsigned short day);
+
+ gday (unsigned short day, short zone_hours, short zone_minutes);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+ };
+
+ bool
+ operator== (const gday&amp;, const gday&amp;);
+
+ bool
+ operator!= (const gday&amp;, const gday&amp;);
+}
+ </pre>
+
+ <h2><a name="5.9">5.9 Mapping for <code>gMonth</code></a></h2>
+
+ <p>The <code>gMonth</code> built-in XML Schema type is mapped to the
+ <code>gmonth</code> class which represents a month of the year
+ with an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gmonth: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gmonth ();
+
+ explicit
+ gmonth (unsigned short month);
+
+ gmonth (unsigned short month,
+ short zone_hours, short zone_minutes);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+ };
+
+ bool
+ operator== (const gmonth&amp;, const gmonth&amp;);
+
+ bool
+ operator!= (const gmonth&amp;, const gmonth&amp;);
+}
+ </pre>
+
+ <h2><a name="5.10">5.10 Mapping for <code>gMonthDay</code></a></h2>
+
+ <p>The <code>gMonthDay</code> built-in XML Schema type is mapped to the
+ <code>gmonth_day</code> class which represents a day and a month of
+ the year with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gmonth_day: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gmonth_day ();
+
+ gmonth_day (unsigned short month, unsigned short day);
+
+ gmonth_day (unsigned short month, unsigned short day,
+ short zone_hours, short zone_minutes);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+ };
+
+ bool
+ operator== (const gmonth_day&amp;, const gmonth_day&amp;);
+
+ bool
+ operator!= (const gmonth_day&amp;, const gmonth_day&amp;);
+}
+ </pre>
+
+ <h2><a name="5.11">5.11 Mapping for <code>gYear</code></a></h2>
+
+ <p>The <code>gYear</code> built-in XML Schema type is mapped to the
+ <code>gyear</code> class which represents a year with
+ an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gyear: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gyear ();
+
+ explicit
+ gyear (int year);
+
+ gyear (int year, short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+ };
+
+ bool
+ operator== (const gyear&amp;, const gyear&amp;);
+
+ bool
+ operator!= (const gyear&amp;, const gyear&amp;);
+}
+ </pre>
+
+ <h2><a name="5.12">5.12 Mapping for <code>gYearMonth</code></a></h2>
+
+ <p>The <code>gYearMonth</code> built-in XML Schema type is mapped to the
+ <code>gyear_month</code> class which represents a year and a month
+ with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gyear_month: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gyear_month ();
+
+ gyear_month (int year, unsigned short month);
+
+ gyear_month (int year, unsigned short month,
+ short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+ };
+
+ bool
+ operator== (const gyear_month&amp;, const gyear_month&amp;);
+
+ bool
+ operator!= (const gyear_month&amp;, const gyear_month&amp;);
+}
+ </pre>
+
+
+ <h2><a name="5.13">5.13 Mapping for <code>time</code></a></h2>
+
+ <p>The <code>time</code> built-in XML Schema type is mapped to the
+ <code>time</code> class which represents hours, minutes,
+ and seconds with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#5.4">Section 5.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class time: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ time ();
+
+ time (unsigned short hours, unsigned short minutes, double seconds);
+
+ time (unsigned short hours, unsigned short minutes, double seconds,
+ short zone_hours, short zone_minutes);
+
+ unsigned short
+ hours () const;
+
+ void
+ hours (unsigned short);
+
+ unsigned short
+ minutes () const;
+
+ void
+ minutes (unsigned short);
+
+ double
+ seconds () const;
+
+ void
+ seconds (double);
+ };
+
+ bool
+ operator== (const time&amp;, const time&amp;);
+
+ bool
+ operator!= (const time&amp;, const time&amp;);
+}
+ </pre>
+
+ <h2><a name="5.14">5.14 Mapping for <code>anyType</code></a></h2>
+
+ <p>The <code>anyType</code> built-in XML Schema type is mapped to
+ the <code>any_type</code> class in the <code>xml_schema</code>
+ namespace. With C++ exceptions enabled (<a href="#3.3">Section 3.3,
+ "C++ Exceptions"</a>), it has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class any_type
+ {
+ public:
+ // Custom data.
+ //
+ typedef xml_schema::data_sequence custom_data_sequence;
+ typedef custom_data_sequence::iterator custom_data_iterator;
+ typedef custom_data_sequence::const_iterator custom_data_const_iterator;
+
+ void
+ allocate_custom_data ();
+
+ const custom_data_sequence&amp;
+ custom_data () const;
+
+ custom_data_sequence&amp;
+ custom_data ();
+ };
+}
+ </pre>
+
+ <p>If C++ exceptions are disabled, the <code>any_type</code> class has
+ the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class any_type
+ {
+ public:
+ // Custom data.
+ //
+ typedef xml_schema::data_sequence custom_data_sequence;
+ typedef custom_data_sequence::iterator custom_data_iterator;
+ typedef custom_data_sequence::const_iterator custom_data_const_iterator;
+
+ bool
+ allocate_custom_data ();
+
+ const custom_data_sequence&amp;
+ custom_data () const;
+
+ custom_data_sequence&amp;
+ custom_data ();
+ };
+}
+ </pre>
+
+ <p>The <code>allocate_custom_data()</code> function allocates the
+ custom data sequence. With C++ exceptions disabled, it returns
+ <code>false</code> if memory allocation has failed and <code>true</code>
+ otherwise. For more information on custom data, refer to
+ <a href="#4.9">Section 4.9, "Customizing the Object Model"</a>.</p>
+
+ <p>The default parser and serializer implementations for the
+ <code>anyType</code> built-in type ignore all its content and
+ return an empty <code>any_type</code> instance. If your application
+ needs to access this content, then you will need to provide your
+ own implementations of these parser and serializer and use the
+ custom data sequence to store the extracted data.</p>
+
+ <!-- Parsing and Serialization -->
+
+ <h1><a name="6">6 Parsing and Serialization</a></h1>
+
+ <p>As was mentioned in the introduction, the C++/Hybrid mapping
+ uses the C++/Parser and C++/Serializer mappings for XML parsing
+ and serialization. If your parsing and serialization requirements
+ are fairly basic, for example, parsing from and serializing to
+ a file or a memory buffer, then you don't need to concern yourself
+ with these two underlying mappings. On the other hand, the C++/Parser
+ and C++/Serializer mappings provide well-defined APIs which allow
+ a great amount of flexibility that may be useful in certain situations.
+ In such cases, you may need to get an understanding of how the
+ C++/Parser and C++/Serializer mappings work. See the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml">Embedded
+ C++/Parser Mapping Getting Started Guide</a> and the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml">Embedded
+ C++/Serializer Mapping Getting Started Guide</a> for more detailed
+ information on these mappings.</p>
+
+ <p>For each type defined in XML Schema, the C++/Parser and
+ C++/Serializer mappings generate a parser skeleton class and
+ serializer skeleton class, respectively. These classes manage
+ parsing/serialization state, convert data between text
+ and C++ types, and perform XML Schema validation, if enabled.
+ Parser skeletons deliver the parsed data and serializer
+ skeletons request the data to be serialized with callbacks.
+ These callbacks are implemented by parser and serializer
+ implementation classes that are derived from the skeletons.
+ If the application uses the C++/Parser and C++/Serializer
+ mappings directly, these implementation classes are normally
+ written by the application developer to perform some
+ application-specific actions. In case of the C++/Hybrid mapping,
+ these implementations are automatically generated by the XSD/e
+ compiler to parse XML to object models and to serialize object
+ models to XML.
+ To request the generation of parser skeletons and
+ implementations, you need to specify the <code>--generate-parser</code>
+ XSD/e command line option. Similarly, to generate serializer
+ skeletons and implementations, you will need to use the
+ <code>--generate-serializer</code> option.</p>
+
+ <p>Before an XML document can be parsed or serialized, the
+ individual parser and serializer implementations need to
+ be instantiated and connected to each other. Again, if the
+ application uses the C++/Parser and C++/Serializer mappings
+ directly, this is done by the application developer. While
+ you can also do this with the generated C++/Hybrid parser and
+ serializer implementations, it is easier to request the
+ generation of parser and serializer aggregate classes with
+ the <code>--generate-aggregate</code> options. Aggregate
+ classes instantiate and connect all the necessary individual
+ parser and serializer implementations for a particular root
+ element or type. Consider again the <code>hello.xsd</code>
+ schema from <a href="#2">Chapter 2, "Hello World Example"</a>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="hello">
+ &lt;xs:sequence>
+ &lt;xs:element name="greeting" type="xs:string"/>
+ &lt;xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="hello" type="hello"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>If we compile this schema with the <code>--generate-parser</code>,
+ <code>--generate-serializer</code>, and <code>--generate-aggregate</code>
+ options, we will have two aggregate classes, <code>hello_paggr</code>
+ and <code>hello_saggr</code>, generated for the root <code>hello</code>
+ element. The interface of the <code>hello_paggr</code> class is
+ presented below:</p>
+
+ <pre class="c++">
+class hello_paggr
+{
+public:
+ hello_paggr ();
+
+ void
+ pre ();
+
+ hello*
+ post ();
+
+ hello_pimpl&amp;
+ root_parser ();
+
+ static const char*
+ root_name ();
+
+ static const char*
+ root_namespace ();
+};
+ </pre>
+
+ <p>The <code>pre()</code> and <code>post()</code> functions
+ call the corresponding callbacks on the root parser
+ implementation. The <code>root_parser()</code> function
+ returns the root parser implementation. The <code>root_name()</code>
+ and <code>root_namespace()</code> functions return the
+ root element name and namespace, respectively.</p>
+
+ <p>As was shown in <a href="#2">Chapter 2, "Hello World Example"</a>,
+ we can use this parser aggregate to create the document parser
+ (supplied by the C++/Parser mapping) and perform the parsing:</p>
+
+ <pre class="c++">
+hello_paggr hello_p;
+xml_schema::document_pimpl doc_p (hello_p.root_parser (),
+ hello_p.root_name ());
+hello_p.pre ();
+doc_p.parse ("hello.xml");
+hello* h = hello_p.post ();
+ </pre>
+
+ <p>For more information on the <code>document_pimpl</code> class,
+ including the other variants of the <code>parse()</code> function
+ as well as error handling during parsing, see
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml#7">Chapter 7,
+ "Document Parser and Error Handling"</a> in the Embedded C++/Parser
+ Mapping Getting Started Guide.</p>
+
+ <p>The interface of the <code>hello_saggr</code> serializer aggregate
+ mirrors that of <code>hello_paggr</code> and is presented below:</p>
+
+ <pre class="c++">
+class hello_saggr
+{
+public:
+ hello_saggr ();
+
+ void
+ pre (const hello&amp;);
+
+ void
+ post ();
+
+ hello_simpl&amp;
+ root_serializer ();
+
+ static const char*
+ root_name ();
+
+ static const char*
+ root_namespace ();
+};
+ </pre>
+
+ <p>The <code>pre()</code> and <code>post()</code> functions
+ call the corresponding callbacks on the root serializer
+ implementation. The <code>root_serializer()</code> function
+ returns the root serializer implementation. The
+ <code>root_name()</code> and <code>root_namespace()</code>
+ functions return the root element name and namespace,
+ respectively.</p>
+
+ <p>As was shown in <a href="#2">Chapter 2, "Hello World Example"</a>,
+ we can use this serializer aggregate to create the document
+ serializer (supplied by the C++/Serializer mapping) and perform
+ the serialization:</p>
+
+ <pre class="c++">
+hello_saggr hello_s;
+xml_schema::document_simpl doc_s (hello_s.root_serializer (),
+ hello_s.root_name ());
+hello_s.pre (*h);
+doc_s.serialize (std::cout, xml_schema::document_simpl::pretty_print);
+hello_s.post ();
+ </pre>
+
+ <p>For more information on the <code>document_simpl</code> class,
+ including the other variants of the <code>serialize()</code>
+ function as well as error handling during serialization, see
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml#8">Chapter 8,
+ "Document Serializer and Error Handling"</a> in the Embedded
+ C++/Serializer Mapping Getting Started Guide.</p>
+
+ <h2><a name="6.1">6.1 Customizing Parsers and Serializers</a></h2>
+
+ <p>The C++/Hybrid mapping allows you to customize the generated
+ parser and serializer implementations. This mechanism can be
+ used, for example, to implement filtering, partially
+ event-driven XML processing, as well as parsing of content
+ matched by XML Schema wildcards. Filtering allows only parts
+ of the XML document to be parsed into the object model or only
+ parts of the object model to be serialized to XML. With
+ partially event-driven parsing and serialization, we can
+ process parts of the document as they become available as
+ well as handle documents that are too large to fit into
+ memory. This section expects you to have an understanding
+ of the C++/Parser and C++/Serializer programming models.</p>
+
+ <p>To request customization of a parser or serializer
+ implementation, you will need to specify the
+ <code>--custom-parser</code> or <code>--custom-serializer</code>
+ option, respectively. The argument format for these two options
+ is <code>name[=[base][/include]]]</code>. The <code><i>name</i></code>
+ component is the XML Schema type name being customized. Optional
+ <code><i>base</i></code> is a C++ name that should be given to the
+ generated version. It is normally used as a base for the custom
+ implementation. Optional <code><i>include</i></code> is the header file
+ that defines the custom implementation. It is <code>#include</code>'ed
+ into the generated code immediately after (if <code><i>base</i></code>
+ is specified) or instead of the generated version. The following
+ examples show how we can use these options:</p>
+
+ <pre class="terminal">
+--custom-parser foo
+--custom-parser foo=foo_base_pimpl
+--custom-parser foo=foo_base_pimpl/foo/foo-custom.hxx
+--custom-parser foo=/foo/foo-custom.hxx
+ </pre>
+
+ <p>The first version instructs the XSD/e compiler not to generate
+ the parser implementation for the <code>foo</code> XML Schema
+ type. The second version instructs the compiler to generate
+ the parser implementation for type <code>foo</code> but call
+ it <code>foo_base_pimpl</code>. The third version is similar to the
+ second except that the compiler generates the <code>#include</code>
+ directive with the <code>foo/foo-custom.hxx</code> file (which
+ presumably defines <code>foo_pimpl</code>) right after the
+ <code>foo_base_pimpl</code> class. The last version instructs
+ the XSD/e compiler to include <code>foo/foo-custom.hxx</code>
+ instead of generating the parser implementation for
+ <code>foo</code>. If you omit the last component
+ (<code><i>include</i></code>), then
+ you can include the custom parser/serializer definitions
+ using one of the prologue or epilogue XSD/e compiler options.
+ See the <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a> for details.</p>
+
+ <p>Once you specify the <code>--custom-parser</code> or
+ <code>--custom-serializer</code> option, you will need to
+ provide the custom implementation. You have a choice of either
+ basing it on the generated version and overriding some
+ callbacks or implementing it from scratch.</p>
+
+ <p>In the remainder of this section we will examine how to
+ customize the <code>people</code> parser and serializer
+ implementations from the example presented in <a href="#4">Chapter 4,
+ "Working with Object Models"</a>. Our custom parser
+ implementation will filter the records being parsed
+ based on a person's age. Similarly, the serializer will
+ only serialize records of a specific gender. The code
+ presented below is taken from the <code>filter</code>
+ example in the XSD/e distribution. Other examples
+ related to parser/serializer customization are
+ <code>wildcard</code> and <code>streaming</code>.</p>
+
+ <p>First, we compile the <code>people.xsd</code> schema
+ and instruct the XSD/e compiler to customize the
+ parser and serializer implementations for the <code>people</code>
+ XML Schema type:</p>
+
+ <pre class="terminal">
+$ xsde cxx-hybrid --generate-parser --generate-serializer \
+--custom-parser people=people_base_pimpl/people-custom-pimpl.hxx \
+--custom-serializer people=people_base_simpl/people-custom-simpl.hxx \
+--generate-aggregate people.xsd
+ </pre>
+
+ <p>The custom <code>people_pimpl</code> parser implementation
+ is based on the generated version and is saved to
+ <code>people-custom-pimpl.hxx</code>:</p>
+
+ <pre class="c++">
+class people_pimpl: public people_base_pimpl
+{
+public:
+ void
+ age_filter (unsigned short min, unsigned short max)
+ {
+ min_age_ = min;
+ max_age_ = max;
+ }
+
+ virtual void
+ person (const ::person&amp; p)
+ {
+ // Check if the age constraints are met.
+ //
+ unsigned short age = p.age ();
+
+ if (age >= min_age_ &amp;&amp; age &lt;= max_age_)
+ people_base_pimpl::person (p);
+ }
+
+private:
+ unsigned short min_age_;
+ unsigned short max_age_;
+};
+ </pre>
+
+ <p>Here we override the <code>person()</code> callback and,
+ if the filter conditions are satisfied, call the original
+ version which adds the person record to the object model.
+ Note that if the <code>person</code> object model class
+ were variable-length, then the instance would be
+ dynamically allocated and passed as a pointer. In this
+ situation, if we don't use the object, we need to delete it,
+ for example:</p>
+
+<pre class="c++">
+virtual void
+person (const ::person* p)
+{
+ unsigned short age = p->age ();
+
+ if (age >= min_age_ &amp;&amp; age &lt;= max_age_)
+ people_base_pimpl::person (p);
+ else
+ delete p;
+}
+ </pre>
+
+ <p>The custom <code>people_simpl</code> parser implementation
+ is also based on the generated version and is saved to
+ <code>people-custom-simpl.hxx</code>:</p>
+
+ <pre class="c++">
+class people_simpl: public people_base_simpl
+{
+public:
+ void
+ gender_filter (gender g)
+ {
+ gender_ = g;
+ }
+
+ virtual bool
+ person_next ()
+ {
+ // See if we have any more person records with the gender we
+ // are interested in.
+ //
+ people::person_const_iterator&amp; i = people_base_simpl_state_.person_;
+ people::person_const_iterator&amp; e = people_base_simpl_state_.person_end_;
+
+ for (; i != e; ++i)
+ {
+ if (i->gender () == gender_)
+ break;
+ }
+
+ return i != e;
+ }
+
+private:
+ gender gender_;
+};
+ </pre>
+
+ <p>Here we override the <code>person_next()</code> callback
+ where we locate the next record that satisfies the filter
+ conditions. Note that we use the serialization state
+ provided by the generated <code>people_base_simpl</code>
+ implementation.</p>
+
+ <p>The following code fragment shows a test driver that uses
+ the above implementations to filter the data during parsing
+ and serialization:</p>
+
+ <pre class="c++">
+#include &lt;memory>
+#include &lt;iostream>
+
+#include "people.hxx"
+
+#include "people-pimpl.hxx"
+#include "people-simpl.hxx"
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ // Parse.
+ //
+ people_paggr people_p;
+ people_pimpl&amp; root_p = people_p.root_parser ();
+
+ // Initialize the filter.
+ //
+ root_p.age_filter (1, 30);
+
+ xml_schema::document_pimpl doc_p (root_p, people_p.root_name ());
+
+ people_p.pre ();
+ doc_p.parse (argv[1]);
+ auto_ptr&lt;people> ppl (people_p.post ());
+
+ // Print what we've got.
+ //
+ people::person_sequence&amp; ps = ppl->person ();
+
+ for (people::person_iterator i = ps.begin (); i != ps.end (); ++i)
+ {
+ cerr &lt;&lt; "first: " &lt;&lt; i->first_name () &lt;&lt; endl
+ &lt;&lt; "last: " &lt;&lt; i->last_name () &lt;&lt; endl
+ &lt;&lt; "gender: " &lt;&lt; i->gender ().string () &lt;&lt; endl
+ &lt;&lt; "age: " &lt;&lt; i->age () &lt;&lt; endl
+ &lt;&lt; endl;
+ }
+
+ // Serialize.
+ //
+ people_saggr people_s;
+ people_simpl&amp; root_s = people_s.root_serializer ();
+
+ // Initialize the filter.
+ //
+ root_s.gender_filter (gender::female);
+
+ xml_schema::document_simpl doc_s (root_s, people_s.root_name ());
+
+ people_s.pre (*ppl);
+ doc_s.serialize (cout, xml_schema::document_simpl::pretty_print);
+ people_s.post ();
+}
+ </pre>
+
+ <p>If we run this test driver on the following XML document:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;people>
+
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+
+ &lt;person>
+ &lt;first-name>Joe&lt;/first-name>
+ &lt;last-name>Dirt&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>25&lt;/age>
+ &lt;/person>
+
+&lt;/people>
+ </pre>
+
+ <p>We will get the following output:</p>
+
+ <pre class="terminal">
+first: Jane
+last: Doe
+gender: female
+age: 28
+
+first: Joe
+last: Dirt
+gender: male
+age: 25
+
+&lt;people>
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+
+ <!-- Binary Representations -->
+
+ <h1><a name="7">7 Binary Representation</a></h1>
+
+ <p>Besides reading from and writing to XML, the C++/Hybrid mapping
+ also allows you to save the object model to and load it from a
+ number of predefined as well as custom data representation
+ formats. The predefined binary formats are CDR (Common Data
+ Representation) and XDR (eXternal Data Representation). A
+ custom format can easily be supported by providing
+ insertion and extraction operators for basic types.</p>
+
+ <p>Binary representations contain only the data without any meta
+ information or markup. Consequently, saving to and loading
+ from a binary representation can be an order of magnitude
+ faster as well as result in a much smaller footprint compared
+ to parsing and serializing the same data in XML. Furthermore,
+ the resulting representation is normally several times smaller
+ than the equivalent XML representation. These properties make a
+ binary representation ideal for internal data exchange and storage.
+ A typical application that uses this facility stores the data and
+ communicates within the system using a binary format and reads/writes
+ the data in XML when communicating with the outside world.</p>
+
+ <p>In order to request the generation of insertion and extraction
+ operators for a specific predefined or custom data representation
+ stream, you will need to use the <code>--generate-insertion</code>
+ and <code>--generate-extraction</code> compiler options. See the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a> for more information.</p>
+
+ <p>The XSD/e runtime provides implementations of the base insertion
+ and extraction operators for the ACE (Adaptive Communication
+ Environment) CDR streams and the XDR API. The XDR API is available
+ out of the box on most POSIX systems as part of Sun RPC. On other
+ platforms you may need to install a third-party library which
+ provides the XDR API.
+
+ The XSD/e compiler recognizes two special argument values to the
+ <code>--generate-insertion</code> and <code>--generate-extraction</code>
+ options: <code>CDR</code> and <code>XDR</code>. When one of these
+ arguments is specified, the corresponding implementation from the
+ XSD/e runtime is automatically used. The following two sections
+ describe each of these two formats in more detail. It is also
+ possible to add support for saving the object model to and loading
+ it from custom data representation formats as discussed in the
+ last section of this chapter.</p>
+
+ <p>The saving of the object model types to a representation stream
+ is implemented with stream insertion operators
+ (<code>operator&lt;&lt;</code>). Similarly, loading of the object
+ model from a representation stream is implemented with stream
+ extraction operators (<code>operator>></code>). The insertion
+ and extraction operators for the built-in XML Schema types as
+ well as the sequence templates are provided by the stream
+ implementation (that is, by the XSD/e runtime in case of CDR and
+ XDR and by you for custom formats). The XSD/e compiler automatically
+ generates insertion and extraction operators for the generated object
+ model types.</p>
+
+ <p>When C++ exceptions are enabled (<a href="#3.3">Section 3.3, "C++
+ Exceptions"</a>), the signatures of the insertion and extraction
+ operators are as follows:</p>
+
+ <pre class="c++">
+void
+operator&lt;&lt; (ostream&amp;, const type&amp;);
+
+void
+operator>> (istream&amp;, type&amp;);
+ </pre>
+
+ <p>The insertion and extraction errors are indicated by throwing
+ stream-specific exceptions. When C++ exceptions are disabled,
+ the signatures of the insertion and extraction operators are
+ as follows:</p>
+
+ <pre class="c++">
+bool
+operator&lt;&lt; (ostream&amp;, const type&amp;);
+
+bool
+operator>> (istream&amp;, type&amp;);
+ </pre>
+
+ <p>In this case the insertion and extraction operators return
+ <code>true</code> if the operation was successful and
+ <code>false</code> otherwise. The stream object may
+ provide additional error information.</p>
+
+
+ <h2><a name="7.1">7.1 CDR (Common Data Representation)</a></h2>
+
+ <p>When you request the generation of CDR stream insertion and extraction
+ operators, the <code>ocdrstream</code> and <code>icdrstream</code>
+ types are defined in the <code>xml_schema</code> namespace. Additionally,
+ if C++ exceptions are enabled, the <code>cdr_exception</code> exception
+ is also defined in <code>xml_schema</code>. The <code>icdrstream</code>
+ and <code>ocdrstream</code> types are simple wrappers for the
+ ACE_InputCDR and ACE_OutputCDR streams. The following code fragment
+ shows how we can use these types when C++ exceptions are enabled:</p>
+
+ <pre class="c++">
+try
+{
+ const type&amp; x = ... // Object model.
+
+ // Save to a CDR stream.
+ //
+ ACE_OutputCDR ace_ocdr;
+ xml_schema::ocdrstream ocdr (ace_ocdr);
+
+ ocdr &lt;&lt; x;
+
+ // Load from a CDR stream.
+ //
+ ACE_InputCDR ace_icdr (buf, size);
+ xml_schema::icdrstream icdr (ace_icdr);
+
+ type copy;
+ icdr >> copy;
+}
+catch (const xml_schema::cdr_exception&amp;)
+{
+ cerr &lt;&lt; "CDR operation failed" &lt;&lt; endl;
+}
+ </pre>
+
+ <p>The same code fragment but when C++ exceptions are disabled:</p>
+
+ <pre class="c++">
+const type&amp; x = ... // Object model.
+
+// Save to a CDR stream.
+//
+ACE_OutputCDR ace_ocdr;
+xml_schema::ocdrstream ocdr (ace_ocdr);
+
+if (!(ocdr &lt;&lt; x))
+{
+ cerr &lt;&lt; "CDR operation failed" &lt;&lt; endl;
+}
+
+// Load from a CDR stream.
+//
+ACE_InputCDR ace_icdr (buf, size);
+xml_schema::icdrstream icdr (ace_icdr);
+
+type copy;
+
+if (!(icdr >> copy))
+{
+ cerr &lt;&lt; "CDR operation failed" &lt;&lt; endl;
+}
+ </pre>
+
+ <p>The <code>cdr</code> example which can be found in the
+ <code>examples/cxx/hybrid/binary/</code> directory of the XSD/e
+ distribution includes complete source code that shows how to
+ save the object model to and load it from the CDR format.</p>
+
+ <h2><a name="7.2">7.2 XDR (eXternal Data Representation)</a></h2>
+
+ <p>When you request the generation of XDR stream insertion and extraction
+ operators, the <code>oxdrstream</code> and <code>xcdrstream</code>
+ types are defined in the <code>xml_schema</code> namespace. Additionally,
+ if C++ exceptions are enabled, the <code>xdr_exception</code> exception
+ is also defined in <code>xml_schema</code>. The <code>ixdrstream</code>
+ and <code>oxdrstream</code> types are simple wrappers for the XDR
+ API. The following code fragment shows how we can use these types
+ when C++ exceptions are enabled:</p>
+
+ <pre class="c++">
+try
+{
+ const type&amp; x = ... // Object model.
+
+ // Save to a XDR stream.
+ //
+ XDR xdr;
+ xdrrec_create (&amp;xdr, ...);
+ xml_schema::oxdrstream oxdr (xdr);
+
+ oxdr &lt;&lt; x;
+
+ // Load from a XDR stream.
+ //
+ xdrrec_create (&amp;xdr, ...);
+ xml_schema::ixdrstream ixdr (xdr);
+
+ type copy;
+ ixdr >> copy;
+}
+catch (const xml_schema::xdr_exception&amp;)
+{
+ cerr &lt;&lt; "XDR operation failed" &lt;&lt; endl;
+}
+ </pre>
+
+ <p>The same code fragment but when C++ exceptions are disabled:</p>
+
+ <pre class="c++">
+const type&amp; x = ... // Object model.
+
+// Save to a XDR stream.
+//
+XDR xdr;
+xdrrec_create (&amp;xdr, ...);
+xml_schema::oxdrstream oxdr (xdr);
+
+if (!(oxdr &lt;&lt; x))
+{
+ cerr &lt;&lt; "XDR operation failed" &lt;&lt; endl;
+}
+
+// Load from a XDR stream.
+//
+xdrrec_create (&amp;xdr, ...);
+xml_schema::ixdrstream ixdr (xdr);
+
+type copy;
+
+if (!(ixdr >> copy))
+{
+ cerr &lt;&lt; "XDR operation failed" &lt;&lt; endl;
+}
+ </pre>
+
+ <p>The <code>xdr</code> example which can be found in the
+ <code>examples/cxx/hybrid/binary/</code> directory of the XSD/e
+ distribution includes complete source code that shows how to
+ save the object model to and load it from the XDR format.</p>
+
+
+ <h2><a name="7.3">7.3 Custom Representations</a></h2>
+
+ <p>To add support for saving the object model to and loading it
+ from a custom format, you will need to perform the following
+ general steps:</p>
+
+ <ol class="list">
+ <li>Generate a header file corresponding to the XML Schema
+ namespace using the <code>--generate-xml-schema</code>
+ compiler option.</li>
+
+ <li>Implement custom stream insertion and extraction operators
+ for the built-in XML Schema types and sequence templates.
+ Include the header file obtained in the previous step to
+ get definitions for these types.</li>
+
+ <li>Compile your schemas with the <code>--generate-insertion</code>
+ and <code>--generate-extraction</code> options. The arguments
+ to these options will be your custom output and input stream
+ types, respectively. Use the <code>--hxx-prologue</code>
+ option to include the definitions for these stream types
+ into the generated code. Also use the
+ <code>--extern-xml-schema</code> option to include the
+ header file obtained in the first step instead of generating
+ the same code directly.</li>
+ </ol>
+
+ <p>The <code>custom</code> example which can be found in the
+ <code>examples/cxx/hybrid/binary/</code> directory of the XSD/e
+ distribution includes complete source code that shows how to
+ save the object model to and load it from a custom format using
+ the raw binary representation as an example. You can use the
+ source code from this example as a base to implement support
+ for your own format.</p>
+
+ </div>
+</div>
+
+
+</body>
+</html>
diff --git a/doc/cxx/hybrid/guide/makefile b/doc/cxx/hybrid/guide/makefile
new file mode 100644
index 0000000..296a745
--- /dev/null
+++ b/doc/cxx/hybrid/guide/makefile
@@ -0,0 +1,48 @@
+# file : doc/cxx/hybrid/guide/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2006-2011 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+default := $(out_base)/
+dist := $(out_base)/.dist
+dist-win := $(out_base)/.dist-win
+cleandoc := $(out_base)/.cleandoc
+
+# Build.
+#
+$(default): $(out_base)/cxx-hybrid-e-guide.ps \
+ $(out_base)/cxx-hybrid-e-guide.pdf
+
+
+$(out_base)/cxx-hybrid-e-guide.ps: $(src_base)/index.xhtml \
+ $(src_base)/figure-1.png \
+ $(src_base)/guide.html2ps \
+ | $(out_base)/.
+ $(call message,html2ps $<,html2ps -f $(src_base)/guide.html2ps -o $@ $<)
+
+$(out_base)/cxx-hybrid-e-guide.pdf: $(out_base)/cxx-hybrid-e-guide.ps | $(out_base)/.
+ $(call message,ps2pdf $<,ps2pdf14 $< $@)
+
+# Dist.
+#
+$(dist): path := $(subst $(src_root)/,,$(src_base))
+$(dist): $(out_base)/cxx-hybrid-e-guide.ps $(out_base)/cxx-hybrid-e-guide.pdf
+ $(call install-data,$(src_base)/figure-1.png,$(dist_prefix)/$(path)/figure-1.png)
+ $(call install-data,$(src_base)/index.xhtml,$(dist_prefix)/$(path)/index.xhtml)
+ $(call install-data,$(out_base)/cxx-hybrid-e-guide.ps,$(dist_prefix)/$(path)/cxx-hybrid-e-guide.ps)
+ $(call install-data,$(out_base)/cxx-hybrid-e-guide.pdf,$(dist_prefix)/$(path)/cxx-hybrid-e-guide.pdf)
+
+$(dist-win): $(dist)
+
+
+# Clean.
+#
+$(cleandoc):
+ $(call message,rm $$1,rm -f $$1,$(out_base)/cxx-hybrid-e-guide.ps)
+ $(call message,rm $$1,rm -f $$1,$(out_base)/cxx-hybrid-e-guide.pdf)
+
+# How to.
+#
+$(call include,$(bld_root)/install.make)
diff --git a/doc/cxx/makefile b/doc/cxx/makefile
new file mode 100644
index 0000000..4704c60
--- /dev/null
+++ b/doc/cxx/makefile
@@ -0,0 +1,20 @@
+# file : doc/cxx/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2006-2011 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make
+
+mappings := hybrid/guide parser/guide serializer/guide
+
+default := $(out_base)/
+dist := $(out_base)/.dist
+dist-win := $(out_base)/.dist-win
+cleandoc := $(out_base)/.cleandoc
+
+$(default): $(addprefix $(out_base)/,$(addsuffix /,$(mappings)))
+$(dist): $(addprefix $(out_base)/,$(addsuffix /.dist,$(mappings)))
+$(dist-win): $(addprefix $(out_base)/,$(addsuffix /.dist-win,$(mappings)))
+$(cleandoc): $(addprefix $(out_base)/,$(addsuffix /.cleandoc,$(mappings)))
+
+$(foreach m,$(mappings),$(call import,$(src_base)/$m/makefile))
diff --git a/doc/cxx/parser/guide/figure-1.png b/doc/cxx/parser/guide/figure-1.png
new file mode 100644
index 0000000..15d1723
--- /dev/null
+++ b/doc/cxx/parser/guide/figure-1.png
Binary files differ
diff --git a/doc/cxx/parser/guide/figure-1.svg b/doc/cxx/parser/guide/figure-1.svg
new file mode 100644
index 0000000..d994a79
--- /dev/null
+++ b/doc/cxx/parser/guide/figure-1.svg
@@ -0,0 +1,373 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docbase="/tmp"
+ sodipodi:docname="figure-1.svg"
+ inkscape:export-filename="/home/boris/tmp/figure-1.png"
+ inkscape:export-xdpi="76.195885"
+ inkscape:export-ydpi="76.195885">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lend"
+ style="overflow:visible;">
+ <path
+ id="path2934"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.8) rotate(180) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Dot_l"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Dot_l"
+ style="overflow:visible">
+ <path
+ id="path2875"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+ transform="scale(0.8) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path2928"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Dot_m"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Dot_m"
+ style="overflow:visible">
+ <path
+ id="path2872"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+ transform="scale(0.4) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path2937"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path2910"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.98994949"
+ inkscape:cx="328.23027"
+ inkscape:cy="733.01096"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1280"
+ inkscape:window-height="991"
+ inkscape:window-x="154"
+ inkscape:window-y="44" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <g
+ id="g3902">
+ <rect
+ y="194.64178"
+ x="24.142784"
+ height="106.2678"
+ width="149.70432"
+ id="rect1872"
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.29799986;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3038"
+ y="219.99649"
+ x="28.284279"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;color:black;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Monospace"
+ xml:space="preserve"><tspan
+ y="219.99649"
+ x="28.284279"
+ id="tspan3064"
+ sodipodi:role="line">class people_pimpl</tspan><tspan
+ y="236.24649"
+ x="28.284279"
+ id="tspan3066"
+ sodipodi:role="line">{</tspan><tspan
+ y="252.49649"
+ x="28.284279"
+ id="tspan3068"
+ sodipodi:role="line"> void </tspan><tspan
+ y="268.74649"
+ x="28.284279"
+ id="tspan3070"
+ sodipodi:role="line"> person ();</tspan><tspan
+ y="284.99649"
+ x="28.284279"
+ id="tspan3072"
+ sodipodi:role="line">};</tspan></text>
+ </g>
+ <g
+ id="g3881">
+ <rect
+ y="124.93772"
+ x="252.43373"
+ height="245.67592"
+ width="180.01601"
+ id="rect5750"
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:9.12976837;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="100%"
+ id="text5752"
+ y="148.27567"
+ x="257.5889"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;color:black;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Monospace"
+ xml:space="preserve"><tspan
+ y="148.27567"
+ x="257.5889"
+ id="tspan5900"
+ sodipodi:role="line">class person_pimpl</tspan><tspan
+ y="161.27567"
+ x="257.5889"
+ id="tspan5902"
+ sodipodi:role="line">{</tspan><tspan
+ y="174.27567"
+ x="257.5889"
+ id="tspan5904"
+ sodipodi:role="line"> void</tspan><tspan
+ y="187.27567"
+ x="257.5889"
+ id="tspan5906"
+ sodipodi:role="line"> first_name (string);</tspan><tspan
+ y="200.27567"
+ x="257.5889"
+ id="tspan5908"
+ sodipodi:role="line" /><tspan
+ y="213.27567"
+ x="257.5889"
+ id="tspan5910"
+ sodipodi:role="line"> void</tspan><tspan
+ y="226.27567"
+ x="257.5889"
+ id="tspan5912"
+ sodipodi:role="line"> last_name (string);</tspan><tspan
+ y="239.27567"
+ x="257.5889"
+ id="tspan5914"
+ sodipodi:role="line" /><tspan
+ y="252.27567"
+ x="257.5889"
+ id="tspan5916"
+ sodipodi:role="line"> void</tspan><tspan
+ y="265.27567"
+ x="257.5889"
+ id="tspan5918"
+ sodipodi:role="line"> gender ();</tspan><tspan
+ y="278.27567"
+ x="257.5889"
+ id="tspan5920"
+ sodipodi:role="line" /><tspan
+ y="291.27567"
+ x="257.5889"
+ id="tspan5922"
+ sodipodi:role="line"> void</tspan><tspan
+ y="304.27567"
+ x="257.5889"
+ id="tspan5924"
+ sodipodi:role="line"> age (short);</tspan><tspan
+ y="317.27567"
+ x="257.5889"
+ id="tspan5926"
+ sodipodi:role="line"> </tspan><tspan
+ y="330.27567"
+ x="257.5889"
+ id="tspan5928"
+ sodipodi:role="line"> void</tspan><tspan
+ y="343.27567"
+ x="257.5889"
+ id="tspan5930"
+ sodipodi:role="line"> post_person ();</tspan><tspan
+ y="356.27567"
+ x="257.5889"
+ id="tspan5932"
+ sodipodi:role="line">};</tspan></text>
+ </g>
+ <g
+ id="g3845">
+ <rect
+ y="77.741814"
+ x="506.28357"
+ height="99.610825"
+ width="151.1286"
+ id="rect5955"
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <flowRoot
+ transform="translate(-5.050762,12.10153)"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ id="flowRoot5957"
+ xml:space="preserve"><flowRegion
+ id="flowRegion5959"><rect
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ y="74.534515"
+ x="516.18793"
+ height="88.893425"
+ width="143.44167"
+ id="rect5961" /></flowRegion><flowPara
+ id="flowPara5965">class string_pimpl</flowPara><flowPara
+ id="flowPara5967">{</flowPara><flowPara
+ id="flowPara5969"> string</flowPara><flowPara
+ id="flowPara5971"> post_string ();</flowPara><flowPara
+ id="flowPara5973">};</flowPara><flowPara
+ id="flowPara5975" /></flowRoot> </g>
+ <g
+ id="g3857">
+ <rect
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect5977"
+ width="151.1286"
+ height="99.610825"
+ x="506.28357"
+ y="316.15808" />
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot5979"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ transform="translate(-5.050761,250.5178)"
+ inkscape:export-filename="/tmp/figure-1.png"
+ inkscape:export-xdpi="546.53815"
+ inkscape:export-ydpi="546.53815"><flowRegion
+ id="flowRegion5981"><rect
+ id="rect5983"
+ width="143.44167"
+ height="88.893425"
+ x="516.18793"
+ y="74.534515"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace" /></flowRegion><flowPara
+ id="flowPara5985">class short_pimpl</flowPara><flowPara
+ id="flowPara5987">{</flowPara><flowPara
+ id="flowPara5989"> short</flowPara><flowPara
+ id="flowPara5991"> post_short ();</flowPara><flowPara
+ id="flowPara5993">};</flowPara><flowPara
+ id="flowPara5995" /></flowRoot> </g>
+ <g
+ id="g3869">
+ <rect
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect6023"
+ width="151.1286"
+ height="99.610825"
+ x="505.7785"
+ y="196.93977" />
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot6025"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ transform="translate(-5.555838,129.2792)"><flowRegion
+ id="flowRegion6027"><rect
+ id="rect6029"
+ width="143.44167"
+ height="88.893425"
+ x="516.18793"
+ y="74.534515"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace" /></flowRegion><flowPara
+ id="flowPara6031">class gender_pimpl</flowPara><flowPara
+ id="flowPara6033">{</flowPara><flowPara
+ id="flowPara6035"> void</flowPara><flowPara
+ id="flowPara6037"> post_gender ();</flowPara><flowPara
+ id="flowPara6039">};</flowPara><flowPara
+ id="flowPara6041" /></flowRoot> </g>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend)"
+ d="M 265.67011,339.69956 L 210.41811,339.34242 L 210.77124,264.14332 L 127.7843,264.4432"
+ id="path6051"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccs" />
+ <path
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-type="polyline"
+ id="path6077"
+ d="M 518.20825,383.6412 L 471.23616,384.14628 L 471.4887,300.55615 L 368.70568,300.80869"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 517.1981,262.42289 L 353.55339,262.42289"
+ id="path6081"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccs" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 518.57143,145.93361 L 470.35714,146.14281 L 470.53572,183.07646 L 431.42857,183.79075"
+ id="path6089"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 470.46175,178.43361 L 470.89286,222.36218 L 423.21428,222.71932"
+ id="path6091"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="ccc" />
+ </g>
+</svg>
diff --git a/doc/cxx/parser/guide/guide.html2ps b/doc/cxx/parser/guide/guide.html2ps
new file mode 100644
index 0000000..bfeca9e
--- /dev/null
+++ b/doc/cxx/parser/guide/guide.html2ps
@@ -0,0 +1,65 @@
+@html2ps {
+ option {
+ toc: hb;
+ colour: 1;
+ hyphenate: 1;
+ titlepage: 1;
+ }
+
+ datefmt: "%B %Y";
+
+ titlepage {
+ content: "
+<div align=center>
+ <h1><big>Embedded C++/Parser Mapping</big></h1>
+ <h1><big>Getting Started Guide</big></h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+</div>
+ <p>Copyright &copy; 2005-2011 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href='http://www.codesynthesis.com/licenses/fdl-1.2.txt'>GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml'>XHTML</a>,
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/cxx-parser-e-guide.pdf'>PDF</a>, and
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/cxx-parser-e-guide.ps'>PostScript</a>.</p>";
+ }
+
+ toc {
+ indent: 2em;
+ }
+
+ header {
+ odd-right: $H;
+ even-left: $H;
+ }
+
+ footer {
+ odd-left: $D;
+ odd-center: $T;
+ odd-right: $N;
+
+ even-left: $N;
+ even-center: $T;
+ even-right: $D;
+ }
+}
+
+body {
+ font-size: 12pt;
+ text-align: justify;
+}
+
+pre {
+ font-size: 10pt;
+}
diff --git a/doc/cxx/parser/guide/index.xhtml b/doc/cxx/parser/guide/index.xhtml
new file mode 100644
index 0000000..d070c5a
--- /dev/null
+++ b/doc/cxx/parser/guide/index.xhtml
@@ -0,0 +1,5383 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<head>
+ <title>Embedded C++/Parser Mapping Getting Started Guide</title>
+
+ <meta name="copyright" content="&copy; 2005-2011 Code Synthesis Tools CC"/>
+ <meta name="keywords" content="xsd,xml,schema,c++,mapping,data,binding,parser,validation,embedded,mobile"/>
+ <meta name="description" content="Embedded C++/Parser Mapping Getting Started Guide"/>
+
+ <link rel="stylesheet" type="text/css" href="../../../default.css" />
+
+<style type="text/css">
+ pre {
+ padding : 0 0 0 0em;
+ margin : 0em 0em 0em 0;
+
+ font-size : 102%
+ }
+
+ body {
+ min-width: 48em;
+ }
+
+ h1 {
+ font-weight: bold;
+ font-size: 200%;
+ line-height: 1.2em;
+ }
+
+ h2 {
+ font-weight : bold;
+ font-size : 150%;
+
+ padding-top : 0.8em;
+ }
+
+ h3 {
+ font-size : 140%;
+ padding-top : 0.8em;
+ }
+
+ /* Adjust indentation for three levels. */
+ #container {
+ max-width: 48em;
+ }
+
+ #content {
+ padding: 0 0.1em 0 4em;
+ /*background-color: red;*/
+ }
+
+ #content h1 {
+ margin-left: -2.06em;
+ }
+
+ #content h2 {
+ margin-left: -1.33em;
+ }
+
+ /* Title page */
+
+ #titlepage {
+ padding: 2em 0 1em 0;
+ border-bottom: 1px solid black;
+ }
+
+ #titlepage .title {
+ font-weight: bold;
+ font-size: 200%;
+ text-align: center;
+ }
+
+ #titlepage #first-title {
+ padding: 1em 0 0.4em 0;
+ }
+
+ #titlepage #second-title {
+ padding: 0.4em 0 2em 0;
+ }
+
+ /* Lists */
+ ul.list li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+ }
+
+ ol.steps {
+ padding-left : 1.8em;
+ }
+
+ ol.steps li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+ }
+
+
+ div.img {
+ text-align: center;
+ padding: 2em 0 2em 0;
+ }
+
+ /* */
+ dl dt {
+ padding : 0.8em 0 0 0;
+ }
+
+ /* TOC */
+ table.toc {
+ border-style : none;
+ border-collapse : separate;
+ border-spacing : 0;
+
+ margin : 0.2em 0 0.2em 0;
+ padding : 0 0 0 0;
+ }
+
+ table.toc tr {
+ padding : 0 0 0 0;
+ margin : 0 0 0 0;
+ }
+
+ table.toc * td, table.toc * th {
+ border-style : none;
+ margin : 0 0 0 0;
+ vertical-align : top;
+ }
+
+ table.toc * th {
+ font-weight : normal;
+ padding : 0em 0.1em 0em 0;
+ text-align : left;
+ white-space : nowrap;
+ }
+
+ table.toc * table.toc th {
+ padding-left : 1em;
+ }
+
+ table.toc * td {
+ padding : 0em 0 0em 0.7em;
+ text-align : left;
+ }
+
+ /* Built-in table */
+ #builtin {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+ }
+
+ #builtin th, #builtin td {
+ border: 1px solid;
+ padding : 0.9em 0.9em 0.7em 0.9em;
+ }
+
+ #builtin th {
+ background : #cde8f6;
+ }
+
+ #builtin td {
+ text-align: left;
+ }
+
+ /* XML Schema features table. */
+ #features {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+ }
+
+ #features th, #features td {
+ border: 1px solid;
+ padding : 0.6em 0.6em 0.6em 0.6em;
+ }
+
+ #features th {
+ background : #cde8f6;
+ }
+
+ #features td {
+ text-align: left;
+ }
+</style>
+
+
+</head>
+
+<body>
+<div id="container">
+ <div id="content">
+
+ <div class="noprint">
+
+ <div id="titlepage">
+ <div class="title" id="first-title">Embedded C++/Parser Mapping</div>
+ <div class="title" id="second-title">Getting Started Guide</div>
+
+ <p>Copyright &copy; 2005-2011 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href="http://www.codesynthesis.com/licenses/fdl-1.2.txt">GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/index.xhtml">XHTML</a>,
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/cxx-parser-e-guide.pdf">PDF</a>, and
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/cxx-parser-e-guide.ps">PostScript</a>.</p>
+
+ </div>
+
+ <h1>Table of Contents</h1>
+
+ <table class="toc">
+ <tr>
+ <th></th><td><a href="#0">Preface</a>
+ <table class="toc">
+ <tr><th></th><td><a href="#0.1">About This Document</a></td></tr>
+ <tr><th></th><td><a href="#0.2">More Information</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>1</th><td><a href="#1">Introduction</a>
+ <table class="toc">
+ <tr><th>1.1</th><td><a href="#1.1">Mapping Overview</a></td></tr>
+ <tr><th>1.2</th><td><a href="#1.2">Benefits</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>2</th><td><a href="#2">Hello World Example</a>
+ <table class="toc">
+ <tr><th>2.1</th><td><a href="#2.1">Writing XML Document and Schema</a></td></tr>
+ <tr><th>2.2</th><td><a href="#2.2">Translating Schema to C++</a></td></tr>
+ <tr><th>2.3</th><td><a href="#2.3">Implementing Application Logic</a></td></tr>
+ <tr><th>2.4</th><td><a href="#2.4">Compiling and Running</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>3</th><td><a href="#3">Parser Skeletons</a>
+ <table class="toc">
+ <tr><th>3.1</th><td><a href="#3.1">Implementing the Gender Parser</a></td></tr>
+ <tr><th>3.2</th><td><a href="#3.2">Implementing the Person Parser</a></td></tr>
+ <tr><th>3.3</th><td><a href="#3.3">Implementing the People Parser</a></td></tr>
+ <tr><th>3.4</th><td><a href="#3.4">Connecting the Parsers Together</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>4</th><td><a href="#4">Type Maps</a>
+ <table class="toc">
+ <tr><th>4.1</th><td><a href="#4.1">Object Model</a></td></tr>
+ <tr><th>4.2</th><td><a href="#4.2">Type Map File Format</a></td></tr>
+ <tr><th>4.3</th><td><a href="#4.3">Parser Implementations</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>5</th><td><a href="#5">Mapping Configuration</a>
+ <table class="toc">
+ <tr><th>5.1</th><td><a href="#5.1">Standard Template Library</a></td></tr>
+ <tr><th>5.2</th><td><a href="#5.2">Input/Output Stream Library</a></td></tr>
+ <tr><th>5.3</th><td><a href="#5.3">C++ Exceptions</a></td></tr>
+ <tr><th>5.4</th><td><a href="#5.4">XML Schema Validation</a></td></tr>
+ <tr><th>5.5</th><td><a href="#5.5">64-bit Integer Type</a></td></tr>
+ <tr><th>5.6</th><td><a href="#5.6">Parser Reuse</a></td></tr>
+ <tr><th>5.7</th><td><a href="#5.7">Support for Polymorphism</a></td></tr>
+ <tr><th>5.8</th><td><a href="#5.8">Custom Allocators</a></td></tr>
+ <tr><th>5.9</th><td><a href="#5.9">A Minimal Example</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>6</th><td><a href="#6">Built-In XML Schema Type Parsers</a>
+ <table class="toc">
+ <tr><th>6.1</th><td><a href="#6.1"><code>QName</code> Parser</a></td></tr>
+ <tr><th>6.2</th><td><a href="#6.2"><code>NMTOKENS</code> and <code>IDREFS</code> Parsers</a></td></tr>
+ <tr><th>6.3</th><td><a href="#6.3"><code>base64Binary</code> and <code>hexBinary</code> Parsers</a></td></tr>
+ <tr><th>6.4</th><td><a href="#6.4">Time Zone Representation</a></td></tr>
+ <tr><th>6.5</th><td><a href="#6.5"><code>date</code> Parser</a></td></tr>
+ <tr><th>6.6</th><td><a href="#6.6"><code>dateTime</code> Parser</a></td></tr>
+ <tr><th>6.7</th><td><a href="#6.7"><code>duration</code> Parser</a></td></tr>
+ <tr><th>6.8</th><td><a href="#6.8"><code>gDay</code> Parser</a></td></tr>
+ <tr><th>6.9</th><td><a href="#6.9"><code>gMonth</code> Parser</a></td></tr>
+ <tr><th>6.10</th><td><a href="#6.10"><code>gMonthDay</code> Parser</a></td></tr>
+ <tr><th>6.11</th><td><a href="#6.11"><code>gYear</code> Parser</a></td></tr>
+ <tr><th>6.12</th><td><a href="#6.12"><code>gYearMonth</code> Parser</a></td></tr>
+ <tr><th>6.13</th><td><a href="#6.13"><code>time</code> Parser</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>7</th><td><a href="#7">Document Parser and Error Handling</a>
+ <table class="toc">
+ <tr><th>7.1</th><td><a href="#7.1">Document Parser</a></td></tr>
+ <tr><th>7.2</th><td><a href="#7.2">Exceptions</a></td></tr>
+ <tr><th>7.3</th><td><a href="#7.3">Error Codes</a></td></tr>
+ <tr><th>7.4</th><td><a href="#7.4">Reusing Parsers after an Error</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th></th><td><a href="#A">Appendix A &mdash; Supported XML Schema Constructs</a></td>
+ </tr>
+
+ </table>
+ </div>
+
+ <h1><a name="0">Preface</a></h1>
+
+ <h2><a name="0.1">About This Document</a></h2>
+
+ <p>The goal of this document is to provide you with an
+ understanding of the C++/Parser programming model and allow you
+ to efficiently evaluate XSD/e against your project's technical
+ requirements. As such, this document is intended for embedded
+ C++ developers and software architects who are looking for an
+ embedded XML processing solution. Prior experience with XML
+ and C++ is required to understand this document. Basic
+ understanding of XML Schema is advantageous but not expected
+ or required.
+ </p>
+
+
+ <h2><a name="0.2">More Information</a></h2>
+
+ <p>Beyond this guide, you may also find the following sources of
+ information useful:</p>
+
+ <ul class="list">
+ <li><a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a></li>
+
+ <li>The <code>INSTALL</code> file in the XSD/e distribution provides
+ build instructions for various platforms.</li>
+
+ <li>The <code>examples/cxx/parser/</code> directory in the XSD/e
+ distribution contains a collection of examples and a README
+ file with an overview of each example.</li>
+
+ <li>The <a href="http://www.codesynthesis.com/mailman/listinfo/xsde-users">xsde-users</a>
+ mailing list is the place to ask technical questions about XSD/e and the
+ Embedded C++/Parser mapping. Furthermore, the
+ <a href="http://www.codesynthesis.com/pipermail/xsde-users/">archives</a>
+ may already have answers to some of your questions.</li>
+
+ </ul>
+
+ <!-- Introduction -->
+
+ <h1><a name="1">1 Introduction</a></h1>
+
+ <p>Welcome to CodeSynthesis XSD/e and the Embedded C++/Parser mapping.
+ XSD/e is a dependency-free W3C XML Schema to C++ compiler for mobile,
+ embedded, and light-weight applications. Embedded C++/Parser is an
+ XML Schema to C++ mapping that represents an XML vocabulary as a set
+ of parser skeletons which you can implement to perform XML processing
+ as required by your application logic.
+ </p>
+
+ <h2><a name="1.1">1.1 Mapping Overview</a></h2>
+
+ <p>The Embedded C++/Parser mapping provides event-driven, stream-oriented
+ XML parsing, XML Schema validation, and C++ data binding. It was
+ specifically designed and optimized for mobile and embedded
+ systems where hardware constraints require high efficiency and
+ economical use of resources. As a result, the generated
+ parsers are 2-10 times faster than general-purpose validating
+ XML parsers while at the same time maintaining extremely low static
+ and dynamic memory footprints. For example, a validating parser
+ executable can be as small as 120KB in size. The size can be
+ further reduced by disabling support for XML Schema validation.
+ </p>
+
+ <p>The generated code and the runtime library are also highly-portable
+ and, in their minimal configuration, can be used without STL, RTTI,
+ iostream, C++ exceptions, and C++ templates.</p>
+
+ <p>To speed up application development, the C++/Parser mapping
+ can be instructed to generate sample parser implementations
+ and a test driver which can then be filled with the application
+ logic code. The mapping also provides a wide range of
+ mechanisms for controlling and customizing the generated code.</p>
+
+ <p>The next chapter shows how to create a simple application
+ that uses the Embedded C++/Parser mapping to parse, validate,
+ and extract data from a simple XML instance document. The
+ following chapters describe the Embedded C++/Parser mapping
+ in more detail.</p>
+
+ <h2><a name="1.2">1.2 Benefits</a></h2>
+
+ <p>Traditional XML access APIs such as Document Object Model (DOM)
+ or Simple API for XML (SAX) as well as general-purpose XML Schema
+ validators have a number of drawbacks that make them less suitable
+ for creating mobile and embedded XML processing applications. These
+ drawbacks include:
+ </p>
+
+ <ul class="list">
+ <li>Text-based representation results in inefficient use of
+ resources.</li>
+
+ <li>Extra validation code that is not used by the application.</li>
+
+ <li>Generic representation of XML in terms of elements, attributes,
+ and text forces an application developer to write a substantial
+ amount of bridging code that identifies and transforms pieces
+ of information encoded in XML to a representation more suitable
+ for consumption by the application logic.</li>
+
+ <li>String-based flow control defers error detection to runtime.
+ It also reduces code readability and maintainability.</li>
+
+ <li>Lack of type safety because all information is represented
+ as text.</li>
+
+ <li>Resulting applications are hard to debug, change, and
+ maintain.</li>
+ </ul>
+
+ <p>In contrast, statically-typed, vocabulary-specific parser
+ skeletons produced by the Embedded C++/Parser mapping use
+ native data representations (for example, integers are passed as
+ integers, not as text) and include validation code only for
+ XML Schema constructs that are used in the application. This
+ results in efficient use of resources and compact object code.</p>
+
+ <p>Furthermore, the parser skeletons allow you to operate in your
+ domain terms instead of the generic elements, attributes, and
+ text. Static typing helps catch errors at compile-time rather
+ than at run-time. Automatic code generation frees you for more
+ interesting tasks (such as doing something useful with the
+ information stored in the XML documents) and minimizes the
+ effort needed to adapt your applications to changes in the
+ document structure. To summarize, the C++/Parser mapping has
+ the following key advantages over generic XML access APIs:</p>
+
+ <ul class="list">
+ <li><b>Ease of use.</b> The generated code hides all the complexity
+ associated with recreating the document structure, maintaining the
+ dispatch state, and converting the data from the text representation
+ to data types suitable for manipulation by the application logic.
+ Parser skeletons also provide a convenient mechanism for building
+ custom in-memory representations.</li>
+
+ <li><b>Natural representation.</b> The generated parser skeletons
+ implement parser callbacks as virtual functions with names
+ corresponding to elements and attributes in XML. As a result,
+ you process the XML data using your domain vocabulary instead
+ of generic elements, attributes, and text.
+ </li>
+
+ <li><b>Concise code.</b> With a separate parser skeleton for each
+ XML Schema type, the application implementation is
+ simpler and thus easier to read and understand.</li>
+
+ <li><b>Safety.</b> The XML data is delivered to parser callbacks as
+ statically typed objects. The parser callbacks themselves are virtual
+ functions. This helps catch programming errors at compile-time
+ rather than at runtime.</li>
+
+ <li><b>Maintainability.</b> Automatic code generation minimizes the
+ effort needed to adapt the application to changes in the
+ document structure. With static typing, the C++ compiler
+ can pin-point the places in the application code that need to be
+ changed.</li>
+
+ <li><b>Efficiency.</b> The generated parser skeletons use native
+ data representations and combine data extraction, validation,
+ and even dispatching in a single step. This makes them much
+ more efficient than traditional architectures with separate
+ stages for validation and data extraction/dispatch.</li>
+ </ul>
+
+
+ <!-- Hello World Example -->
+
+
+ <h1><a name="2">2 Hello World Example</a></h1>
+
+ <p>In this chapter we will examine how to parse a very simple XML
+ document using the XSD/e-generated C++/Parser skeletons.
+
+ All the code presented in this chapter is based on the <code>hello</code>
+ example which can be found in the <code>examples/cxx/parser/</code>
+ directory of the XSD/e distribution.</p>
+
+ <h2><a name="2.1">2.1 Writing XML Document and Schema</a></h2>
+
+ <p>First, we need to get an idea about the structure
+ of the XML documents we are going to process. Our
+ <code>hello.xml</code>, for example, could look like this:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;hello>
+
+ &lt;greeting>Hello&lt;/greeting>
+
+ &lt;name>sun&lt;/name>
+ &lt;name>moon&lt;/name>
+ &lt;name>world&lt;/name>
+
+&lt;/hello>
+ </pre>
+
+ <p>Then we can write a description of the above XML in the
+ XML Schema language and save it into <code>hello.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="hello">
+ &lt;xs:sequence>
+ &lt;xs:element name="greeting" type="xs:string"/>
+ &lt;xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="hello" type="hello"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Even if you are not familiar with the XML Schema language, it
+ should be easy to connect declarations in <code>hello.xsd</code>
+ to elements in <code>hello.xml</code>. The <code>hello</code> type
+ is defined as a sequence of the nested <code>greeting</code> and
+ <code>name</code> elements. Note that the term sequence in XML
+ Schema means that elements should appear in a particular order
+ as opposed to appearing multiple times. The <code>name</code>
+ element has its <code>maxOccurs</code> property set to
+ <code>unbounde</code> which means it can appear multiple times
+ in an XML document. Finally, the globally-defined <code>hello</code>
+ element prescribes the root element for our vocabulary. For an
+ easily-approachable introduction to XML Schema refer to
+ <a href="http://www.w3.org/TR/xmlschema-0/">XML Schema Part 0:
+ Primer</a>.</p>
+
+ <p>The above schema is a specification of our vocabulary; it tells
+ everybody what valid XML instances of our vocabulary should look
+ like. The next step is to compile this schema to generate C++ parser
+ skeletons.</p>
+
+ <h2><a name="2.2">2.2 Translating Schema to C++</a></h2>
+
+ <p>Now we are ready to translate our <code>hello.xsd</code> to C++ parser
+ skeletons. To do this we invoke the XSD/e compiler from a terminal
+ (UNIX) or a command prompt (Windows):
+ </p>
+
+ <pre class="terminal">
+$ xsde cxx-parser hello.xsd
+ </pre>
+
+ <p>The XSD/e compiler produces two C++ files: <code>hello-pskel.hxx</code>
+ and <code>hello-pskel.cxx</code>. The following code fragment is taken
+ from <code>hello-pskel.hxx</code>; it should give you an idea about what
+ gets generated:
+ </p>
+
+ <pre class="c++">
+class hello_pskel
+{
+public:
+ // Parser callbacks. Override them in your implementation.
+ //
+ virtual void
+ pre ();
+
+ virtual void
+ greeting (const std::string&amp;);
+
+ virtual void
+ name (const std::string&amp;);
+
+ virtual void
+ post_hello ();
+
+ // Parser construction API.
+ //
+ void
+ greeting_parser (xml_schema::string_pskel&amp;);
+
+ void
+ name_parser (xml_schema::string_pskel&amp;);
+
+ void
+ parsers (xml_schema::string_pskel&amp; /* greeting */,
+ xml_schema::string_pskel&amp; /* name */);
+
+private:
+ ...
+};
+ </pre>
+
+ <p>The first four member functions shown above are called parser
+ callbacks. You would normally override them in your implementation
+ of the parser to do something useful. Let's go through all of
+ them one by one.</p>
+
+ <p>The <code>pre()</code> function is an initialization callback. It is
+ called when a new element of type <code>hello</code> is about
+ to be parsed. You would normally use this function to allocate a new
+ instance of the resulting type or clear accumulators that are used
+ to gather information during parsing. The default implementation
+ of this function does nothing.</p>
+
+ <p>The <code>post_hello()</code> function is a finalization callback. Its
+ name is constructed by adding the parser skeleton name to the
+ <code>post_</code> prefix. The finalization callback is called when
+ parsing of the element is complete and the result, if any, should
+ be returned. Note that in our case the return type of
+ <code>post_hello()</code> is <code>void</code> which means there
+ is nothing to return. More on parser return types later.
+ </p>
+
+ <p>You may be wondering why the finalization callback is called
+ <code>post_hello()</code> instead of <code>post()</code> just
+ like <code>pre()</code>. The reason for this is that
+ finalization callbacks can have different return types and
+ result in function signature clashes across inheritance
+ hierarchies. To prevent this, the signatures of finalization
+ callbacks are made unique by adding the type name to their names.</p>
+
+ <p>The <code>greeting()</code> and <code>name()</code> functions are
+ called when the <code>greeting</code> and <code>name</code> elements
+ have been parsed, respectively. Their arguments are of type
+ <code>std::string</code> and contain the data extracted from XML.</p>
+
+ <p>The last three functions are for connecting parsers to each other.
+ For example, there is a predefined parser for built-in XML Schema type
+ <code>string</code> in the XSD/e runtime. We will be using
+ it to parse the contents of <code>greeting</code> and
+ <code>name</code> elements, as shown in the next section.</p>
+
+ <h2><a name="2.3">2.3 Implementing Application Logic</a></h2>
+
+ <p>At this point we have all the parts we need to do something useful
+ with the information stored in XML documents. The first step is
+ to implement the parser:
+ </p>
+
+ <pre class="c++">
+#include &lt;iostream>
+#include "hello-pskel.hxx"
+
+class hello_pimpl: public hello_pskel
+{
+public:
+ virtual void
+ greeting (const std::string&amp; g)
+ {
+ greeting_ = g;
+ }
+
+ virtual void
+ name (const std::string&amp; n)
+ {
+ std::cout &lt;&lt; greeting_ &lt;&lt; ", " &lt;&lt; n &lt;&lt; "!" &lt;&lt; std::endl;
+ }
+
+private:
+ std::string greeting_;
+};
+ </pre>
+
+ <p>We left both <code>pre()</code> and <code>post_hello()</code> with the
+ default implementations; we don't have anything to initialize or
+ return. The rest is pretty straightforward: we store the greeting
+ in a member variable and later, when parsing names, use it to
+ say hello.</p>
+
+ <p>An observant reader my ask what happens if the <code>name</code>
+ element comes before <code>greeting</code>? Don't we need to
+ make sure <code>greeting_</code> was initialized and report
+ an error otherwise? The answer is no, we don't have to do
+ any of this. The <code>hello_pskel</code> parser skeleton
+ performs validation of XML according to the schema from which
+ it was generated. As a result, it will check the order
+ of the <code>greeting</code> and <code>name</code> elements
+ and report an error if it is violated.</p>
+
+ <p>Now it is time to put this parser implementation to work:</p>
+
+ <pre class="c++">
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ // Construct the parser.
+ //
+ xml_schema::string_pimpl string_p;
+ hello_pimpl hello_p;
+
+ hello_p.greeting_parser (string_p);
+ hello_p.name_parser (string_p);
+
+ // Parse the XML instance.
+ //
+ xml_schema::document_pimpl doc_p (hello_p, "hello");
+
+ hello_p.pre ();
+ doc_p.parse (argv[1]);
+ hello_p.post_hello ();
+ }
+ catch (const xml_schema::parser_exception&amp; e)
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>The first part of this code snippet instantiates individual parsers
+ and assembles them into a complete vocabulary parser.
+ <code>xml_schema::string_pimpl</code> is an implementation of a parser
+ for built-in XML Schema type <code>string</code>. It is provided by
+ the XSD/e runtime along with parsers for other built-in types (for
+ more information on the built-in parsers see <a href="#6">Chapter 6,
+ "Built-In XML Schema Type Parsers"</a>). We use <code>string_pimpl</code>
+ to parse the <code>greeting</code> and <code>name</code> elements as
+ indicated by the calls to <code>greeting_parser()</code> and
+ <code>name_parser()</code>.
+ </p>
+
+ <p>Then we instantiate a document parser (<code>doc_p</code>). The
+ first argument to its constructor is the parser for
+ the root element (<code>hello_p</code> in our case). The
+ second argument is the root element name.
+ </p>
+
+ <p>The final piece is the calls to <code>pre()</code>, <code>parse()</code>,
+ and <code>post_hello()</code>. The call to <code>parse()</code>
+ perform the actual XML parsing while the calls to <code>pre()</code> and
+ <code>post_hello()</code> make sure that the parser for the root
+ element can perform proper initialization and cleanup.</p>
+
+ <p>While our parser implementation and test driver are pretty small and
+ easy to write by hand, for bigger XML vocabularies it can be a
+ substantial effort. To help with this task XSD/e can automatically
+ generate sample parser implementations and a test driver from your
+ schemas. You can request the generation of a sample implementation with
+ empty function bodies by specifying the <code>--generate-noop-impl</code>
+ option. Or you can generate a sample implementation that prints the
+ data store in XML by using the <code>--generate-print-impl</code>
+ option. To request the generation of a test driver you can use the
+ <code>--generate-test-driver</code> option. For more information
+ on these options refer to the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a>. The <code>'generated'</code> example
+ in the XSD/e distribution shows the sample implementation generation
+ feature in action.</p>
+
+
+ <h2><a name="2.4">2.4 Compiling and Running</a></h2>
+
+ <p>After saving all the parts from the previous section in
+ <code>driver.cxx</code>, we are ready to compile our first
+ application and run it on the test XML document. On UNIX
+ this can be done with the following commands:
+ </p>
+
+ <pre class="terminal">
+$ c++ -I.../libxsde -c driver.cxx hello-pskel.cxx
+$ c++ -o driver driver.o hello-pskel.o .../libxsde/xsde/libxsde.a
+$ ./driver hello.xml
+Hello, sun!
+Hello, moon!
+Hello, world!
+ </pre>
+
+ <p>Here <code>.../libxsde</code> represents the path to the
+ <code>libxsde</code> directory in the XSD/e distribution.
+ We can also test the error handling. To test XML well-formedness
+ checking, we can try to parse <code>hello-pskel.hxx</code>:</p>
+
+ <pre class="terminal">
+$ ./driver hello-pskel.hxx
+hello-pskel.hxx:1:0: not well-formed (invalid token)
+ </pre>
+
+ <p>We can also try to parse a valid XML but not from our
+ vocabulary, for example <code>hello.xsd</code>:</p>
+
+ <pre class="terminal">
+$ ./driver hello.xsd
+hello.xsd:2:57: unexpected element encountered
+ </pre>
+
+
+ <!-- Chapater 3 -->
+
+
+ <h1><a name="3">3 Parser Skeletons</a></h1>
+
+ <p>As we have seen in the previous chapter, the XSD/e compiler generates
+ a parser skeleton class for each type defined in XML Schema. In
+ this chapter we will take a closer look at different functions
+ that comprise a parser skeleton as well as the way to connect
+ our implementations of these parser skeletons to create a complete
+ parser.</p>
+
+ <p>In this and subsequent chapters we will use the following schema
+ that describes a collection of person records. We save it in
+ <code>people.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:simpleType name="gender">
+ &lt;xs:restriction base="xs:string">
+ &lt;xs:enumeration value="male"/>
+ &lt;xs:enumeration value="female"/>
+ &lt;/xs:restriction>
+ &lt;/xs:simpleType>
+
+ &lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;xs:element name="gender" type="gender"/>
+ &lt;xs:element name="age" type="xs:short"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:complexType name="people">
+ &lt;xs:sequence>
+ &lt;xs:element name="person" type="person" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="people" type="people"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>A sample XML instance to go along with this schema is saved
+ in <code>people.xml</code>:</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;people>
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+ <p>Compiling <code>people.xsd</code> with the XSD/e compiler results
+ in three parser skeletons being generated: <code>gender_pskel</code>,
+ <code>person_pskel</code>, and <code>people_pskel</code>. We are going
+ to examine and implement each of them in the subsequent sections.</p>
+
+ <h2><a name="3.1">3.1 Implementing the Gender Parser</a></h2>
+
+ <p>The generated <code>gender_pskel</code> parser skeleton looks like
+ this:</p>
+
+ <pre class="c++">
+class gender_pskel: public xml_schema::string_pskel
+{
+public:
+ gender_pskel (xml_schema::string_pskel* base_impl);
+
+ // Parser callbacks. Override them in your implementation.
+ //
+ virtual void
+ pre ();
+
+ virtual void
+ post_gender ();
+};
+ </pre>
+
+ <p>Notice that <code>gender_pskel</code> inherits from
+ <code>xml_schema::string_pskel</code> which is a parser skeleton
+ for built-in XML Schema type <code>string</code> and is
+ predefined in the XSD/e runtime library. This is an example
+ of the general rule that parser skeletons follow: if a type
+ in XML Schema inherits from another then there will be an
+ equivalent inheritance between the corresponding parser
+ skeleton classes. The <code>gender_pskel</code> class also
+ declares a constructor which expects a pointer to the base
+ parser skeleton. We will discuss the purpose of this
+ constructor shortly.</p>
+
+ <p>The <code>pre()</code> and <code>post_gender()</code> callbacks
+ should look familiar from the previous chapter. Let's now
+ implement the parser. Our implementation will simply print
+ the gender to <code>cout</code>:</p>
+
+
+ <pre class="c++">
+class gender_pimpl: public gender_pskel
+{
+public:
+ gender_pimpl ()
+ : gender_pskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ post_gender ()
+ {
+ std::string s = post_string ();
+ cout &lt;&lt; "gender: " &lt;&lt; s &lt;&lt; endl;
+ }
+
+private:
+ xml_schema::string_pimpl base_impl_;
+};
+ </pre>
+
+ <p>While the code is quite short, there is a lot going on. First,
+ notice that we define a member variable <code>base_impl_</code>
+ of type <code>xml_schema::string_pimpl</code> and then pass
+ it to the <code>gender_pskel</code>'s constructor. We have
+ encountered <code>xml_schema::string_pimpl</code> already; it is an
+ implementation of the <code>xml_schema::string_pskel</code> parser
+ skeleton for built-in XML Schema type <code>string</code>. By
+ passing <code>base_impl_</code> to the <code>gender_pskel</code>'s
+ constructor we provide an implementation for the part of the
+ parser skeleton that is inherited from <code>string_pskel</code>.</p>
+
+ <p>This is another common theme in the C++/Parser programming model:
+ reusing implementations of the base parsers in the derived ones.
+ In our case, <code>string_pimpl</code> will do all the dirty work
+ of extracting the data and we can just get it at the end with the
+ call to <code>post_string()</code>. For more information on parser
+ implementation reuse refer to <a href="#5.6">Section 5.6,
+ "Parser Reuse"</a>.</p>
+
+ <p>In case you are curious, here are the definitions for
+ <code>xml_schema::string_pskel</code> and
+ <code>xml_schema::string_pimpl</code>:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_pskel: public parser_simple_content
+ {
+ public:
+ virtual std::string
+ post_string () = 0;
+ };
+
+ class string_pimpl: public string_pskel
+ {
+ public:
+ virtual void
+ _pre ();
+
+ virtual void
+ _characters (const xml_schema::ro_string&amp;);
+
+ virtual std::string
+ post_string ();
+
+ protected:
+ std::string str_;
+ };
+}
+ </pre>
+
+ <p>There are three new pieces in this code that we haven't seen yet.
+ Those are the <code>parser_simple_content</code> class and
+ the <code>_pre()</code> and <code>_characters()</code> functions.
+ The <code>parser_simple_content</code> class is defined in the XSD/e
+ runtime and is a base class for all parser skeletons that conform
+ to the simple content model in XML Schema. Types with the
+ simple content model cannot have nested elements&mdash;only text
+ and attributes. There is also the <code>parser_complex_content</code>
+ class which corresponds to the complex content mode (types with
+ nested elements, for example, <code>person</code> from
+ <code>people.xsd</code>).</p>
+
+ <p>The <code>_pre()</code> function is a parser callback. Remember we
+ talked about the <code>pre()</code> and <code>post_*()</code> callbacks
+ in the previous chapter? There are actually two more callbacks
+ with similar roles: <code>_pre()</code> and <code>_post ()</code>.
+ As a result, each parser skeleton has four special callbacks:</p>
+
+ <pre class="c++">
+ virtual void
+ pre ();
+
+ virtual void
+ _pre ();
+
+ virtual void
+ _post ();
+
+ virtual void
+ post_name ();
+ </pre>
+
+ <p><code>pre()</code> and <code>_pre()</code> are initialization
+ callbacks. They get called in that order before a new instance of the type
+ is about to be parsed. The difference between <code>pre()</code> and
+ <code>_pre()</code> is conventional: <code>pre()</code> can
+ be completely overridden by a derived parser. The derived
+ parser can also override <code>_pre()</code> but has to always call
+ the original version. This allows you to partition initialization
+ into customizable and required parts.</p>
+
+ <p>Similarly, <code>_post()</code> and <code>post_name()</code> are
+ finalization callbacks with exactly the same semantics:
+ <code>post_name()</code> can be completely overridden by the derived
+ parser while the original <code>_post()</code> should always be called.
+ </p>
+
+ <p>The final bit we need to discuss in this section is the
+ <code>_characters()</code> function. As you might have guessed, it
+ is also a callback. A low-level one that delivers raw character content
+ for the type being parsed. You will seldom need to use this callback
+ directly. Using implementations for the built-in parsers provided by
+ the XSD/e runtime is usually a simpler and more convenient
+ alternative.</p>
+
+ <p>At this point you might be wondering why some <code>post_*()</code>
+ callbacks, for example <code>post_string()</code>, return some data
+ while others, for example <code>post_gender()</code>, have
+ <code>void</code> as a return type. This is a valid concern
+ and it will be addressed in the next chapter.</p>
+
+ <h2><a name="3.2">3.2 Implementing the Person Parser</a></h2>
+
+ <p>The generated <code>person_pskel</code> parser skeleton looks like
+ this:</p>
+
+ <pre class="c++">
+class person_pskel: public xml_schema::parser_complex_content
+{
+public:
+ // Parser callbacks. Override them in your implementation.
+ //
+ virtual void
+ pre ();
+
+ virtual void
+ first_name (const std::string&amp;);
+
+ virtual void
+ last_name (const std::string&amp;);
+
+ virtual void
+ gender ();
+
+ virtual void
+ age (short);
+
+ virtual void
+ post_person ();
+
+ // Parser construction API.
+ //
+ void
+ first_name_parser (xml_schema::string_pskel&amp;);
+
+ void
+ last_name_parser (xml_schema::string_pskel&amp;);
+
+ void
+ gender_parser (gender_pskel&amp;);
+
+ void
+ age_parser (xml_schema::short_pskel&amp;);
+
+ void
+ parsers (xml_schema::string_pskel&amp; /* first-name */,
+ xml_schema::string_pskel&amp; /* last-name */,
+ gender_pskel&amp; /* gender */,
+ xml_schema::short_pskel&amp; /* age */);
+};
+ </pre>
+
+
+ <p>As you can see, we have a parser callback for each of the nested
+ elements found in the <code>person</code> XML Schema type.
+ The implementation of this parser is straightforward:</p>
+
+ <pre class="c++">
+class person_pimpl: public person_pskel
+{
+public:
+ virtual void
+ first_name (const std::string&amp; n)
+ {
+ cout &lt;&lt; "first: " &lt;&lt; f &lt;&lt; endl;
+ }
+
+ virtual void
+ last_name (const std::string&amp; l)
+ {
+ cout &lt;&lt; "last: " &lt;&lt; l &lt;&lt; endl;
+ }
+
+ virtual void
+ age (short a)
+ {
+ cout &lt;&lt; "age: " &lt;&lt; a &lt;&lt; endl;
+ }
+};
+ </pre>
+
+ <p>Notice that we didn't override the <code>gender()</code> callback
+ because all the printing is done by <code>gender_pimpl</code>.</p>
+
+ <h2><a name="3.3">3.3 Implementing the People Parser</a></h2>
+
+ <p>The generated <code>people_pskel</code> parser skeleton looks like
+ this:</p>
+
+ <pre class="c++">
+class people_pskel: public xml_schema::parser_complex_content
+{
+public:
+ // Parser callbacks. Override them in your implementation.
+ //
+ virtual void
+ pre ();
+
+ virtual void
+ person ();
+
+ virtual void
+ post_people ();
+
+ // Parser construction API.
+ //
+ void
+ person_parser (person_pskel&amp;);
+
+ void
+ parsers (person_pskel&amp; /* person */);
+};
+ </pre>
+
+ <p>The <code>person()</code> callback will be called after parsing each
+ <code>person</code> element. While <code>person_pimpl</code> does
+ all the printing, one useful thing we can do in this callback is to
+ print an extra newline after each person record so that our
+ output is more readable:</p>
+
+ <pre class="c++">
+class people_pimpl: public people_pskel
+{
+public:
+ virtual void
+ person ()
+ {
+ cout &lt;&lt; endl;
+ }
+};
+ </pre>
+
+ <p>Now it is time to put everything together.</p>
+
+
+ <h2><a name="3.4">3.4 Connecting the Parsers Together</a></h2>
+
+ <p>At this point we have all the individual parsers implemented
+ and can proceed to assemble them into a complete parser
+ for our XML vocabulary. The first step is to instantiate
+ all the individual parsers that we will need:</p>
+
+ <pre class="c++">
+xml_schema::short_pimpl short_p;
+xml_schema::string_pimpl string_p;
+
+gender_pimpl gender_p;
+person_pimpl person_p;
+people_pimpl people_p;
+ </pre>
+
+ <p>Notice that our schema uses two built-in XML Schema types:
+ <code>string</code> for the <code>first-name</code> and
+ <code>last-name</code> elements as well as <code>short</code>
+ for <code>age</code>. We will use predefined parsers that
+ come with the XSD/e runtime to handle these types. The next
+ step is to connect all the individual parsers. We do this
+ with the help of functions defined in the parser
+ skeletons and marked with the "Parser Construction API"
+ comment. One way to do it is to connect each individual
+ parser by calling the <code>*_parser()</code> functions:</p>
+
+ <pre class="c++">
+person_p.first_name_parser (string_p);
+person_p.last_name_parser (string_p);
+person_p.gender_parser (gender_p);
+person_p.age_parser (short_p);
+
+people_p.person_parser (person_p);
+ </pre>
+
+ <p>You might be wondering what happens if you do not provide
+ a parser by not calling one of the <code>*_parser()</code> functions.
+ In that case the corresponding XML content will be skipped,
+ including validation. This is an efficient way to ignore parts
+ of the document that you are not interested in.</p>
+
+
+ <p>An alternative, shorter, way to connect the parsers is by using
+ the <code>parsers()</code> functions which connects all the parsers
+ for a given type at once:</p>
+
+ <pre class="c++">
+person_p.parsers (string_p, string_p, gender_p, short_p);
+people_p.parsers (person_p);
+ </pre>
+
+ <p>The following figure illustrates the resulting connections. Notice
+ the correspondence between return types of the <code>post_*()</code>
+ functions and argument types of element callbacks that are connected
+ by the arrows.</p>
+
+ <!-- align=center is needed for html2ps -->
+ <div class="img" align="center"><img src="figure-1.png"/></div>
+
+ <p>The last step is the construction of the document parser and
+ invocation of the complete parser on our sample XML instance:</p>
+
+ <pre class="c++">
+xml_schema::document_pimpl doc_p (people_p, "people");
+
+people_p.pre ();
+doc_p.parse ("people.xml");
+people_p.post_people ();
+ </pre>
+
+ <p>Let's consider <code>xml_schema::document_pimpl</code> in
+ more detail. While the exact definition of this class
+ varies depending on the mapping configuration, here is
+ the part relevant to our example:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class document_pimpl
+ {
+ public:
+ document_pimpl (xml_schema::parser_base&amp;,
+ const std::string&amp; root_element_name);
+
+ document_pimpl (xml_schema::parser_base&amp;,
+ const std::string&amp; root_element_namespace,
+ const std::string&amp; root_element_name);
+
+ void
+ parse (const std::string&amp; file);
+
+ void
+ parse (std::istream&amp;);
+
+ void
+ parse (const void* data, size_t size, bool last);
+ };
+}
+ </pre>
+
+ <p><code>xml_schema::document_pimpl</code> is a root parser for
+ the vocabulary. The first argument to its constructors is the
+ parser for the type of the root element (<code>people_pimpl</code>
+ in our case). Because a type parser is only concerned with
+ the element's content and not with the element's name, we need
+ to specify the root element name somewhere. That's
+ what is passed as the second and third arguments to the
+ <code>document_pimpl</code>'s constructors.</p>
+
+ <p>There are also three overloaded <code>parse()</code> function
+ defined in the <code>document_pimpl</code> class. The first version
+ parses a local file identified by a name. The second version
+ reads the data from an input stream. The last version allows
+ you to parse the data directly from a buffer, one chunk at a
+ time. You can call this function multiple times with the final
+ call having the <code>last</code> argument set to true. For more
+ information on the <code>xml_schema::document_pimpl</code> class
+ refer to <a href="#7">Chapter 7, "Document Parser and Error
+ Handling"</a>.</p>
+
+ <p>Let's now consider a step-by-step list of actions that happen
+ as we parse through <code>people.xml</code>. The content of
+ <code>people.xml</code> is repeated below for convenience.</p>
+
+ <pre class="xml">
+&lt;?xml version="1.0"?>
+&lt;people>
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+
+ <ol class="steps">
+ <li><code>people_p.pre()</code> is called from
+ <code>main()</code>. We did not provide any implementation
+ for this callback so this call is a no-op.</li>
+
+ <li><code>doc_p.parse("people.xml")</code> is called from
+ <code>main()</code>. The parser opens the file and starts
+ parsing its content.</li>
+
+ <li>The parser encounters the root element. <code>doc_p</code>
+ verifies that the root element is correct and calls
+ <code>_pre()</code> on <code>people_p</code> which is also
+ a no-op. Parsing is now delegated to <code>people_p</code>.</li>
+
+ <li>The parser encounters the <code>person</code> element.
+ <code>people_p</code> determines that <code>person_p</code>
+ is responsible for parsing this element. <code>pre()</code>
+ and <code>_pre()</code> callbacks are called on <code>person_p</code>.
+ Parsing is now delegated to <code>person_p</code>.</li>
+
+ <li>The parser encounters the <code>first-name</code> element.
+ <code>person_p</code> determines that <code>string_p</code>
+ is responsible for parsing this element. <code>pre()</code>
+ and <code>_pre()</code> callbacks are called on <code>string_p</code>.
+ Parsing is now delegated to <code>string_p</code>.</li>
+
+ <li>The parser encounters character content consisting of
+ <code>"John"</code>. The <code>_characters()</code> callback is
+ called on <code>string_p</code>.</li>
+
+ <li>The parser encounters the end of <code>first-name</code>
+ element. The <code>_post()</code> and <code>post_string()</code>
+ callbacks are called on <code>string_p</code>. The
+ <code>first_name()</code> callback is called on <code>person_p</code>
+ with the return value of <code>post_string()</code>. The
+ <code>first_name()</code> implementation prints
+ <code>"first: John"</code> to <code>cout</code>.
+ Parsing is now returned to <code>person_p</code>.</li>
+
+ <li>Steps analogous to 5-7 are performed for the <code>last-name</code>,
+ <code>gender</code>, and <code>age</code> elements.</li>
+
+ <li>The parser encounters the end of <code>person</code>
+ element. The <code>_post()</code> and <code>post_person()</code>
+ callbacks are called on <code>person_p</code>. The
+ <code>person()</code> callback is called on <code>people_p</code>.
+ The <code>person()</code> implementation prints a new line
+ to <code>cout</code>. Parsing is now returned to
+ <code>people_p</code>.</li>
+
+ <li>Steps 4-9 are performed for the second <code>person</code>
+ element.</li>
+
+ <li>The parser encounters the end of <code>people</code>
+ element. The <code>_post()</code> callback is called on
+ <code>people_p</code>. The <code>doc_p.parse("people.xml")</code>
+ call returns to <code>main()</code>.</li>
+
+ <li><code>people_p.post_people()</code> is called from
+ <code>main()</code> which is a no-op.</li>
+
+ </ol>
+
+
+ <!-- Chpater 4 -->
+
+
+ <h1><a name="4">4 Type Maps</a></h1>
+
+ <p>There are many useful things you can do inside parser callbacks as they
+ are right now. There are, however, times when you want to propagate
+ some information from one parser to another or to the caller of the
+ parser. One common task that would greatly benefit from such a
+ possibility is building a tree-like in-memory object model of the
+ data stored in XML. During execution, each individual sub-parser
+ would create a sub-tree and return it to its <em>parent</em> parser
+ which can then incorporate this sub-tree into the whole tree.</p>
+
+ <p>In this chapter we will discuss the mechanisms offered by the
+ C++/Parser mapping for returning information from individual
+ parsers and see how to use them to build an object model
+ of our people vocabulary.</p>
+
+ <h2><a name="4.1">4.1 Object Model</a></h2>
+
+ <p>An object model for our person record example could
+ look like this (saved in the <code>people.hxx</code> file):</p>
+
+ <pre class="c++">
+#include &lt;string>
+#include &lt;vector>
+
+enum gender
+{
+ male,
+ female
+};
+
+class person
+{
+public:
+ person (const std::string&amp; first,
+ const std::string&amp; last,
+ ::gender gender,
+ short age)
+ : first_ (first), last_ (last),
+ gender_ (gender), age_ (age)
+ {
+ }
+
+ const std::string&amp;
+ first () const
+ {
+ return first_;
+ }
+
+ const std::string&amp;
+ last () const
+ {
+ return last_;
+ }
+
+ ::gender
+ gender () const
+ {
+ return gender_;
+ }
+
+ short
+ age () const
+ {
+ return age_;
+ }
+
+private:
+ std::string first_;
+ std::string last_;
+ ::gender gender_;
+ short age_;
+};
+
+typedef std::vector&lt;person> people;
+ </pre>
+
+ <p>While it is clear which parser is responsible for which part of
+ the object model, it is not exactly clear how, for
+ example, <code>gender_pimpl</code> will deliver <code>gender</code>
+ to <code>person_pimpl</code>. You might have noticed that
+ <code>string_pimpl</code> manages to deliver its value to the
+ <code>first_name()</code> callback of <code>person_pimpl</code>. Let's
+ see how we can utilize the same mechanism to propagate our
+ own data.</p>
+
+ <p>There is a way to tell the XSD/e compiler that you want to
+ exchange data between parsers. More precisely, for each
+ type defined in XML Schema, you can tell the compiler two things.
+ First, the return type of the <code>post_*()</code> callback
+ in the parser skeleton generated for this type. And, second,
+ the argument type for callbacks corresponding to elements and
+ attributes of this type. For example, for XML Schema type
+ <code>gender</code> we can specify the return type for
+ <code>post_gender()</code> in the <code>gender_pskel</code>
+ skeleton and the argument type for the <code>gender()</code> callback
+ in the <code>person_pskel</code> skeleton. As you might have guessed,
+ the generated code will then pass the return value from the
+ <code>post_*()</code> callback as an argument to the element or
+ attribute callback.</p>
+
+ <p>The way to tell the XSD/e compiler about these XML Schema to
+ C++ mappings is with type map files. Here is a simple type
+ map for the <code>gender</code> type from the previous paragraph.</p>
+
+ <pre class="type-map">
+include "people.hxx";
+gender ::gender ::gender;
+ </pre>
+
+ <p>The first line indicates that the generated code must include
+ <code>people.hxx</code> in order to get the definition for the
+ <code>gender</code> type. The second line specifies that both
+ argument and return types for the <code>gender</code>
+ XML Schema type should be the <code>::gender</code> C++ enum
+ (we use fully-qualified C++ names to avoid name clashes).
+ The next section will describe the type map format in detail.
+ We save this type map in <code>people.map</code> and
+ then translate our schemas with the <code>--type-map</code>
+ option to let the XSD/e compiler know about our type map:</p>
+
+ <pre class="terminal">
+$ xsde cxx-parser --type-map people.map people.xsd
+ </pre>
+
+ <p>If we now look at the generated <code>people-pskel.hxx</code>,
+ we will see the following changes in the <code>gender_pskel</code> and
+ <code>person_pskel</code> skeletons:</p>
+
+ <pre class="c++">
+#include "people.hxx"
+
+class gender_pskel: public xml_schema::string_pskel
+{
+ virtual ::gender
+ post_gender () = 0;
+
+ ...
+};
+
+class person_pskel: public xml_schema::parser_complex_content
+{
+ virtual void
+ gender (::gender);
+
+ ...
+};
+ </pre>
+
+ <p>Notice that <code>#include "people.hxx"</code> was added to
+ the generated header file from the type map to provide the
+ definition for the <code>gender</code> enum.</p>
+
+ <h2><a name="4.2">4.2 Type Map File Format</a></h2>
+
+ <p>Type map files are used to define a mapping between XML Schema
+ and C++ types. The compiler uses this information
+ to determine return types of <code>post_*()</code>
+ callbacks in parser skeletons corresponding to XML Schema
+ types as well as argument types for callbacks corresponding
+ to elements and attributes of these types.</p>
+
+ <p>The compiler has a set of predefined mapping rules that map the
+ built-in XML Schema types to suitable C++ types (discussed
+ below) and all other types to <code>void</code>.
+ By providing your own type maps you can override these predefined
+ rules. The format of the type map file is presented below:
+ </p>
+
+ <pre class="type-map">
+namespace &lt;schema-namespace> [&lt;cxx-namespace>]
+{
+ (include &lt;file-name>;)*
+ ([type] &lt;schema-type> &lt;cxx-ret-type> [&lt;cxx-arg-type>];)*
+}
+ </pre>
+
+ <p>Both <code><i>&lt;schema-namespace></i></code> and
+ <code><i>&lt;schema-type></i></code> are regex patterns while
+ <code><i>&lt;cxx-namespace></i></code>,
+ <code><i>&lt;cxx-ret-type></i></code>, and
+ <code><i>&lt;cxx-arg-type></i></code> are regex pattern
+ substitutions. All names can be optionally enclosed in
+ <code>"&nbsp;"</code>, for example, to include white-spaces.</p>
+
+ <p><code><i>&lt;schema-namespace></i></code> determines XML
+ Schema namespace. Optional <code><i>&lt;cxx-namespace></i></code>
+ is prefixed to every C++ type name in this namespace declaration.
+ <code><i>&lt;cxx-ret-type></i></code> is a C++ type name that is
+ used as a return type for the <code>post_*()</code> callback.
+ Optional <code><i>&lt;cxx-arg-type></i></code> is an argument
+ type for callbacks corresponding to elements and attributes
+ of this type. If <code><i>&lt;cxx-arg-type></i></code> is not
+ specified, it defaults to <code><i>&lt;cxx-ret-type></i></code>
+ if <code><i>&lt;cxx-ret-type></i></code> ends with <code>*</code> or
+ <code>&amp;</code> (that is, it is a pointer or a reference) and
+ <code>const&nbsp;<i>&lt;cxx-ret-type></i>&amp;</code>
+ otherwise.
+ <code><i>&lt;file-name></i></code> is a file name either in the
+ <code>"&nbsp;"</code> or <code>&lt;&nbsp;></code> format
+ and is added with the <code>#include</code> directive to
+ the generated code.</p>
+
+ <p>The <code><b>#</b></code> character starts a comment that ends
+ with a new line or end of file. To specify a name that contains
+ <code><b>#</b></code> enclose it in <code><b>"&nbsp;"</b></code>.
+ For example:</p>
+
+ <pre>
+namespace http://www.example.com/xmlns/my my
+{
+ include "my.hxx";
+
+ # Pass apples by value.
+ #
+ apple apple;
+
+ # Pass oranges as pointers.
+ #
+ orange orange_t*;
+}
+ </pre>
+
+ <p>In the example above, for the
+ <code>http://www.example.com/xmlns/my#orange</code>
+ XML Schema type, the <code>my::orange_t*</code> C++ type will
+ be used as both return and argument types.</p>
+
+ <p>Several namespace declarations can be specified in a single
+ file. The namespace declaration can also be completely
+ omitted to map types in a schema without a namespace. For
+ instance:</p>
+
+ <pre class="type-map">
+include "my.hxx";
+apple apple;
+
+namespace http://www.example.com/xmlns/my
+{
+ orange "const orange_t*";
+}
+ </pre>
+
+ <p>The compiler has a number of predefined mapping rules for
+ the built-in XML Schema types which can be presented as the
+ following map files:</p>
+
+ <pre class="type-map">
+namespace http://www.w3.org/2001/XMLSchema
+{
+ boolean bool bool;
+
+ byte "signed char" "signed char";
+ unsignedByte "unsigned char" "unsigned char";
+
+ short short short;
+ unsignedShort "unsigned short" "unsigned short";
+
+ int int int;
+ unsignedInt "unsigned int" "unsigned int";
+
+ long "long long" "long long";
+ unsignedLong "unsigned long long" "unsigned long long";
+
+ integer long long;
+
+ negativeInteger long long;
+ nonPositiveInteger long long;
+
+ positiveInteger "unsigned long" "unsigned long";
+ nonNegativeInteger "unsigned long" "unsigned long";
+
+ float float float;
+ double double double;
+ decimal double double;
+
+ NMTOKENS xml_schema::string_sequence*;
+ IDREFS xml_schema::string_sequence*;
+
+ base64Binary xml_schema::buffer*;
+ hexBinary xml_schema::buffer*;
+
+ date xml_schema::date;
+ dateTime xml_schema::date_time;
+ duration xml_schema::duration;
+ gDay xml_schema::gday;
+ gMonth xml_schema::gmonth;
+ gMonthDay xml_schema::gmonth_day;
+ gYear xml_schema::gyear;
+ gYearMonth xml_schema::gyear_month;
+ time xml_schema::time;
+}
+ </pre>
+
+ <p>If STL is enabled (<a href="#5.1">Section 5.1, "Standard Template
+ Library"</a>), the following mapping is used for the string-based
+ XML Schema built-in types:</p>
+
+ <pre class="type-map">
+namespace http://www.w3.org/2001/XMLSchema
+{
+ include &lt;string>;
+
+ anySimpleType std::string;
+
+ string std::string;
+ normalizedString std::string;
+ token std::string;
+ Name std::string;
+ NMTOKEN std::string;
+ NCName std::string;
+ ID std::string;
+ IDREF std::string;
+ language std::string;
+ anyURI std::string;
+
+ QName xml_schema::qname;
+}
+ </pre>
+
+ <p>Otherwise, a C string-based mapping is used:</p>
+
+ <pre class="type-map">
+namespace http://www.w3.org/2001/XMLSchema
+{
+ anySimpleType char*;
+
+ string char*;
+ normalizedString char*;
+ token char*;
+ Name char*;
+ NMTOKEN char*;
+ NCName char*;
+ ID char*;
+ IDREF char*;
+ language char*;
+ anyURI char*;
+
+ QName xml_schema::qname*;
+}
+ </pre>
+
+ <p>For more information about the mapping of the built-in XML Schema types
+ to C++ types refer to <a href="#6">Chapter 6, "Built-In XML Schema Type
+ Parsers"</a>. The last predefined rule maps anything that wasn't
+ mapped by previous rules to <code>void</code>:</p>
+
+ <pre class="type-map">
+namespace .*
+{
+ .* void void;
+}
+ </pre>
+
+
+ <p>When you provide your own type maps with the
+ <code>--type-map</code> option, they are evaluated first. This
+ allows you to selectively override any
+ of the predefined rules. Note also that if you change the mapping
+ of a built-in XML Schema type then it becomes your responsibility
+ to provide the corresponding parser skeleton and implementation
+ in the <code>xml_schema</code> namespace. You can include the
+ custom definitions into the generated header file using the
+ <code>--hxx-prologue-*</code> options.</p>
+
+ <h2><a name="4.3">4.3 Parser Implementations</a></h2>
+
+ <p>With the knowledge from the previous section, we can proceed
+ with creating a type map that maps types in the <code>people.xsd</code>
+ schema to our object model classes in
+ <code>people.hxx</code>. In fact, we already have the beginning
+ of our type map file in <code>people.map</code>. Let's extend
+ it with the rest of the types:</p>
+
+ <pre class="type-map">
+include "people.hxx";
+
+gender ::gender ::gender;
+person ::person;
+people ::people;
+ </pre>
+
+ <p>A few things to note about this type map. We did not
+ provide the argument types for <code>person</code> and
+ <code>people</code> because the default constant reference is
+ exactly what we need. We also did not provide any mappings
+ for built-in XML Schema types <code>string</code> and
+ <code>short</code> because they are handled by the predefined
+ rules and we are happy with the result. Note also that
+ all C++ types are fully qualified. This is done to avoid
+ potential name conflicts in the generated code. Now we can
+ recompile our schema and move on to implementing the parsers:</p>
+
+ <pre class="terminal">
+$ xsde cxx-parser --type-map people.map people.xsd
+ </pre>
+
+ <p>Here is the implementation of our three parsers in full. One
+ way to save typing when implementing your own parsers is
+ to open the generated code and copy the signatures of parser
+ callbacks into your code. Or you could always auto generate the
+ sample implementations and fill them with your code.</p>
+
+ <pre class="c++">
+#include "people-pskel.hxx"
+
+class gender_pimpl: public gender_pskel
+{
+public:
+ gender_pimpl ()
+ : gender_pskel (&amp;base_impl_)
+ {
+ }
+
+ virtual ::gender
+ post_gender ()
+ {
+ return post_string () == "male" ? male : female;
+ }
+
+private:
+ xml_schema::string_pimpl base_impl_;
+};
+
+class person_pimpl: public person_pskel
+{
+public:
+ virtual void
+ first_name (const std::string&amp; f)
+ {
+ first_ = f;
+ }
+
+ virtual void
+ last_name (const std::string&amp; l)
+ {
+ last_ = l;
+ }
+
+ virtual void
+ gender (::gender g)
+ {
+ gender_ = g;
+ }
+
+ virtual void
+ age (short a)
+ {
+ age_ = a;
+ }
+
+ virtual ::person
+ post_person ()
+ {
+ return ::person (first_, last_, gender_, age_);
+ }
+
+private:
+ std::string first_;
+ std::string last_;
+ ::gender gender_;
+ short age_;
+};
+
+class people_pimpl: public people_pskel
+{
+public:
+ virtual void
+ person (const ::person&amp; p)
+ {
+ people_.push_back (p);
+ }
+
+ virtual ::people
+ post_people ()
+ {
+ ::people r;
+ r.swap (people_);
+ return r;
+ }
+
+private:
+ ::people people_;
+};
+ </pre>
+
+ <p>This code fragment should look familiar by now. Just note that
+ all the <code>post_*()</code> callbacks now have return types instead
+ of <code>void</code>. Here is the implementation of the test
+ driver for this example:</p>
+
+ <pre class="c++">
+#include &lt;iostream>
+
+using namespace std;
+
+int
+main (int argc, char* argv[])
+{
+ // Construct the parser.
+ //
+ xml_schema::short_pimpl short_p;
+ xml_schema::string_pimpl string_p;
+
+ gender_pimpl gender_p;
+ person_pimpl person_p;
+ people_pimpl people_p;
+
+ person_p.parsers (string_p, string_p, gender_p, short_p);
+ people_p.parsers (person_p);
+
+ // Parse the document to obtain the object model.
+ //
+ xml_schema::document_pimpl doc_p (people_p, "people");
+
+ people_p.pre ();
+ doc_p.parse (argv[1]);
+ people ppl = people_p.post_people ();
+
+ // Print the object model.
+ //
+ for (people::iterator i (ppl.begin ()); i != ppl.end (); ++i)
+ {
+ cout &lt;&lt; "first: " &lt;&lt; i->first () &lt;&lt; endl
+ &lt;&lt; "last: " &lt;&lt; i->last () &lt;&lt; endl
+ &lt;&lt; "gender: " &lt;&lt; (i->gender () == male ? "male" : "female") &lt;&lt; endl
+ &lt;&lt; "age: " &lt;&lt; i->age () &lt;&lt; endl
+ &lt;&lt; endl;
+ }
+}
+ </pre>
+
+ <p>The parser creation and assembly part is exactly the same as in
+ the previous chapter. The parsing part is a bit different:
+ <code>post_people()</code> now has a return value which is the
+ complete object model. We store it in the
+ <code>ppl</code> variable. The last bit of the code simply iterates
+ over the <code>people</code> vector and prints the information
+ for each person. We save the last two code fragments to
+ <code>driver.cxx</code> and proceed to compile and test
+ our new application:</p>
+
+
+ <pre class="terminal">
+$ c++ -I.../libxsde -c driver.cxx people-pskel.cxx
+$ c++ -o driver driver.o people-pskel.o .../libxsde/xsde/libxsde.a
+$ ./driver people.xml
+first: John
+last: Doe
+gender: male
+age: 32
+
+first: Jane
+last: Doe
+gender: female
+age: 28
+ </pre>
+
+
+ <!-- Mapping Configuration -->
+
+
+ <h1><a name="5">5 Mapping Configuration</a></h1>
+
+ <p>The Embedded C++/Parser mapping has a number of configuration
+ parameters that determine the overall properties and behavior
+ of the generated code, such as the use of Standard Template
+ Library (STL), Input/Output Stream Library (iostream), C++
+ exceptions, XML Schema validation, 64-bit integer types, parser
+ implementation reuse styles, and support for XML Schema polymorphism.
+ Previous chapters assumed that the use of STL, iostream, C++
+ exceptions, and XML Schema validation were enabled.
+ This chapter will discuss the changes in the Embedded C++/Parser
+ programming model that result from the changes to these configuration
+ parameters. A complete example that uses the minimal mapping
+ configuration is presented at the end of this chapter.</p>
+
+ <p>In order to enable or disable a particular feature, the corresponding
+ configuration parameter should be set accordingly in the XSD/e runtime
+ library as well as specified during schema compilation with the XSD/e
+ command line options as described in the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a>.
+ </p>
+
+ <p>While the XML documents can use various encodings, the Embedded
+ C++/Parser mapping always delivers character data to the application
+ in the same encoding. The application encoding can either be UTF-8
+ (default) or ISO-8859-1. To select a particular encoding, configure
+ the XSD/e runtime library accordingly and pass the <code>--char-encoding</code>
+ option to the XSD/e compiler when translating your schemas.</p>
+
+ <p>When using ISO-8859-1 as the application encoding, XML documents
+ being parsed may contain characters with Unicode values greater
+ than 0xFF which are unrepresentable in the ISO-8859-1 encoding.
+ By default, in such situations parsing will terminate with
+ an error. However, you can suppress the error by providing a
+ replacement character that should be used instead of
+ unrepresentable characters, for example:</p>
+
+ <pre class="c++">
+xml_schema::iso8859_1::unrep_char ('?');
+ </pre>
+
+ <p>To revert to the default behavior, set the replacement character
+ to <code>'\0'</code>.</p>
+
+ <p>The Embedded C++/Parser mapping includes built-in support for XML
+ documents encoded in UTF-8, UTF-16, ISO-8859-1, and US-ASCII.
+ Other encodings can be supported by providing application-specific
+ decoder functions.</p>
+
+ <h2><a name="5.1">5.1 Standard Template Library</a></h2>
+
+ <p>To disable the use of STL you will need to configure the XSD/e
+ runtime without support for STL as well as pass the
+ <code>--no-stl</code> option to the XSD/e compiler when
+ translating your schemas. When STL is disabled, all string-based
+ XML Schema types are mapped to C-style <code>char*</code> instead
+ of <code>std::string</code>, as described in
+ <a href="#4.2">Section 4.2, "Type Map File Format"</a>. The
+ following code fragment shows changes in the
+ signatures of <code>first_name()</code> and <code>last_name()</code>
+ callbacks from the person record example.</p>
+
+ <pre class="c++">
+class person_pskel
+{
+public:
+ virtual void
+ first_name (char*);
+
+ virtual void
+ last_name (char*);
+
+ ...
+};
+ </pre>
+
+ <p>Note that it is your responsibility to eventually release the memory
+ associated with these strings using operator <code>delete[]</code>.
+ </p>
+
+ <h2><a name="5.2">5.2 Input/Output Stream Library</a></h2>
+
+ <p>To disable the use of iostream you will need to configure the
+ XSD/e runtime library without support for iostream as well as
+ pass the <code>--no-iostream</code> option to the XSD/e compiler
+ when translating your schemas. When iostream is disabled, the
+ following two <code>parse()</code> functions in the
+ <code>xml_schema::document_pimpl</code> class become unavailable:</p>
+
+ <pre class="c++">
+ void
+ parse (const std::string&amp; file);
+
+ void
+ parse (std::istream&amp;);
+ </pre>
+
+ <p>Leaving you with only one function in the form:</p>
+
+ <pre class="c++">
+ void
+ parse (const void* data, size_t size, bool last);
+ </pre>
+
+ <p>See <a href="#7.1">Section 7.1, "Document Parser"</a>
+ for more information on the semantics of these functions.</p>
+
+ <h2><a name="5.3">5.3 C++ Exceptions</a></h2>
+
+ <p>To disable the use of C++ exceptions, you will need to configure
+ the XSD/e runtime without support for exceptions as well as pass
+ the <code>--no-exceptions</code> option to the XSD/e compiler
+ when translating your schemas. When C++ exceptions are disabled,
+ the error conditions are indicated with error codes instead of
+ exceptions, as described in <a href="#7.3">Section 7.3,
+ "Error Codes"</a>.
+ </p>
+
+ <h2><a name="5.4">5.4 XML Schema Validation</a></h2>
+
+ <p>To disable support for XML Schema validation, you will need to
+ configure the XSD/e runtime accordingly as well as pass
+ the <code>--suppress-validation</code> option to the XSD/e compiler
+ when translating your schemas. Disabling XML Schema validation
+ allows to further increase the parsing performance and
+ reduce footprint in cases where XML instances are known to be
+ valid.
+ </p>
+
+ <h2><a name="5.5">5.5 64-bit Integer Type</a></h2>
+
+ <p>By default the 64-bit <code>long</code> and <code>unsignedLong</code>
+ XML Schema built-in types are mapped to the 64-bit <code>long long</code>
+ and <code>unsigned long long</code> fundamental C++ types. To
+ disable the use of these types in the mapping you will need to
+ configure the XSD/e runtime accordingly as well as pass
+ the <code>--no-long-long</code> option to the XSD/e compiler
+ when translating your schemas. When the use of 64-bit integral
+ C++ types is disabled the <code>long</code> and
+ <code>unsignedLong</code> XML Schema built-in types are mapped
+ to <code>long</code> and <code>unsigned long</code> fundamental
+ C++ types.</p>
+
+ <h2><a name="5.6">5.6 Parser Reuse</a></h2>
+
+ <p>When one type in XML Schema inherits from another, it is
+ often desirable to be able to reuse the parser implementation
+ corresponding to the base type in the parser implementation
+ corresponding to the derived type. XSD/e provides support
+ for two parser reuse styles: the so-called <em>mixin</em>
+ (generated when the <code>--reuse-style-mixin</code> option
+ is specified) and <em>tiein</em> (generated by default) styles.</p>
+
+ <p>The compiler can also be instructed not to generate any support
+ for parser reuse with the <code>--reuse-style-none</code> option.
+ This is mainly useful to further reduce the generated code size
+ when your vocabulary does not use inheritance or when you plan
+ to implement each parser from scratch. Note also that the
+ XSD/e runtime should be configured in accordance with the
+ parser reuse style used in the generated code. The remainder
+ of this section discusses the mixin and tiein parser reuse
+ styles in more detail.</p>
+
+
+ <p>To provide concrete examples for each reuse style we will use the
+ following schema fragment:</p>
+
+ <pre class="xml">
+&lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;xs:element name="age" type="xs:short"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+
+&lt;xs:complexType name="emplyee">
+ &lt;complexContent>
+ &lt;extension base="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="position" type="xs:string"/>
+ &lt;xs:element name="salary" type="xs:unsignedLong"/>
+ &lt;/xs:sequence>
+ &lt;/extension>
+ &lt;/complexContent>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The mixin parser reuse style uses the C++ mixin idiom that
+ relies on multiple and virtual inheritance. Because
+ virtual inheritance can result in a significant object
+ code size increase, this reuse style should be considered
+ when such an overhead is acceptable and/or the vocabulary
+ consists of only a handful of types. When the mixin reuse
+ style is used, the generated parser skeletons use virtual
+ inheritance, for example:</p>
+
+ <pre class="c++">
+class person_pskel: public virtual parser_complex_content
+{
+ ...
+};
+
+class employee_pskel: public virtual person_pskel
+{
+ ...
+};
+ </pre>
+
+
+ <p>When you implement the base parser you also need to use
+ virtual inheritance. The derived parser is implemented
+ by inheriting from both the derived parser skeleton and
+ the base parser implementation (that is, <em>mixing in</em>
+ the base parser implementation), for example:</p>
+
+ <pre class="c++">
+class person_pimpl: public virtual person_pskel
+{
+ ...
+};
+
+class employee_pimpl: public employee_pskel,
+ public person_pimpl
+{
+ ...
+};
+ </pre>
+
+
+ <p>The tiein parser reuse style uses delegation and normally
+ results in a significantly smaller object code while being
+ almost as convenient to use as the mixin style. When the
+ tiein reuse style is used, the generated derived parser
+ skeleton declares a constructor which allows you to specify
+ the implementation of the base parser:</p>
+
+ <pre class="c++">
+class person_pskel: public parser_complex_content
+{
+ ...
+};
+
+class employee_pskel: public person_pskel
+{
+public:
+ employee_pskel (person_pskel* base_impl)
+
+ ...
+};
+ </pre>
+
+ <p>If you pass the implementation of the base parser to this
+ constructor then the generated code will transparently
+ forward all the callbacks corresponding to the base parser
+ skeleton to this implementation. You can also pass
+ <code>0</code> to this constructor in which case you will
+ need to implement the derived parser from scratch. The
+ following example shows how we could implement the
+ <code>person</code> and <code>employee</code> parsers
+ using the tiein style:</p>
+
+ <pre class="c++">
+class person_pimpl: public person_pskel
+{
+ ...
+};
+
+class employee_pimpl: public employee_pskel
+{
+public:
+ employee_pimpl ()
+ : employee_pskel (&amp;base_impl_)
+ {
+ }
+
+ ...
+
+private:
+ person_pimpl base_impl_;
+};
+ </pre>
+
+ <p>Note that you cannot use the <em>tied in</em> base parser
+ instance (<code>base_impl_</code> in the above code) for
+ parsing anything except the derived type.</p>
+
+ <p>The ability to override the base parser callbacks in the
+ derived parser is also available in the tiein style. For
+ example, the following code fragment shows how we can
+ override the <code>age()</code> callback if we didn't
+ like the implementation provided by the base parser:</p>
+
+ <pre class="c++">
+class employee_pimpl: public employee_pskel
+{
+public:
+ employee_pimpl ()
+ : employee_pskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ age (short a)
+ {
+ ...
+ }
+
+ ...
+
+private:
+ person_pimpl base_impl_;
+};
+ </pre>
+
+ <p>In the above example the <code>age</code> element will be
+ handled by <code>emplyee_pimpl</code> while the <code>first-name</code>
+ and <code>last-name</code> callbacks will still go to
+ <code>base_impl_</code>.</p>
+
+ <p>It is also possible to inherit from the base parser implementation
+ instead of declaring it as a member variable. This can be useful
+ if you need to access protected members in the base implementation
+ or need to override a virtual function that is not part of
+ the parser skeleton interface. Note, however, that in this case
+ you will need to resolve a number of ambiguities with explicit
+ qualifications or using-declarations. For example:</p>
+
+
+ <pre class="c++">
+class person_pimpl: public person_pskel
+{
+ ...
+protected:
+ virtual person*
+ create ()
+ {
+ return new person ();
+ }
+};
+
+class employee_pimpl: public employee_pskel,
+ public person_pimpl
+{
+public:
+ employee_pimpl ()
+ : employee_pskel (static_cast&lt;person_pimpl*> (this))
+ {
+ }
+
+ // Resolve ambiguities.
+ //
+ using emplyee_pskel::parsers;
+
+ ...
+
+protected:
+ virtual employee*
+ create ()
+ {
+ return new employee ();
+ }
+};
+ </pre>
+
+
+ <h2><a name="5.7">5.7 Support for Polymorphism</a></h2>
+
+ <p>By default the XSD/e compiler generates non-polymorphic code. If your
+ vocabulary uses XML Schema polymorphism in the form of <code>xsi:type</code>
+ and/or substitution groups, then you will need to configure the XSD/e
+ runtime with support for polymorphism, compile your schemas with the
+ <code>--generate-polymorphic</code> option to produce polymorphism-aware
+ code, as well as pass <code>true</code> as the last argument to the
+ <code>xml_schema::document_pimpl</code>'s constructors. If some of your
+ schemas do not require support for polymorphism then you can compile
+ them with the <code>--runtime-polymorphic</code> option and still
+ use the XSD/e runtime configured with polymorphism support.
+ </p>
+
+ <p>When using the polymorphism-aware generated code, you can specify
+ several parsers for a single element by passing a parser map
+ instead of an individual parser to the parser connection function
+ for the element. One of the parsers will then be looked up and used
+ depending on the <code>xsi:type</code> attribute value or an element
+ name from a substitution group. Consider the following schema as an
+ example:</p>
+
+ <pre class="xml">
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="name" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;!-- substitution group root -->
+ &lt;xs:element name="person" type="person"/>
+
+ &lt;xs:complexType name="superman">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="person">
+ &lt;xs:attribute name="can-fly" type="xs:boolean"/>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="superman"
+ type="superman"
+ substitutionGroup="person"/>
+
+ &lt;xs:complexType name="batman">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="superman">
+ &lt;xs:attribute name="wing-span" type="xs:unsignedInt"/>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="batman"
+ type="batman"
+ substitutionGroup="superman"/>
+
+ &lt;xs:complexType name="supermen">
+ &lt;xs:sequence>
+ &lt;xs:element ref="person" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="supermen" type="supermen"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Conforming XML documents can use the <code>superman</code>
+ and <code>batman</code> types in place of the <code>person</code>
+ type either by specifying the type with the <code>xsi:type</code>
+ attributes or by using the elements from the substitution
+ group, for instance:</p>
+
+
+ <pre class="xml">
+&lt;supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ &lt;person>
+ &lt;name>John Doe&lt;/name>
+ &lt;/person>
+
+ &lt;superman can-fly="false">
+ &lt;name>James "007" Bond&lt;/name>
+ &lt;/superman>
+
+ &lt;superman can-fly="true" wing-span="10" xsi:type="batman">
+ &lt;name>Bruce Wayne&lt;/name>
+ &lt;/superman>
+
+&lt;/supermen>
+ </pre>
+
+ <p>To print the data stored in such XML documents we can implement
+ the parsers as follows:</p>
+
+ <pre class="c++">
+class person_pimpl: public person_pskel
+{
+public:
+ virtual void
+ pre ()
+ {
+ cout &lt;&lt; "starting to parse person" &lt;&lt; endl;
+ }
+
+ virtual void
+ name (const std::string&amp; v)
+ {
+ cout &lt;&lt; "name: " &lt;&lt; v &lt;&lt; endl;
+ }
+
+ virtual void
+ post_person ()
+ {
+ cout &lt;&lt; "finished parsing person" &lt;&lt; endl;
+ }
+};
+
+class superman_pimpl: public superman_pskel
+{
+public:
+ superman_pimpl ()
+ : superman_pskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ pre ()
+ {
+ cout &lt;&lt; "starting to parse superman" &lt;&lt; endl;
+ }
+
+ virtual void
+ can_fly (bool v)
+ {
+ cout &lt;&lt; "can-fly: " &lt;&lt; v &lt;&lt; endl;
+ }
+
+ virtual void
+ post_person ()
+ {
+ post_superman ();
+ }
+
+ virtual void
+ post_superman ()
+ {
+ cout &lt;&lt; "finished parsing superman" &lt;&lt; endl
+ }
+
+private:
+ person_pimpl base_impl_;
+};
+
+class batman_pimpl: public batman_pskel
+{
+public:
+ batman_pimpl ()
+ : batman_pskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ pre ()
+ {
+ cout &lt;&lt; "starting to parse batman" &lt;&lt; endl;
+ }
+
+ virtual void
+ wing_span (unsigned int v)
+ {
+ cout &lt;&lt; "wing-span: " &lt;&lt; v &lt;&lt; endl;
+ }
+
+ virtual void
+ post_person ()
+ {
+ post_superman ();
+ }
+
+ virtual void
+ post_superman ()
+ {
+ post_batman ();
+ }
+
+ virtual void
+ post_batman ()
+ {
+ cout &lt;&lt; "finished parsing batman" &lt;&lt; endl;
+ }
+
+private:
+ superman_pimpl base_impl_;
+};
+ </pre>
+
+ <p>Note that because the derived type parsers (<code>superman_pskel</code>
+ and <code>batman_pskel</code>) are called via the <code>person_pskel</code>
+ interface, we have to override the <code>post_person()</code> virtual
+ function in <code>superman_pimpl</code> and <code>batman_pimpl</code>
+ to call <code>post_superman()</code> and the <code>post_superman()</code>
+ virtual function in <code>batman_pimpl</code> to call
+ <code>post_batman()</code> (when the mixin parser reuse style is used
+ it is not necessary to override <code>post_person()</code>
+ in <code>batman_pimpl</code> since the suitable implementation
+ is inherited from <code>superman_pimpl</code>).</p>
+
+ <p>The following code fragment shows how to connect the parsers together.
+ Notice that for the <code>person</code> element in the <code>supermen_p</code>
+ parser we specify a parser map instead of a specific parser and we pass
+ <code>true</code> as the last argument to the document parser constructor
+ to indicate that we are parsing potentially-polymorphic XML documents:</p>
+
+ <pre class="c++">
+int
+main (int argc, char* argv[])
+{
+ // Construct the parser.
+ //
+ xml_schema::string_pimpl string_p;
+ xml_schema::boolean_pimpl boolean_p;
+ xml_schema::unsigned_int_pimpl unsigned_int_p;
+
+ person_pimpl person_p;
+ superman_pimpl superman_p;
+ batman_pimpl batman_p;
+
+ xml_schema::parser_map_impl person_map (5); // 5 hashtable buckets
+ supermen_pimpl supermen_p;
+
+ person_p.parsers (string_p);
+ superman_p.parsers (string_p, boolean_p);
+ batman_p.parsers (string_p, boolean_p, unsigned_int_p);
+
+ // Here we are specifying several parsers that can be used to
+ // parse the person element.
+ //
+ person_map.insert (person_p);
+ person_map.insert (superman_p);
+ person_map.insert (batman_p);
+
+ supermen_p.person_parser (person_map);
+
+ // Parse the XML document. The last argument to the document's
+ // constructor indicates that we are parsing polymorphic XML
+ // documents.
+ //
+ xml_schema::document_pimpl doc_p (supermen_p, "supermen", true);
+
+ supermen_p.pre ();
+ doc_p.parse (argv[1]);
+ supermen_p.post_supermen ();
+}
+ </pre>
+
+ <p>When polymorphism-aware code is generated, each element's
+ <code>*_parser()</code> function is overloaded to also accept
+ an object of the <code>xml_schema::parser_map</code> type.
+ For example, the <code>supermen_pskel</code> class from the
+ above example looks like this:</p>
+
+ <pre class="c++">
+class supermen_pskel: public xml_schema::parser_complex_content
+{
+public:
+
+ ...
+
+ // Parser construction API.
+ //
+ void
+ parsers (person_pskel&amp;);
+
+ // Individual element parsers.
+ //
+ void
+ person_parser (person_pskel&amp;);
+
+ void
+ person_parser (xml_schema::parser_map&amp;);
+
+ ...
+};
+ </pre>
+
+ <p>Note that you can specify both the individual (static) parser and
+ the parser map. The individual parser will be used when the static
+ element type and the dynamic type of the object being parsed are
+ the same. This is the case, for example, when there is no
+ <code>xsi:type</code> attribute and the element hasn't been
+ substituted. Because the individual parser for an element is
+ cached and no map lookup is necessary, it makes sense to specify
+ both the individual parser and the parser map when most of the
+ objects being parsed are of the static type and optimal
+ performance is important. The following code fragment shows
+ how to change the above example to set both the individual
+ parser and the parser map:</p>
+
+ <pre class="c++">
+int
+main (int argc, char* argv[])
+{
+ ...
+
+ // Here we are specifying several parsers that can be used to
+ // parse the person element.
+ //
+ person_map.insert (superman_p);
+ person_map.insert (batman_p);
+
+ supermen_p.person_parser (person_p);
+ supermen_p.person_parser (person_map);
+
+ ...
+}
+ </pre>
+
+
+ <p>The <code>xml_schema::parser_map</code> interface and the
+ <code>xml_schema::parser_map_impl</code> default implementation
+ are presented below:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class parser_map
+ {
+ public:
+ virtual parser_base*
+ find (const char* type) const = 0;
+
+ virtual void
+ reset () const = 0;
+ };
+
+ class parser_map_impl: public parser_map
+ {
+ public:
+ parser_map_impl (size_t buckets);
+
+ void
+ insert (parser_base&amp;);
+
+ virtual parser_base*
+ find (const char* type) const;
+
+ virtual void
+ reset () const;
+
+ private:
+ parser_map_impl (const parser_map_impl&amp;);
+
+ parser_map_impl&amp;
+ operator= (const parser_map_impl&amp;);
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>type</code> argument in the <code>find()</code> virtual
+ function is the type name and namespace from the xsi:type attribute
+ (the namespace prefix is resolved to the actual XML namespace)
+ or the type of an element from the substitution group in the form
+ <code>"&lt;name>&nbsp;&lt;namespace>"</code> with the space and the
+ namespace part absent if the type does not have a namespace.
+ You can obtain a parser's dynamic type in the same format
+ using the <code>_dynamic_type()</code> function. The static
+ type can be obtained by calling the static <code>_static_type()</code>
+ function, for example <code>person_pskel::_static_type()</code>.
+ Both functions return a C string (<code>const char*</code>) which
+ is valid for as long as the application is running. The
+ <code>reset()</code> virtual function is used to reset
+ the parsers contained in the map (as opposed to resetting or
+ clearing the map itself). For more information on parser
+ resetting refer to <a href="#7.4">Section 7.4, "Reusing Parsers
+ after an Error"</a>. The following example shows how we can
+ implement our own parser map using <code>std::map</code>:</p>
+
+
+ <pre class="c++">
+#include &lt;map>
+#include &lt;string>
+
+class parser_map: public xml_schema::parser_map
+{
+public:
+ void
+ insert (xml_schema::parser_base&amp; p)
+ {
+ map_[p._dynamic_type ()] = &amp;p;
+ }
+
+ virtual xml_schema::parser_base*
+ find (const char* type) const
+ {
+ map::const_iterator i = map_.find (type);
+ return i != map_.end () ? i->second : 0;
+ }
+
+ virtual void
+ reset () const
+ {
+ for (map::const_iterator i (map_.begin ()), e (map_.end ());
+ i != e; ++i)
+ {
+ xml_schema::parser_base* p = i->second;
+ p->_reset ();
+ }
+ }
+
+private:
+ typedef std::map&lt;std::string, xml_schema::parser_base*> map;
+ map map_;
+};
+ </pre>
+
+ <p>The XSD/e runtime provides the default implementation for the
+ <code>xml_schema::parser_map</code> interface,
+ <code>xml_schema::parser_map_impl</code>, which is a hashmap.
+ It requires that you specify the number of buckets it will contain
+ and it does not support automatic table resizing. To obtain good
+ performance the elements to buckets ratio should be between 0.7 and
+ 0.9. It is also recommended to use prime numbers for bucket counts:
+ 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317,
+ 196613, 393241.
+ </p>
+
+ <p>If C++ exceptions are disabled (<a href="#5.3">Section 5.3,
+ "C++ Exceptions"</a>), the <code>xml_schema::parser_map_impl</code>
+ class has the following additional error querying API. It can be used
+ to detect the out of memory errors after calls to the
+ <code>parser_map_impl</code>'s constructor and <code>insert()</code>
+ function.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class parser_map_impl: public parser_map
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ error
+ _error () const;
+
+ ...
+ };
+}
+ </pre>
+
+ <p>To support polymorphic parsing the XSD/e runtime and generated code
+ maintain a number of hashmaps that contain substitution and, if
+ XML Schema validation is enabled (<a href="#5.4">Section 5.4,
+ "XML Schema Validation"</a>), inheritance information. Because
+ the number of elements in these hashmaps depends on the schemas
+ being compiled and thus is fairly static, these hashmaps do not
+ perform automatic table resizing and instead the number of buckets
+ is specified when the XSD/e runtime is configured. To obtain good
+ performance the elements to buckets ratio in these hashmaps should
+ be between 0.7 and 0.9. The recommended way to ensure this range
+ is to add diagnostics code to your application as shown in the
+ following example:</p>
+
+ <pre class="c++">
+int
+main ()
+{
+ // Check that the load in substitution and inheritance hashmaps
+ // is not too high.
+ //
+#ifndef NDEBUG
+ float load = xml_schema::parser_smap_elements ();
+ load /= xml_schema::parser_smap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr &lt;&lt; "substitution hashmap load is " &lt;&lt; load &lt;&lt; endl;
+ cerr &lt;&lt; "time to increase XSDE_PARSER_SMAP_BUCKETS" &lt;&lt; endl;
+ }
+
+ load = xml_schema::parser_imap_elements ();
+ load /= xml_schema::parser_imap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr &lt;&lt; "inheritance hashmap load is " &lt;&lt; load &lt;&lt; endl;
+ cerr &lt;&lt; "time to increase XSDE_PARSER_IMAP_BUCKETS" &lt;&lt; endl;
+ }
+#endif
+
+ ...
+}
+ </pre>
+
+ <p>Most of the code presented in this section is taken from the
+ <code>polymorphism</code> example which can be found in the
+ <code>examples/cxx/parser/</code> directory of the XSD/e distribution.
+ Handling of <code>xsi:type</code> and substitution groups when used
+ on root elements requires a number of special actions as shown in
+ the <code>polyroot</code> example.</p>
+
+ <h2><a name="5.8">5.8 Custom Allocators</a></h2>
+
+ <p>By default the XSD/e runtime and generated code use
+ the standard operators <code>new</code> and <code>delete</code>
+ to manage dynamic memory. However, it is possible to instead
+ use custom allocator functions provided by your application.
+ To achieve this, configure the XSD/e runtime library to use
+ custom allocator functions as well as pass the
+ <code>--custom-allocator</code> option to the XSD/e compiler
+ when translating your schemas. The signatures of the custom
+ allocator functions that should be provided by your application
+ are listed below. Their semantics should be equivalent to the
+ standard C <code>malloc()</code>, <code>realloc()</code>, and
+ <code>free()</code> functions.</p>
+
+ <pre class="c++">
+extern "C" void*
+xsde_alloc (size_t);
+
+extern "C" void*
+xsde_realloc (void*, size_t);
+
+extern "C" void
+xsde_free (void*);
+ </pre>
+
+ <p>Note also that when custom allocators are enabled, any
+ dynamically-allocated object of which the XSD/e runtime
+ or generated code assume ownership should be allocated
+ using the custom allocation function. Similarly, if your
+ application assumes ownership of any dynamically-allocated
+ object returned by the XSD/e runtime or the generated code,
+ then such an object should be disposed of using the custom
+ deallocation function. To help with these tasks the generated
+ <code>xml_schema</code> namespace defines the following two
+ helper functions and, if C++ exceptions are enabled, automatic
+ pointer class:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ void*
+ alloc (size_t);
+
+ void
+ free (void*);
+
+ struct alloc_guard
+ {
+ alloc_guard (void*);
+ ~alloc_guard ();
+
+ void*
+ get () const;
+
+ void
+ release ();
+
+ private:
+ ...
+ };
+}
+ </pre>
+
+ <p>If C++ exceptions are disabled, these functions are equivalent
+ to <code>xsde_alloc()</code> and <code>xsde_free()</code>.
+ If exceptions are enabled, <code>xml_schema::alloc()</code>
+ throws <code>std::bad_alloc</code> on memory allocation failure.</p>
+
+ <p>The following code fragment shows how to create and destroy a
+ dynamically-allocated object with custom allocators when C++
+ exceptions are disabled:</p>
+
+ <pre class="c++">
+void* v = xml_schema::alloc (sizeof (type));
+
+if (v == 0)
+{
+ // Handle out of memory condition.
+}
+
+type* x = new (v) type (1, 2);
+
+...
+
+if (x)
+{
+ x->~type ();
+ xml_schema::free (x);
+}
+ </pre>
+
+ <p>The equivalent code fragment for configurations with C++ exceptions
+ enabled is shown below:</p>
+
+ <pre class="c++">
+xml_schema::alloc_guard g (xml_schema::alloc (sizeof (type)));
+type* x = new (g.get ()) type (1, 2);
+g.release ();
+
+...
+
+if (x)
+{
+ x->~type ();
+ xml_schema::free (x);
+}
+ </pre>
+
+ <h2><a name="5.9">5.9 A Minimal Example</a></h2>
+
+ <p>The following example is a re-implementation of the person
+ records example presented in <a href="#3">Chapter 3,
+ "Parser Skeletons"</a>. It is intended to work
+ without STL, iostream, and C++ exceptions. It can be found in
+ the <code>examples/cxx/parser/minimal/</code> directory of the
+ XSD/e distribution. The <code>people.xsd</code> schema is
+ compiled with the <code>--no-stl</code>, <code>--no-iostream</code>,
+ and <code>--no-exceptions</code> options. The following listing
+ presents the implementation of parser skeletons and the test
+ driver in full.</p>
+
+ <pre class="c++">
+#include &lt;stdio.h>
+
+#include "people-pskel.hxx"
+
+class gender_pimpl: public gender_pskel
+{
+public:
+ gender_pimpl ()
+ : gender_pskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ post_gender ()
+ {
+ char* s = post_string ();
+ printf ("gender: %s\n", s);
+ delete[] s;
+ }
+
+private:
+ xml_schema::string_pimpl base_impl_;
+};
+
+class person_pimpl: public person_pskel
+{
+public:
+ virtual void
+ first_name (char* n)
+ {
+ printf ("first: %s\n", n);
+ delete[] n;
+ }
+
+ virtual void
+ last_name (char* n)
+ {
+ printf ("last: %s\n", n);
+ delete[] n;
+ }
+
+ virtual void
+ age (short a)
+ {
+ printf ("age: %hd\n", a);
+ }
+};
+
+class people_pimpl: public people_pskel
+{
+public:
+ virtual void
+ person ()
+ {
+ // Add an extra newline after each person record.
+ //
+ printf ("\n");
+ }
+};
+
+int
+main (int argc, char* argv[])
+{
+ // Construct the parser.
+ //
+ xml_schema::short_pimpl short_p;
+ xml_schema::string_pimpl string_p;
+
+ gender_pimpl gender_p;
+ person_pimpl person_p;
+ people_pimpl people_p;
+
+ person_p.parsers (string_p, string_p, gender_p, short_p);
+ people_p.parsers (person_p);
+
+ // Open the file.
+ //
+ FILE* f = fopen (argv[1], "rb");
+
+ if (f == 0)
+ {
+ fprintf (stderr, "%s: unable to open\n", argv[1]);
+ return 1;
+ }
+
+ // Parse.
+ //
+ typedef xml_schema::parser_error error;
+ error e;
+ bool io_error = false;
+
+ do
+ {
+ xml_schema::document_pimpl doc_p (people_p, "people");
+ if (e = doc_p._error ())
+ break;
+
+ people_p.pre ();
+ if (e = people_p._error ())
+ break;
+
+ char buf[4096];
+ do
+ {
+ size_t s = fread (buf, 1, sizeof (buf), f);
+
+ if (s != sizeof (buf) &amp;&amp; ferror (f))
+ {
+ io_error = true;
+ break;
+ }
+
+ doc_p.parse (buf, s, feof (f) != 0);
+ e = doc_p._error ();
+
+ } while (!e &amp;&amp; !feof (f));
+
+ if (io_error || e)
+ break;
+
+ people_p.post_people ();
+ e = people_p._error ();
+
+ } while (false);
+
+ fclose (f);
+
+ // Handle errors.
+ //
+
+ if (io_error)
+ {
+ fprintf (stderr, "%s: read failure\n", argv[1]);
+ return 1;
+ }
+
+ if (e)
+ {
+ switch (e.type ())
+ {
+ case error::sys:
+ {
+ fprintf (stderr, "%s: %s\n", argv[1], e.sys_text ());
+ break;
+ }
+ case error::xml:
+ {
+ fprintf (stderr, "%s:%lu:%lu: %s\n",
+ argv[1], e.line (), e.column (), e.xml_text ());
+ break;
+ }
+ case error::schema:
+ {
+ fprintf (stderr, "%s:%lu:%lu: %s\n",
+ argv[1], e.line (), e.column (), e.schema_text ());
+ break;
+ }
+ case error::app:
+ {
+ fprintf (stderr, "%s:%lu:%lu: application error %d\n",
+ argv[1], e.line (), e.column (), e.app_code ());
+ break;
+ }
+ default:
+ break;
+ }
+ return 1;
+ }
+ return 0;
+}
+ </pre>
+
+
+ <!-- Built-in XML Schema Type Parsers -->
+
+
+ <h1><a name="6">6 Built-In XML Schema Type Parsers</a></h1>
+
+ <p>The XSD/e runtime provides parser implementations for all built-in
+ XML Schema types as summarized in the following table. Declarations
+ for these types are automatically included into each generated
+ header file. As a result you don't need to include any headers
+ to gain access to these parser implementations.</p>
+
+ <!-- border="1" is necessary for html2ps -->
+ <table id="builtin" border="1">
+ <tr>
+ <th>XML Schema type</th>
+ <th>Parser implementation in the <code>xml_schema</code> namespace</th>
+ <th>Parser return type</th>
+ </tr>
+
+ <tr>
+ <th colspan="3">anyType and anySimpleType types</th>
+ </tr>
+ <tr>
+ <td><code>anyType</code></td>
+ <td><code>any_type_pimpl</code></td>
+ <td><code>void</code></td>
+ </tr>
+ <tr>
+ <td><code>anySimpleType</code></td>
+ <td><code>any_simple_type_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-length integral types</th>
+ </tr>
+ <!-- 8-bit -->
+ <tr>
+ <td><code>byte</code></td>
+ <td><code>byte_pimpl</code></td>
+ <td><code>signed&nbsp;char</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedByte</code></td>
+ <td><code>unsigned_byte_pimpl</code></td>
+ <td><code>unsigned&nbsp;char</code></td>
+ </tr>
+
+ <!-- 16-bit -->
+ <tr>
+ <td><code>short</code></td>
+ <td><code>short_pimpl</code></td>
+ <td><code>short</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedShort</code></td>
+ <td><code>unsigned_short_pimpl</code></td>
+ <td><code>unsigned&nbsp;short</code></td>
+ </tr>
+
+ <!-- 32-bit -->
+ <tr>
+ <td><code>int</code></td>
+ <td><code>int_pimpl</code></td>
+ <td><code>int</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedInt</code></td>
+ <td><code>unsigned_int_pimpl</code></td>
+ <td><code>unsigned&nbsp;int</code></td>
+ </tr>
+
+ <!-- 64-bit -->
+ <tr>
+ <td><code>long</code></td>
+ <td><code>long_pimpl</code></td>
+ <td><code>long&nbsp;long</code> or <code>long</code><br/>
+ <a href="#5.5">Section 5.5, "64-bit Integer Type"</a></td>
+ </tr>
+ <tr>
+ <td><code>unsignedLong</code></td>
+ <td><code>unsigned_long_pimpl</code></td>
+ <td><code>unsigned&nbsp;long&nbsp;long</code> or
+ <code>unsigned&nbsp;long</code><br/>
+ <a href="#5.5">Section 5.5, "64-bit Integer Type"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-length integral types</th>
+ </tr>
+ <tr>
+ <td><code>integer</code></td>
+ <td><code>integer_pimpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonPositiveInteger</code></td>
+ <td><code>non_positive_integer_pimpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonNegativeInteger</code></td>
+ <td><code>non_negative_integer_pimpl</code></td>
+ <td><code>unsigned&nbsp;long</code></td>
+ </tr>
+ <tr>
+ <td><code>positiveInteger</code></td>
+ <td><code>positive_integer_pimpl</code></td>
+ <td><code>unsigned&nbsp;long</code></td>
+ </tr>
+ <tr>
+ <td><code>negativeInteger</code></td>
+ <td><code>negative_integer_pimpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">boolean types</th>
+ </tr>
+ <tr>
+ <td><code>boolean</code></td>
+ <td><code>boolean_pimpl</code></td>
+ <td><code>bool</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>float</code></td>
+ <td><code>float_pimpl</code></td>
+ <td><code>float</code></td>
+ </tr>
+ <tr>
+ <td><code>double</code></td>
+ <td><code>double_pimpl</code></td>
+ <td><code>double</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>decimal</code></td>
+ <td><code>decimal_pimpl</code></td>
+ <td><code>double</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">string-based types</th>
+ </tr>
+ <tr>
+ <td><code>string</code></td>
+ <td><code>string_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>normalizedString</code></td>
+ <td><code>normalized_string_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>token</code></td>
+ <td><code>token_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>Name</code></td>
+ <td><code>name_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>NMTOKEN</code></td>
+ <td><code>nmtoken_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>NCName</code></td>
+ <td><code>ncname_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <td><code>language</code></td>
+ <td><code>language_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">qualified name</th>
+ </tr>
+ <tr>
+ <td><code>QName</code></td>
+ <td><code>qname_pimpl</code></td>
+ <td><code>xml_schema::qname</code> or <code>xml_schema::qname*</code><br/>
+ <a href="#6.1">Section 6.1, "<code>QName</code> Parser"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">ID/IDREF types</th>
+ </tr>
+ <tr>
+ <td><code>ID</code></td>
+ <td><code>id_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREF</code></td>
+ <td><code>idref_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">list types</th>
+ </tr>
+ <tr>
+ <td><code>NMTOKENS</code></td>
+ <td><code>nmtokens_pimpl</code></td>
+ <td><code>xml_schema::string_sequence*</code><br/><a href="#6.2">Section
+ 6.2, "<code>NMTOKENS</code> and <code>IDREFS</code> Parsers"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREFS</code></td>
+ <td><code>idrefs_pimpl</code></td>
+ <td><code>xml_schema::string_sequence*</code><br/><a href="#6.2">Section
+ 6.2, "<code>NMTOKENS</code> and <code>IDREFS</code> Parsers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">URI types</th>
+ </tr>
+ <tr>
+ <td><code>anyURI</code></td>
+ <td><code>uri_pimpl</code></td>
+ <td><code>std::string</code> or <code>char*</code><br/>
+ <a href="#5.1">Section 5.1, "Standard Template Library"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">binary types</th>
+ </tr>
+ <tr>
+ <td><code>base64Binary</code></td>
+ <td><code>base64_binary_pimpl</code></td>
+ <td><code>xml_schema::buffer*</code><br/>
+ <a href="#6.3">Section 6.3, "<code>base64Binary</code> and
+ <code>hexBinary</code> Parsers"</a></td>
+ </tr>
+ <tr>
+ <td><code>hexBinary</code></td>
+ <td><code>hex_binary_pimpl</code></td>
+ <td><code>xml_schema::buffer*</code><br/>
+ <a href="#6.3">Section 6.3, "<code>base64Binary</code> and
+ <code>hexBinary</code> Parsers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">date/time types</th>
+ </tr>
+ <tr>
+ <td><code>date</code></td>
+ <td><code>date_pimpl</code></td>
+ <td><code>xml_schema::date</code><br/><a href="#6.5">Section 6.5,
+ "<code>date</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>dateTime</code></td>
+ <td><code>date_time_pimpl</code></td>
+ <td><code>xml_schema::date_time</code><br/><a href="#6.6">Section 6.6,
+ "<code>dateTime</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>duration</code></td>
+ <td><code>duration_pimpl</code></td>
+ <td><code>xml_schema::duration</code><br/><a href="#6.7">Section 6.7,
+ "<code>duration</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>gDay</code></td>
+ <td><code>gday_pimpl</code></td>
+ <td><code>xml_schema::gday</code><br/><a href="#6.8">Section 6.8,
+ "<code>gDay</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonth</code></td>
+ <td><code>gmonth_pimpl</code></td>
+ <td><code>xml_schema::gmonth</code><br/><a href="#6.9">Section 6.9,
+ "<code>gMonth</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonthDay</code></td>
+ <td><code>gmonth_day_pimpl</code></td>
+ <td><code>xml_schema::gmonth_day</code><br/><a href="#6.10">Section 6.10,
+ "<code>gMonthDay</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYear</code></td>
+ <td><code>gyear_pimpl</code></td>
+ <td><code>xml_schema::gyear</code><br/><a href="#6.11">Section 6.11,
+ "<code>gYear</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYearMonth</code></td>
+ <td><code>gyear_month_pimpl</code></td>
+ <td><code>xml_schema::gyear_month</code><br/><a href="#6.12">Section
+ 6.12, "<code>gYearMonth</code> Parser"</a></td>
+ </tr>
+ <tr>
+ <td><code>time</code></td>
+ <td><code>time_pimpl</code></td>
+ <td><code>xml_schema::time</code><br/><a href="#6.13">Section 6.13,
+ "<code>time</code> Parser"</a></td>
+ </tr>
+
+ </table>
+
+ <h2><a name="6.1">6.1 <code>QName</code> Parser</a></h2>
+
+ <p>The return type of the <code>qname_pimpl</code> parser implementation
+ is either <code>xml_schema::qname</code> when STL is enabled
+ (<a href="#5.1">Section 5.1, "Standard Template Library"</a>) or
+ <code>xml_schema::qname*</code> when STL is disabled. The
+ <code>qname</code> class represents an XML qualified name. When the
+ return type is <code>xml_schema::qname*</code>, the returned
+ object is dynamically allocated with operator <code>new</code>
+ and should eventually be deallocated with operator <code>delete</code>.
+ With STL enabled, the <code>qname</code> type has the following
+ interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (const std::string&amp; name);
+ qname (const std::string&amp; prefix, const std::string&amp; name);
+
+ void
+ swap (qname&amp;);
+
+ const std::string&amp;
+ prefix () const;
+
+ std::string&amp;
+ prefix ();
+
+ void
+ prefix (const std::string&amp;);
+
+ const std::string&amp;
+ name () const;
+
+ std::string&amp;
+ name ();
+
+ void
+ name (const std::string&amp;);
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <p>When STL is disabled and C++ exceptions are enabled
+ (<a href="#5.3">Section 5.3, "C++ Exceptions"</a>), the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (char* name);
+ qname (char* prefix, char* name);
+
+ void
+ swap (qname&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ public:
+ char*
+ prefix ();
+
+ const char*
+ prefix () const;
+
+ void
+ prefix (char*);
+
+ void
+ prefix_copy (const char*);
+
+ char*
+ prefix_detach ();
+
+ public:
+ char*
+ name ();
+
+ const char*
+ name () const;
+
+ void
+ name (char*);
+
+ void
+ name_copy (const char*);
+
+ char*
+ name_detach ();
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+</pre>
+
+ <p>The modifier functions and constructors that have the <code>char*</code>
+ argument assume ownership of the passed strings which should be allocated
+ with operator <code>new char[]</code> and will be deallocated with
+ operator <code>delete[]</code> by the <code>qname</code> object.
+ If you detach the underlying prefix or name strings, then they
+ should eventually be deallocated with operator <code>delete[]</code>.
+ </p>
+
+ <p>Finally, if both STL and C++ exceptions are disabled, the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (char* name);
+ qname (char* prefix, char* name);
+
+ void
+ swap (qname&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ public:
+ char*
+ prefix ();
+
+ const char*
+ prefix () const;
+
+ void
+ prefix (char*);
+
+ error
+ prefix_copy (const char*);
+
+ char*
+ prefix_detach ();
+
+ public:
+ char*
+ name ();
+
+ const char*
+ name () const;
+
+ void
+ name (char*);
+
+ error
+ name_copy (const char*);
+
+ char*
+ name_detach ();
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <h2><a name="6.2">6.2 <code>NMTOKENS</code> and <code>IDREFS</code> Parsers</a></h2>
+
+ <p>The return type of the <code>nmtokens_pimpl</code> and
+ <code>idrefs_pimpl</code> parser implementations is
+ <code>xml_schema::string_sequence*</code>.
+ The returned object is dynamically allocated with operator
+ <code>new</code> and should eventually be deallocated with
+ operator <code>delete</code>. With STL and C++ exceptions enabled
+ (<a href="#5.1">Section 5.1, "Standard Template Library"</a>,
+ <a href="#5.3">Section 5.3, "C++ Exceptions"</a>), the
+ <code>string_sequence</code> type has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ typedef std::string value_type;
+ typedef std::string* pointer;
+ typedef const std::string* const_pointer;
+ typedef std::string&amp; reference;
+ typedef const std::string&amp; const_reference;
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef std::string* iterator;
+ typedef const std::string* const_iterator;
+
+ public:
+ string_sequence ();
+
+ void
+ swap (string_sequence&amp;);
+
+ private:
+ string_sequence (string_sequence&amp;);
+
+ string_sequence&amp;
+ operator= (string_sequence&amp;);
+
+ public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ std::string&amp;
+ front ();
+
+ const std::string&amp;
+ front () const;
+
+ std::string&amp;
+ back ();
+
+ const std::string&amp;
+ back () const;
+
+ std::string&amp;
+ operator[] (size_t);
+
+ const std::string&amp;
+ operator[] (size_t) const;
+
+ public:
+ bool
+ empty () const;
+
+ size_t
+ size () const;
+
+ size_t
+ capacity () const;
+
+ size_t
+ max_size () const;
+
+ public:
+ void
+ clear ();
+
+ void
+ pop_back ();
+
+ iterator
+ erase (iterator);
+
+ void
+ push_back (const std::string&amp;);
+
+ iterator
+ insert (iterator, const std::string&amp;);
+
+ void
+ reserve (size_t);
+ };
+
+ bool
+ operator== (const string_sequence&amp;, const string_sequence&amp;);
+
+ bool
+ operator!= (const string_sequence&amp;, const string_sequence&amp;);
+}
+ </pre>
+
+ <p>When STL is enabled and C++ exceptions are disabled, the signatures
+ of the <code>push_back()</code>, <code>insert()</code>, and
+ <code>reserve()</code> functions change as follows:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ ...
+
+ public:
+ error
+ push_back (const std::string&amp;);
+
+ error
+ insert (iterator, const std::string&amp;);
+
+ error
+ insert (iterator, const std::string&amp;, iterator&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+ <p>When STL is disabled and C++ exceptions are enabled, the
+ <code>string_sequence</code> type has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ typedef char* value_type;
+ typedef char** pointer;
+ typedef const char** const_pointer;
+ typedef char* reference;
+ typedef const char* const_reference;
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef char** iterator;
+ typedef const char* const* const_iterator;
+
+ string_sequence ();
+
+ void
+ swap (string_sequence&amp;);
+
+ private:
+ string_sequence (string_sequence&amp;);
+
+ string_sequence&amp;
+ operator= (string_sequence&amp;);
+
+ public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ char*
+ front ();
+
+ const char*
+ front () const;
+
+ char*
+ back ();
+
+ const char*
+ back () const;
+
+ char*
+ operator[] (size_t);
+
+ const char*
+ operator[] (size_t) const;
+
+ public:
+ bool
+ empty () const;
+
+ size_t
+ size () const;
+
+ size_t
+ capacity () const;
+
+ size_t
+ max_size () const;
+
+ public:
+ void
+ clear ();
+
+ void
+ pop_back ();
+
+ iterator
+ erase (iterator);
+
+ void
+ push_back (char*);
+
+ void
+ push_back_copy (const char*);
+
+ iterator
+ insert (iterator, char*);
+
+ void
+ reserve (size_t);
+
+ // Detach a string from the sequence at a given position.
+ // The string pointer at this position in the sequence is
+ // set to 0.
+ //
+ char*
+ detach (iterator);
+ };
+
+ bool
+ operator== (const string_sequence&amp;, const string_sequence&amp;);
+
+ bool
+ operator!= (const string_sequence&amp;, const string_sequence&amp;);
+}
+ </pre>
+
+ <p>The <code>push_back()</code> and <code>insert()</code> functions
+ assume ownership of the passed string which should be allocated
+ with operator <code>new char[]</code> and will be deallocated
+ with operator <code>delete[]</code> by the <code>string_sequence</code>
+ object. These two functions free the passed object if the reallocation
+ of the underlying sequence buffer fails. The <code>push_back_copy()</code>
+ function makes a copy of the passed string.
+ If you detach the underlying element string, then it should
+ eventually be deallocated with operator <code>delete[]</code>.</p>
+
+ <p>When both STL and C++ exceptions are disabled, the signatures
+ of the <code>push_back()</code>, <code>push_back_copy()</code>,
+ <code>insert()</code>, and <code>reserve()</code> functions change
+ as follows:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ ...
+
+ public:
+ error
+ push_back (char*);
+
+ error
+ push_back_copy (const char*);
+
+ error
+ insert (iterator, char*);
+
+ error
+ insert (iterator, char*, iterator&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+
+ <h2><a name="6.3">6.3 <code>base64Binary</code> and <code>hexBinary</code> Parsers</a></h2>
+
+ <p>The return type of the <code>base64_binary_pimpl</code> and
+ <code>hex_binary_pimpl</code> parser implementations is
+ <code>xml_schema::buffer*</code>. The returned object is
+ dynamically allocated with operator <code>new</code> and
+ should eventually be deallocated with operator <code>delete</code>.
+ With C++ exceptions enabled (<a href="#5.3">Section 5.3, "C++
+ Exceptions"</a>), the <code>buffer</code> type has the following
+ interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class buffer
+ {
+ public:
+ class bounds {}; // Out of bounds exception.
+
+ public:
+ buffer ();
+
+ explicit
+ buffer (size_t size);
+ buffer (size_t size, size_t capacity);
+ buffer (const void* data, size_t size);
+ buffer (const void* data, size_t size, size_t capacity);
+
+ enum ownership_value { assume_ownership };
+
+ // This constructor assumes ownership of the memory passed.
+ //
+ buffer (void* data, size_t size, size_t capacity, ownership_value);
+
+ private:
+ buffer (const buffer&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ void
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+ void
+ swap (buffer&amp;);
+
+ public:
+ size_t
+ capacity () const;
+
+ bool
+ capacity (size_t);
+
+ public:
+ size_t
+ size () const;
+
+ bool
+ size (size_t);
+
+ public:
+ const char*
+ data () const;
+
+ char*
+ data ();
+
+ const char*
+ begin () const;
+
+ char*
+ begin ();
+
+ const char*
+ end () const;
+
+ char*
+ end ();
+ };
+
+ bool
+ operator== (const buffer&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <p>The last constructor and the <code>attach()</code> member function
+ make the <code>buffer</code> instance assume the ownership of the
+ memory block pointed to by the <code>data</code> argument and
+ eventually release it by calling <code>operator delete()</code>.
+ The <code>detach()</code> member function detaches and returns the
+ underlying memory block which should eventually be released by
+ calling <code>operator delete()</code>.
+ </p>
+
+ <p>The <code>capacity()</code> and <code>size()</code> modifier functions
+ return <code>true</code> if the underlying buffer has moved. The
+ <code>bounds</code> exception is thrown if the constructor or
+ <code>attach()</code> member function arguments violate the
+ <code>(size&nbsp;&lt;=&nbsp;capacity)</code> constraint.</p>
+
+ <p>If C++ exceptions are disabled, the <code>buffer</code> type has
+ the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class buffer
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_bounds,
+ error_no_memory
+ };
+
+ buffer ();
+
+ private:
+ buffer (const buffer&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ error
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+ void
+ swap (buffer&amp;);
+
+ public:
+ size_t
+ capacity () const;
+
+ error
+ capacity (size_t);
+
+ error
+ capacity (size_t, bool&amp; moved);
+
+ public:
+ size_t
+ size () const;
+
+ error
+ size (size_t);
+
+ error
+ size (size_t, bool&amp; moved);
+
+ public:
+ const char*
+ data () const;
+
+ char*
+ data ();
+
+ const char*
+ begin () const;
+
+ char*
+ begin ();
+
+ const char*
+ end () const;
+
+ char*
+ end ();
+ };
+
+ bool
+ operator== (const buffer&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <h2><a name="6.4">6.4 Time Zone Representation</a></h2>
+
+ <p>The <code>date</code>, <code>dateTime</code>, <code>gDay</code>,
+ <code>gMonth</code>, <code>gMonthDay</code>, <code>gYear</code>,
+ <code>gYearMonth</code>, and <code>time</code> XML Schema built-in
+ types all include an optional time zone component. The following
+ <code>xml_schema::time_zone</code> base class is used to represent
+ this information:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class time_zone
+ {
+ public:
+ time_zone ();
+ time_zone (short hours, short minutes);
+
+ bool
+ zone_present () const;
+
+ void
+ zone_reset ();
+
+ short
+ zone_hours () const;
+
+ void
+ zone_hours (short);
+
+ short
+ zone_minutes () const;
+
+ void
+ zone_minutes (short);
+ };
+
+ bool
+ operator== (const time_zone&amp;, const time_zone&amp;);
+
+ bool
+ operator!= (const time_zone&amp;, const time_zone&amp;);
+}
+ </pre>
+
+ <p>The <code>zone_present()</code> accessor function returns <code>true</code>
+ if the time zone is specified. The <code>zone_reset()</code> modifier
+ function resets the time zone object to the <em>not specified</em>
+ state. If the time zone offset is negative then both hours and
+ minutes components are represented as negative integers.</p>
+
+ <h2><a name="6.5">6.5 <code>date</code> Parser</a></h2>
+
+ <p>The return type of the <code>date_pimpl</code> parser implementation
+ is <code>xml_schema::date</code> which represents a year, a day, and a month
+ with an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class date: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ date ();
+
+ date (int year, unsigned short month, unsigned short day);
+
+ date (int year, unsigned short month, unsigned short day,
+ short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+ };
+
+ bool
+ operator== (const date&amp;, const date&amp;);
+
+ bool
+ operator!= (const date&amp;, const date&amp;);
+}
+ </pre>
+
+ <h2><a name="6.6">6.6 <code>dateTime</code> Parser</a></h2>
+
+ <p>The return type of the <code>date_time_pimpl</code> parser implementation
+ is <code>xml_schema::date_time</code> which represents a year, a month, a day,
+ hours, minutes, and seconds with an optional time zone. Its interface
+ is presented below. For more information on the base
+ <code>xml_schema::time_zone</code> class refer to <a href="#6.4">Section
+ 6.4, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class date_time: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ date_time ();
+
+ date_time (int year, unsigned short month, unsigned short day,
+ unsigned short hours, unsigned short minutes,
+ double seconds);
+
+ date_time (int year, unsigned short month, unsigned short day,
+ unsigned short hours, unsigned short minutes,
+ double seconds, short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+
+ unsigned short
+ hours () const;
+
+ void
+ hours (unsigned short);
+
+ unsigned short
+ minutes () const;
+
+ void
+ minutes (unsigned short);
+
+ double
+ seconds () const;
+
+ void
+ seconds (double);
+ };
+
+ bool
+ operator== (const date_time&amp;, const date_time&amp;);
+
+ bool
+ operator!= (const date_time&amp;, const date_time&amp;);
+}
+ </pre>
+
+ <h2><a name="6.7">6.7 <code>duration</code> Parser</a></h2>
+
+ <p>The return type of the <code>duration_pimpl</code> parser implementation
+ is <code>xml_schema::duration</code> which represents a potentially
+ negative duration in the form of years, months, days, hours, minutes,
+ and seconds. Its interface is presented below.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class duration
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ duration ();
+
+ duration (bool negative,
+ unsigned int years, unsigned int months, unsigned int days,
+ unsigned int hours, unsigned int minutes, double seconds);
+
+ bool
+ negative () const;
+
+ void
+ negative (bool);
+
+ unsigned int
+ years () const;
+
+ void
+ years (unsigned int);
+
+ unsigned int
+ months () const;
+
+ void
+ months (unsigned int);
+
+ unsigned int
+ days () const;
+
+ void
+ days (unsigned int);
+
+ unsigned int
+ hours () const;
+
+ void
+ hours (unsigned int);
+
+ unsigned int
+ minutes () const;
+
+ void
+ minutes (unsigned int);
+
+ double
+ seconds () const;
+
+ void
+ seconds (double);
+ };
+
+ bool
+ operator== (const duration&amp;, const duration&amp;);
+
+ bool
+ operator!= (const duration&amp;, const duration&amp;);
+}
+ </pre>
+
+
+ <h2><a name="6.8">6.8 <code>gDay</code> Parser</a></h2>
+
+ <p>The return type of the <code>gday_pimpl</code> parser implementation
+ is <code>xml_schema::gday</code> which represents a day of the month with
+ an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gday: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gday ();
+
+ explicit
+ gday (unsigned short day);
+
+ gday (unsigned short day, short zone_hours, short zone_minutes);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+ };
+
+ bool
+ operator== (const gday&amp;, const gday&amp;);
+
+ bool
+ operator!= (const gday&amp;, const gday&amp;);
+}
+ </pre>
+
+ <h2><a name="6.9">6.9 <code>gMonth</code> Parser</a></h2>
+
+ <p>The return type of the <code>gmonth_pimpl</code> parser implementation
+ is <code>xml_schema::gmonth</code> which represents a month of the year
+ with an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gmonth: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gmonth ();
+
+ explicit
+ gmonth (unsigned short month);
+
+ gmonth (unsigned short month,
+ short zone_hours, short zone_minutes);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+ };
+
+ bool
+ operator== (const gmonth&amp;, const gmonth&amp;);
+
+ bool
+ operator!= (const gmonth&amp;, const gmonth&amp;);
+}
+ </pre>
+
+ <h2><a name="6.10">6.10 <code>gMonthDay</code> Parser</a></h2>
+
+ <p>The return type of the <code>gmonth_day_pimpl</code> parser implementation
+ is <code>xml_schema::gmonth_day</code> which represents a day and a month of
+ the year with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gmonth_day: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gmonth_day ();
+
+ gmonth_day (unsigned short month, unsigned short day);
+
+ gmonth_day (unsigned short month, unsigned short day,
+ short zone_hours, short zone_minutes);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+ };
+
+ bool
+ operator== (const gmonth_day&amp;, const gmonth_day&amp;);
+
+ bool
+ operator!= (const gmonth_day&amp;, const gmonth_day&amp;);
+}
+ </pre>
+
+ <h2><a name="6.11">6.11 <code>gYear</code> Parser</a></h2>
+
+ <p>The return type of the <code>gyear_pimpl</code> parser implementation
+ is <code>xml_schema::gyear</code> which represents a year with
+ an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gyear: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gyear ();
+
+ explicit
+ gyear (int year);
+
+ gyear (int year, short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+ };
+
+ bool
+ operator== (const gyear&amp;, const gyear&amp;);
+
+ bool
+ operator!= (const gyear&amp;, const gyear&amp;);
+}
+ </pre>
+
+ <h2><a name="6.12">6.12 <code>gYearMonth</code> Parser</a></h2>
+
+ <p>The return type of the <code>gyear_month_pimpl</code> parser implementation
+ is <code>xml_schema::gyear_month</code> which represents a year and a month
+ with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gyear_month: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gyear_month ();
+
+ gyear_month (int year, unsigned short month);
+
+ gyear_month (int year, unsigned short month,
+ short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+ };
+
+ bool
+ operator== (const gyear_month&amp;, const gyear_month&amp;);
+
+ bool
+ operator!= (const gyear_month&amp;, const gyear_month&amp;);
+}
+ </pre>
+
+
+ <h2><a name="6.13">6.13 <code>time</code> Parser</a></h2>
+
+ <p>The return type of the <code>time_pimpl</code> parser implementation
+ is <code>xml_schema::time</code> which represents hours, minutes,
+ and seconds with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#6.4">Section 6.4, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class time: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ time ();
+
+ time (unsigned short hours, unsigned short minutes, double seconds);
+
+ time (unsigned short hours, unsigned short minutes, double seconds,
+ short zone_hours, short zone_minutes);
+
+ unsigned short
+ hours () const;
+
+ void
+ hours (unsigned short);
+
+ unsigned short
+ minutes () const;
+
+ void
+ minutes (unsigned short);
+
+ double
+ seconds () const;
+
+ void
+ seconds (double);
+ };
+
+ bool
+ operator== (const time&amp;, const time&amp;);
+
+ bool
+ operator!= (const time&amp;, const time&amp;);
+}
+ </pre>
+
+
+ <!-- Error Handling -->
+
+
+ <h1><a name="7">7 Document Parser and Error Handling</a></h1>
+
+ <p>In this chapter we will discuss the <code>xml_schema::document_pimpl</code>
+ type, the error handling mechanisms provided by the mapping, as well
+ as how to reuse a parser after an error has occurred.</p>
+
+ <p>There are four categories of errors that can result from running
+ a parser on an XML instance: system, xml, schema, and application.
+ The system category contains memory allocation and file/stream
+ operation errors. The xml category is for XML parsing and
+ well-formedness checking errors. Similarly, the schema category is
+ for XML Schema validation errors. Finally, the application category
+ is for application logic errors that you may want to propagate
+ from parser implementations to the caller of the parser.
+ </p>
+
+ <p>The C++/Parser mapping supports two methods of reporting errors:
+ using C++ exceptions and with error codes. The method used depends
+ on whether or not you have configured the XSD/e runtime and
+ the generated code with C++ exceptions enabled, as described
+ in <a href="#5.3">Section 5.3, "C++ Exceptions"</a>.</p>
+
+ <h2><a name="7.1">7.1 Document Parser</a></h2>
+
+ <p>The <code>xml_schema::document_pimpl</code> parser is a root parser for
+ the vocabulary. As mentioned in <a href="#3.4">Section 3.4,
+ "Connecting the Parsers Together"</a>, its interface varies depending
+ on the mapping configuration (<a href="#5">Chapter 5, "Mapping
+ Configuration"</a>). When STL and the iostream library are
+ enabled, the <code>xml_schema::document_pimpl</code> class has the
+ following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class parser_base;
+
+ class document_pimpl
+ {
+ public:
+ document_pimpl (parser_base&amp;,
+ const char* root_element_name);
+
+ document_pimpl (parser_base&amp;,
+ const char* root_element_namespace,
+ const char* root_element_name);
+
+ document_pimpl (parser_base&amp;,
+ const std::string&amp; root_element_name);
+
+ document_pimpl (parser_base&amp;,
+ const std::string&amp; root_element_namespace,
+ const std::string&amp; root_element_name);
+
+
+ public:
+ // Parse a local file. The file is accessed with std::ifstream
+ // in binary mode. The std::ios_base::failure exception is used
+ // to report io errors (badbit and failbit) if exceptions are
+ // enabled. Otherwise error codes are used.
+ //
+ void
+ parse (const char* file);
+
+ void
+ parse (const std::string&amp; file);
+
+ // Parse std::istream. std::ios_base::failure exception is used
+ // to report io errors (badbit and failbit) if exceptions are
+ // enabled. Otherwise error codes are used.
+ //
+ void
+ parse (std::istream&amp;);
+
+ // Parse a chunk of input. You can call this function multiple
+ // times with the last call having the last argument true.
+ //
+ void
+ parse (const void* data, size_t size, bool last);
+
+ // Low-level Expat-specific parsing API.
+ //
+ void
+ parse_begin (XML_Parser);
+
+ void
+ parse_end ();
+ };
+}
+ </pre>
+
+ <p>When the use of STL is disabled, the constructors and the <code>parse()</code>
+ function that use <code>std::string</code> in their signatures
+ are not available. When the use of iostream is disabled, the
+ <code>parse()</code> functions that parse a local file and
+ <code>std::istream</code> are not available.</p>
+
+ <p>When support for XML Schema polymorphism is enabled, the
+ overloaded <code>document_pimpl</code> constructors have
+ additional arguments which control polymorphic parsing.
+ For more information refer to <a href="#5.7">Section 5.7,
+ "Support for Polymorphism"</a>.
+ </p>
+
+ <p>The first argument to all overloaded constructors is the
+ parser for the type of the root element. The <code>parser_base</code>
+ class is the base type for all parser skeletons. The second and
+ third arguments to the <code>document_pimpl</code>'s constructors are
+ the root element's name and namespace.</p>
+
+ <p>The <code>parse_begin()</code> and <code>parse_end()</code> functions
+ present a low-level, Expat-specific parsing API for maximum control.
+ A typical use case would look like this (pseudo-code):</p>
+
+ <pre class="c++">
+xxx_pimpl root_p;
+document_pimpl doc_p (root_p, "root");
+
+root_p.pre ();
+doc_p.parse_begin (xml_parser);
+
+while (more_stuff_to_parse)
+{
+ // Call XML_Parse or XML_ParseBuffer:
+ //
+ if (XML_Parse (...) != XML_STATUS_ERROR)
+ break;
+}
+
+doc_p.parse_end ();
+result_type result (root_p.post_xxx ());
+ </pre>
+
+ <p>Note that if your vocabulary use XML namespaces, the
+ <code>XML_ParserCreateNS()</code> functions should be used to create
+ the XML parser. Space (<code>XML_Char (' ')</code>) should be used
+ as a separator (the second argument to <code>XML_ParserCreateNS()</code>).
+ Furthermore, if XML_Parse or XML_ParseBuffer fail, call
+ <code>parse_end()</code> to determine the error which is indicated
+ either via exception or set as an error code.
+ </p>
+
+ <p>The error handling mechanisms employed by the <code>document_pimpl</code>
+ parser are described in <a href="#7.2">Section 7.2, "Exceptions"</a>
+ and <a href="#7.3">Section 7.3, "Error Codes"</a>.</p>
+
+ <h2><a name="7.2">7.2 Exceptions</a></h2>
+
+ <p>When C++ exceptions are used for error reporting, the system
+ errors are mapped to the standard exceptions. The out of memory
+ condition is indicated by throwing an instance
+ of <code>std::bad_alloc</code>. The stream operation errors
+ are reported by throwing an instance of
+ <code>std::ios_base::failure</code>.</p>
+
+ <p>The xml and schema errors are reported by throwing the
+ <code>xml_schema::parser_xml</code> and <code>xml_schema::parser_schema</code>
+ exceptions, respectively. These two exceptions derive from
+ <code>xml_schema::parser_exception</code> which, in turn, derives
+ from <code>std::exception</code>. As a result, you can handle
+ any error from these two categories by either catching
+ <code>std::exception</code>, <code>xml_schema::parser_exception</code>,
+ or individual exceptions. The further down the hierarchy you go
+ the more detailed error information is available to you. The
+ following listing shows the definitions of these exceptions:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class parser_exception: public std::exception
+ {
+ public:
+ unsigned long
+ line () const;
+
+ unsigned long
+ column () const;
+
+ virtual const char*
+ text () const = 0;
+
+ ...
+ };
+
+ std::ostream&amp;
+ operator&lt;&lt; (std::ostream&amp;, const parser_exception&amp;);
+
+
+ typedef &lt;implementation-details> parser_xml_error;
+
+ class parser_xml: public parser_exception
+ {
+ public:
+ parser_xml_error
+ code () const;
+
+ virtual const char*
+ text () const;
+
+ virtual const char*
+ what () const throw ();
+
+ ...
+ };
+
+
+ typedef &lt;implementation-details> parser_schema_error;
+
+ class parser_schema: public parser_exception
+ {
+ public:
+ parser_schema_error
+ code () const;
+
+ virtual const char*
+ text () const;
+
+ virtual const char*
+ what () const throw ();
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>parser_xml_error</code> and <code>parser_schema_error</code>
+ are implementation-specific error code types. The
+ <code>operator&lt;&lt;</code> defined for the <code>parser_exception</code>
+ class simply prints the error description as returned by the
+ <code>text()</code> function. The following example shows
+ how we can catch these exceptions:</p>
+
+ <pre class="c++">
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ // Parse argv[1].
+ }
+ catch (const xml_schema::parser_exception&amp; e)
+ {
+ cout &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": error: " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>Finally, for reporting application errors from parsing callbacks, you
+ can throw any exceptions of your choice. They are propagated to
+ the caller of the parser without any alterations.</p>
+
+ <h2><a name="7.3">7.3 Error Codes</a></h2>
+
+ <p>When C++ exceptions are not available, error codes are used to
+ report error conditions. Each parser skeleton and the root
+ <code>document_pimpl</code> parser have the following member
+ function for querying
+ the error status:</p>
+
+ <pre class="c++">
+xml_schema::parser_error
+_error () const;
+ </pre>
+
+ <p>To handle all possible error conditions, you will need to obtain
+ the error status after calls to: the <code>document_pimpl</code>'s
+ constructor (it performs memory allocations which may fail), the
+ root parser <code>pre()</code> callback, each call to the <code>parse()</code>
+ function, and, finally, the call to the root parser
+ <code>post_*()</code> callback. The definition of
+ <code>xml_schema::parser_error</code> class is presented below:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class sys_error
+ {
+ public:
+ enum value
+ {
+ none,
+ no_memory,
+ open_failed,
+ read_failed,
+ write_failed
+ };
+
+ sys_error (value);
+
+ operator value () const;
+
+ static const char*
+ text (value);
+
+ ...
+ };
+
+ typedef &lt;implementation-details> parser_xml_error;
+ typedef &lt;implementation-details> parser_schema_error;
+
+ class parser_error
+ {
+ public:
+ enum error_type
+ {
+ none,
+ sys,
+ xml,
+ schema,
+ app
+ };
+
+ error_type
+ type () const;
+
+ // Line and column are only available for xml, schema, and
+ // app errors.
+ //
+ unsigned long
+ line () const;
+
+ unsigned long
+ column () const;
+
+ // Returns true if there is an error so that you can write
+ // if (p.error ()) or if (error e = p.error ()).
+ //
+ typedef void (error::*bool_convertible) ();
+ operator bool_convertible () const;
+
+ // system
+ //
+ sys_error
+ sys_code () const;
+
+ const char*
+ sys_text () const;
+
+ // xml
+ //
+ parser_xml_error
+ xml_code () const;
+
+ const char*
+ xml_text () const;
+
+ // schema
+ //
+ parser_schema_error
+ schema_code () const;
+
+ const char*
+ schema_text () const;
+
+ // app
+ //
+ int
+ app_code () const;
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>parser_xml_error</code> and <code>parser_schema_error</code>
+ are implementation-specific error code types. The
+ <code>parser_error</code> class incorporates four categories of errors
+ which you can query by calling the <code>type()</code> function.
+ The following example shows how to handle error conditions with
+ error codes. It is based on the person record example presented
+ in <a href="#3">Chapter 3, "Parser Skeletons"</a>.</p>
+
+ <pre class="c++">
+int
+main (int argc, char* argv[])
+{
+ // Construct the parser.
+ //
+ xml_schema::short_pimpl short_p;
+ xml_schema::string_pimpl string_p;
+
+ gender_pimpl gender_p;
+ person_pimpl person_p;
+ people_pimpl people_p;
+
+ person_p.parsers (string_p, string_p, gender_p, short_p);
+ people_p.parsers (person_p);
+
+ // Parse.
+ //
+ using xml_schema::parser_error;
+ parser_error e;
+
+ do
+ {
+ xml_schema::document_pimpl doc_p (people_p, "people");
+ if (e = doc_p._error ())
+ break;
+
+ people_p.pre ();
+ if (e = people_p._error ())
+ break;
+
+ doc_p.parse (argv[1]);
+ if (e = doc_p._error ())
+ break;
+
+ people_p.post_people ();
+ e = people_p._error ();
+
+ } while (false);
+
+ // Handle errors.
+ //
+ if (e)
+ {
+ switch (e.type ())
+ {
+ case parser_error::sys:
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ": error: " &lt;&lt; e.sys_text () &lt;&lt; endl;
+ break;
+ }
+ case parser_error::xml:
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": error: " &lt;&lt; e.xml_text () &lt;&lt; endl;
+ break;
+ }
+ case parser_error::schema:
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": error: " &lt;&lt; e.schema_text () &lt;&lt; endl;
+ break;
+ }
+ case parser_error::app:
+ {
+ cerr &lt;&lt; argv[1] &lt;&lt; ":" &lt;&lt; e.line () &lt;&lt; ":" &lt;&lt; e.column ()
+ &lt;&lt; ": application error " &lt;&lt; e.app_code () &lt;&lt; endl;
+ break;
+ }
+ }
+ return 1;
+ }
+}
+ </pre>
+
+ <p>The error type for application errors is <code>int</code> with
+ the value <code>0</code> indicated the absence of error. You can
+ set the application error by calling the <code>_app_error()</code>
+ function inside a parser callback. For example, if it was invalid to
+ have a person younger than 18 in our people catalog, then we could
+ have implemented this check as follows: </p>
+
+ <pre class="c++">
+class person_pimpl: public person_pskel
+{
+public:
+ virtual void
+ age (short a)
+ {
+ if (a &lt; 18)
+ _app_error (1);
+ }
+
+ ...
+};
+ </pre>
+
+ <p>You can also set a system error by calling the <code>_sys_error()</code>
+ function inside a parser callback. This function has one argument of type
+ <code>xml_schema::sys_error</code> which was presented above. For
+ example:</p>
+
+ <pre class="c++">
+class person_pimpl: public person_pskel
+{
+public:
+ virtual void
+ pre ()
+ {
+ p_ = new person ();
+
+ if (p_ == 0)
+ _sys_error (xml_schema::sys_error::no_memory);
+ }
+
+ ...
+
+private:
+ person* p_;
+};
+ </pre>
+
+
+ <h2><a name="7.4">7.4 Reusing Parsers after an Error</a></h2>
+
+ <p>After a successful execution a parser returns into the initial
+ state and can be used to parse another document without any
+ extra actions. On the other hand, if an error occurred during
+ parsing and you would like to reuse the parser to parse another
+ document, you need to explicitly reset it into the initial
+ state as shown in the following code fragment:</p>
+
+ <pre class="c++">
+int
+main ()
+{
+ ...
+
+ std::vector&lt;std::string> files = ...
+
+ xml_schema::document_pimpl doc_p (people_p, "people");
+
+ for (size_t i = 0; i &lt; files.size (); ++i)
+ {
+ try
+ {
+ people_p.pre ();
+ doc_p.parse (files[i]);
+ people_p.post_people ();
+ }
+ catch (const xml_schema::parser_exception&amp;)
+ {
+ doc_p.reset ();
+ }
+ }
+}
+ </pre>
+
+ <p>If you do not need to reuse parsers after an error for example
+ because your application terminates or you create a new parser
+ instance in such situations, then you can avoid generating
+ parser reset code by specifying the <code>--suppress-reset</code>
+ XSD/e compiler option.</p>
+
+ <p>Your individual parser implementations may also require extra
+ actions in order to bring them into a usable state after an
+ error. To accomplish this you can override the <code>_reset()</code>
+ virtual function as shown below. Notice that when you override the
+ <code>_reset()</code> function in your implementation, you should
+ always call the base skeleton version to allow it to reset
+ its state:</p>
+
+<pre class="c++">
+class person_pimpl: public person_pskel
+{
+public:
+ virtual void
+ pre ()
+ {
+ p_ = new person ();
+ }
+
+ virtual void
+ _reset ()
+ {
+ person_pskel::_reset ();
+ delete p_;
+ p_ = 0;
+ }
+
+ ...
+
+private:
+ person* p_;
+};
+ </pre>
+
+ <p>Note also that the <code>_reset()</code> mechanism is used only when
+ an error has occurred. To make sure that your parser implementations
+ arrive at the initial state during successful execution, use the
+ initialization (<code>pre()</code> and <code>_pre()</code>) and
+ finalization (<code>post_*()</code> and <code>_post()</code>)
+ callbacks.</p>
+
+ <!-- Appendix A -->
+
+
+ <h1><a name="A">Appendix A &mdash; Supported XML Schema Constructs</a></h1>
+
+ <p>The Embedded C++/Parser mapping supports validation of the following
+ W3C XML Schema constructs in the generated code.</p>
+
+ <!-- border="1" is necessary for html2ps -->
+ <table id="features" border="1">
+ <tr><th>Construct</th><th>Notes</th></tr>
+ <tr><th colspan="2">Structure</th></tr>
+
+ <tr><td>element</td><td></td></tr>
+ <tr><td>attribute</td><td></td></tr>
+
+ <tr><td>any</td><td></td></tr>
+ <tr><td>anyAttribute</td><td></td></tr>
+
+ <tr><td>all</td><td></td></tr>
+ <tr><td>sequence</td><td></td></tr>
+ <tr><td>choice</td><td></td></tr>
+
+ <tr><td>complex type, empty content</td><td></td></tr>
+ <tr><td>complex type, mixed content</td><td></td></tr>
+ <tr><td>complex type, simple content extension</td><td></td></tr>
+ <tr><td>complex type, simple content restriction</td><td></td></tr>
+ <tr><td>complex type, complex content extension</td><td></td></tr>
+ <tr><td>complex type, complex content restriction</td><td></td></tr>
+
+ <tr><td>list</td><td></td></tr>
+
+ <tr><th colspan="2">Facets</th></tr>
+
+ <tr><td>length</td><td>String-based types.</td></tr>
+ <tr><td>minLength</td><td>String-based types.</td></tr>
+ <tr><td>maxLength</td><td>String-based types.</td></tr>
+ <tr><td>pattern</td><td>String-based types.</td></tr>
+ <tr><td>whiteSpace</td><td>String-based types.</td></tr>
+ <tr><td>enumeration</td><td>String-based types.</td></tr>
+
+ <tr><td>minExclusive</td><td>Integer and floating-point types.</td></tr>
+ <tr><td>minInclusive</td><td>Integer and floating-point types.</td></tr>
+ <tr><td>maxExclusive</td><td>Integer and floating-point types.</td></tr>
+ <tr><td>maxInclusive</td><td>Integer and floating-point types.</td></tr>
+
+ <tr><th colspan="2">Datatypes</th></tr>
+
+ <tr><td>byte</td><td></td></tr>
+ <tr><td>unsignedByte</td><td></td></tr>
+ <tr><td>short</td><td></td></tr>
+ <tr><td>unsignedShort</td><td></td></tr>
+ <tr><td>int</td><td></td></tr>
+ <tr><td>unsignedInt</td><td></td></tr>
+ <tr><td>long</td><td></td></tr>
+ <tr><td>unsignedLong</td><td></td></tr>
+ <tr><td>integer</td><td></td></tr>
+ <tr><td>nonPositiveInteger</td><td></td></tr>
+ <tr><td>nonNegativeInteger</td><td></td></tr>
+ <tr><td>positiveInteger</td><td></td></tr>
+ <tr><td>negativeInteger</td><td></td></tr>
+
+ <tr><td>boolean</td><td></td></tr>
+
+ <tr><td>float</td><td></td></tr>
+ <tr><td>double</td><td></td></tr>
+ <tr><td>decimal</td><td></td></tr>
+
+ <tr><td>string</td><td></td></tr>
+ <tr><td>normalizedString</td><td></td></tr>
+ <tr><td>token</td><td></td></tr>
+ <tr><td>Name</td><td></td></tr>
+ <tr><td>NMTOKEN</td><td></td></tr>
+ <tr><td>NCName</td><td></td></tr>
+ <tr><td>language</td><td></td></tr>
+ <tr><td>anyURI</td><td></td></tr>
+
+ <tr><td>ID</td><td>Identity constraint is not enforced.</td></tr>
+ <tr><td>IDREF</td><td>Identity constraint is not enforced.</td></tr>
+
+ <tr><td>NMTOKENS</td><td></td></tr>
+ <tr><td>IDREFS</td><td>Identity constraint is not enforced.</td></tr>
+
+ <tr><td>QName</td><td></td></tr>
+
+ <tr><td>base64Binary</td><td></td></tr>
+ <tr><td>hexBinary</td><td></td></tr>
+
+ <tr><td>date</td><td></td></tr>
+ <tr><td>dateTime</td><td></td></tr>
+ <tr><td>duration</td><td></td></tr>
+ <tr><td>gDay</td><td></td></tr>
+ <tr><td>gMonth</td><td></td></tr>
+ <tr><td>gMonthDay</td><td></td></tr>
+ <tr><td>gYear</td><td></td></tr>
+ <tr><td>gYearMonth</td><td></td></tr>
+ <tr><td>time</td><td></td></tr>
+ </table>
+
+ </div>
+</div>
+
+
+</body>
+</html>
diff --git a/doc/cxx/parser/guide/makefile b/doc/cxx/parser/guide/makefile
new file mode 100644
index 0000000..48c37d9
--- /dev/null
+++ b/doc/cxx/parser/guide/makefile
@@ -0,0 +1,48 @@
+# file : doc/cxx/parser/guide/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2006-2011 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+default := $(out_base)/
+dist := $(out_base)/.dist
+dist-win := $(out_base)/.dist-win
+cleandoc := $(out_base)/.cleandoc
+
+# Build.
+#
+$(default): $(out_base)/cxx-parser-e-guide.ps \
+ $(out_base)/cxx-parser-e-guide.pdf
+
+
+$(out_base)/cxx-parser-e-guide.ps: $(src_base)/index.xhtml \
+ $(src_base)/figure-1.png \
+ $(src_base)/guide.html2ps \
+ | $(out_base)/.
+ $(call message,html2ps $<,html2ps -f $(src_base)/guide.html2ps -o $@ $<)
+
+$(out_base)/cxx-parser-e-guide.pdf: $(out_base)/cxx-parser-e-guide.ps | $(out_base)/.
+ $(call message,ps2pdf $<,ps2pdf14 $< $@)
+
+# Dist.
+#
+$(dist): path := $(subst $(src_root)/,,$(src_base))
+$(dist): $(out_base)/cxx-parser-e-guide.ps $(out_base)/cxx-parser-e-guide.pdf
+ $(call install-data,$(src_base)/figure-1.png,$(dist_prefix)/$(path)/figure-1.png)
+ $(call install-data,$(src_base)/index.xhtml,$(dist_prefix)/$(path)/index.xhtml)
+ $(call install-data,$(out_base)/cxx-parser-e-guide.ps,$(dist_prefix)/$(path)/cxx-parser-e-guide.ps)
+ $(call install-data,$(out_base)/cxx-parser-e-guide.pdf,$(dist_prefix)/$(path)/cxx-parser-e-guide.pdf)
+
+$(dist-win): $(dist)
+
+
+# Clean
+#
+$(cleandoc):
+ $(call message,rm $$1,rm -f $$1,$(out_base)/cxx-parser-e-guide.ps)
+ $(call message,rm $$1,rm -f $$1,$(out_base)/cxx-parser-e-guide.pdf)
+
+# How to.
+#
+$(call include,$(bld_root)/install.make)
diff --git a/doc/cxx/serializer/guide/figure-1.png b/doc/cxx/serializer/guide/figure-1.png
new file mode 100644
index 0000000..8700758
--- /dev/null
+++ b/doc/cxx/serializer/guide/figure-1.png
Binary files differ
diff --git a/doc/cxx/serializer/guide/figure-1.svg b/doc/cxx/serializer/guide/figure-1.svg
new file mode 100644
index 0000000..68790f9
--- /dev/null
+++ b/doc/cxx/serializer/guide/figure-1.svg
@@ -0,0 +1,372 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ sodipodi:docbase="/home/boris/tmp"
+ sodipodi:docname="figure-1.svg"
+ inkscape:export-filename="/home/boris/tmp/figure-1.png"
+ inkscape:export-xdpi="76.195885"
+ inkscape:export-ydpi="76.195885"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lend"
+ style="overflow:visible;">
+ <path
+ id="path2934"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.8) rotate(180) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Dot_l"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Dot_l"
+ style="overflow:visible">
+ <path
+ id="path2875"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+ transform="scale(0.8) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path2928"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Dot_m"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Dot_m"
+ style="overflow:visible">
+ <path
+ id="path2872"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+ transform="scale(0.4) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path2937"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path2910"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.98994949"
+ inkscape:cx="425.58704"
+ inkscape:cy="699.39127"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1280"
+ inkscape:window-height="991"
+ inkscape:window-x="140"
+ inkscape:window-y="42"
+ showgrid="false" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <g
+ id="g3902">
+ <rect
+ y="194.64178"
+ x="24.142784"
+ height="106.2678"
+ width="149.70432"
+ id="rect1872"
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.29799986;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3038"
+ y="219.99649"
+ x="28.284279"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Monospace"
+ xml:space="preserve"><tspan
+ y="219.99649"
+ x="28.284279"
+ id="tspan3064"
+ sodipodi:role="line">class people_simpl</tspan><tspan
+ y="236.24649"
+ x="28.284279"
+ id="tspan3066"
+ sodipodi:role="line">{</tspan><tspan
+ y="252.49649"
+ x="28.284279"
+ id="tspan3068"
+ sodipodi:role="line"> void </tspan><tspan
+ y="268.74649"
+ x="28.284279"
+ id="tspan3070"
+ sodipodi:role="line"> person ();</tspan><tspan
+ y="284.99649"
+ x="28.284279"
+ id="tspan3072"
+ sodipodi:role="line">};</tspan></text>
+ </g>
+ <rect
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:8.33343506;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect5750"
+ width="149.4976"
+ height="246.47226"
+ x="264.03558"
+ y="124.53955" />
+ <text
+ xml:space="preserve"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;font-family:Monospace"
+ x="269.5889"
+ y="148.27567"
+ id="text5752"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan5900"
+ x="269.5889"
+ y="148.27567">class person_simpl</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5902"
+ x="269.5889"
+ y="161.27567">{</tspan><tspan
+ id="tspan2235"
+ sodipodi:role="line"
+ x="269.5889"
+ y="174.27567"> void</tspan><tspan
+ id="tspan2237"
+ sodipodi:role="line"
+ x="269.5889"
+ y="187.27567"> pre ();</tspan><tspan
+ id="tspan2239"
+ sodipodi:role="line"
+ x="269.5889"
+ y="200.27567" /><tspan
+ sodipodi:role="line"
+ id="tspan5904"
+ x="269.5889"
+ y="213.27567"> string</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5906"
+ x="269.5889"
+ y="226.27567"> first_name ();</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5908"
+ x="269.5889"
+ y="239.27567" /><tspan
+ sodipodi:role="line"
+ id="tspan5910"
+ x="269.5889"
+ y="252.27567"> string</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5912"
+ x="269.5889"
+ y="265.27567"> last_name ();</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5914"
+ x="269.5889"
+ y="278.27567" /><tspan
+ sodipodi:role="line"
+ id="tspan5916"
+ x="269.5889"
+ y="291.27567"> void</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5918"
+ x="269.5889"
+ y="304.27567"> gender ();</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5920"
+ x="269.5889"
+ y="317.27567" /><tspan
+ sodipodi:role="line"
+ id="tspan5922"
+ x="269.5889"
+ y="330.27567"> short</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5930"
+ x="269.5889"
+ y="343.27567"> age ();</tspan><tspan
+ sodipodi:role="line"
+ id="tspan5932"
+ x="269.5889"
+ y="356.27567">};</tspan></text>
+ <g
+ id="g3845">
+ <rect
+ y="77.741814"
+ x="506.28357"
+ height="99.610825"
+ width="151.1286"
+ id="rect5955"
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <flowRoot
+ transform="translate(-5.050762,12.10153)"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ id="flowRoot5957"
+ xml:space="preserve"><flowRegion
+ id="flowRegion5959"><rect
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ y="74.534515"
+ x="516.18793"
+ height="88.893425"
+ width="143.44167"
+ id="rect5961" /></flowRegion><flowPara
+ id="flowPara5965">class string_simpl</flowPara><flowPara
+ id="flowPara5967">{</flowPara><flowPara
+ id="flowPara5969"> void</flowPara><flowPara
+ id="flowPara5971"> pre (string);</flowPara><flowPara
+ id="flowPara5973">};</flowPara><flowPara
+ id="flowPara5975" /></flowRoot> </g>
+ <g
+ id="g3857">
+ <rect
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect5977"
+ width="151.1286"
+ height="99.610825"
+ x="506.28357"
+ y="316.15808" />
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot5979"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ transform="translate(-5.050761,250.5178)"
+ inkscape:export-filename="/tmp/figure-1.png"
+ inkscape:export-xdpi="546.53815"
+ inkscape:export-ydpi="546.53815"><flowRegion
+ id="flowRegion5981"><rect
+ id="rect5983"
+ width="143.44167"
+ height="88.893425"
+ x="516.18793"
+ y="74.534515"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace" /></flowRegion><flowPara
+ id="flowPara5985">class short_simpl</flowPara><flowPara
+ id="flowPara5987">{</flowPara><flowPara
+ id="flowPara5989"> void</flowPara><flowPara
+ id="flowPara5991"> pre (short);</flowPara><flowPara
+ id="flowPara5993">};</flowPara><flowPara
+ id="flowPara5995" /></flowRoot> </g>
+ <g
+ id="g3869">
+ <rect
+ style="fill:#c5ddf8;fill-opacity:1;fill-rule:evenodd;stroke:#c5ddf8;stroke-width:5.69227886;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect6023"
+ width="151.1286"
+ height="99.610825"
+ x="505.7785"
+ y="196.93977" />
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot6025"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace"
+ transform="translate(-5.555838,129.2792)"><flowRegion
+ id="flowRegion6027"><rect
+ id="rect6029"
+ width="143.44167"
+ height="88.893425"
+ x="516.18793"
+ y="74.534515"
+ style="font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Monospace" /></flowRegion><flowPara
+ id="flowPara6031">class gender_simpl</flowPara><flowPara
+ id="flowPara6033">{</flowPara><flowPara
+ id="flowPara6035"> void</flowPara><flowPara
+ id="flowPara6037"> pre ();</flowPara><flowPara
+ id="flowPara6039">};</flowPara><flowPara
+ id="flowPara6041" /></flowRoot> </g>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 129.28571,265.21932 L 214.28572,264.86218 L 215,185.3979 L 277.85714,184.50504"
+ id="path2267"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-mid:none;marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 400,222.36218 L 461.07144,222.36217 L 460.89286,143.79075 L 520.71429,143.79075"
+ id="path3240"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 370,301.64789 L 481.78571,301.29075 L 481.60714,262.8979 L 520,262.36218"
+ id="path3242"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);marker-end:url(#Arrow1Lend);stroke-opacity:1;display:inline"
+ d="M 345.71429,340.93361 L 461.07143,341.29075 L 461.25,383.25504 L 520.71429,383.07647"
+ id="path3244"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Dot_l);stroke-opacity:1;display:inline"
+ d="M 393.57143,261.64789 L 461.19314,261.78285 L 461.13464,222.52186"
+ id="path3250"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="ccc" />
+ </g>
+</svg>
diff --git a/doc/cxx/serializer/guide/guide.html2ps b/doc/cxx/serializer/guide/guide.html2ps
new file mode 100644
index 0000000..9e5fc78
--- /dev/null
+++ b/doc/cxx/serializer/guide/guide.html2ps
@@ -0,0 +1,65 @@
+@html2ps {
+ option {
+ toc: hb;
+ colour: 1;
+ hyphenate: 1;
+ titlepage: 1;
+ }
+
+ datefmt: "%B %Y";
+
+ titlepage {
+ content: "
+<div align=center>
+ <h1><big>Embedded C++/Serializer Mapping</big></h1>
+ <h1><big>Getting Started Guide</big></h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+ <h1>&nbsp;</h1>
+</div>
+ <p>Copyright &copy; 2005-2011 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href='http://www.codesynthesis.com/licenses/fdl-1.2.txt'>GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml'>XHTML</a>,
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/cxx-serializer-e-guide.pdf'>PDF</a>, and
+ <a href='http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/cxx-serializer-e-guide.ps'>PostScript</a>.</p>";
+ }
+
+ toc {
+ indent: 2em;
+ }
+
+ header {
+ odd-right: $H;
+ even-left: $H;
+ }
+
+ footer {
+ odd-left: $D;
+ odd-center: $T;
+ odd-right: $N;
+
+ even-left: $N;
+ even-center: $T;
+ even-right: $D;
+ }
+}
+
+body {
+ font-size: 12pt;
+ text-align: justify;
+}
+
+pre {
+ font-size: 10pt;
+}
diff --git a/doc/cxx/serializer/guide/index.xhtml b/doc/cxx/serializer/guide/index.xhtml
new file mode 100644
index 0000000..34ddbe1
--- /dev/null
+++ b/doc/cxx/serializer/guide/index.xhtml
@@ -0,0 +1,6542 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<head>
+ <title>Embedded C++/Serializer Mapping Getting Started Guide</title>
+
+ <meta name="copyright" content="&copy; 2005-2011 Code Synthesis Tools CC"/>
+ <meta name="keywords" content="xsd,xml,schema,c++,mapping,data,binding,serialize,create,write,validation,embedded,mobile"/>
+ <meta name="description" content="Embedded C++/Serializer Mapping Getting Started Guide"/>
+
+ <link rel="stylesheet" type="text/css" href="../../../default.css" />
+
+<style type="text/css">
+ pre {
+ padding : 0 0 0 0em;
+ margin : 0em 0em 0em 0;
+
+ font-size : 102%
+ }
+
+ body {
+ min-width: 48em;
+ }
+
+ h1 {
+ font-weight: bold;
+ font-size: 200%;
+ line-height: 1.2em;
+ }
+
+ h2 {
+ font-weight : bold;
+ font-size : 150%;
+
+ padding-top : 0.8em;
+ }
+
+ h3 {
+ font-size : 140%;
+ padding-top : 0.8em;
+ }
+
+ /* Adjust indentation for three levels. */
+ #container {
+ max-width: 48em;
+ }
+
+ #content {
+ padding: 0 0.1em 0 4em;
+ /*background-color: red;*/
+ }
+
+ #content h1 {
+ margin-left: -2.06em;
+ }
+
+ #content h2 {
+ margin-left: -1.33em;
+ }
+
+ /* Title page */
+
+ #titlepage {
+ padding: 2em 0 1em 0;
+ border-bottom: 1px solid black;
+ }
+
+ #titlepage .title {
+ font-weight: bold;
+ font-size: 200%;
+ text-align: center;
+ }
+
+ #titlepage #first-title {
+ padding: 1em 0 0.4em 0;
+ }
+
+ #titlepage #second-title {
+ padding: 0.4em 0 2em 0;
+ }
+
+ /* Lists */
+ ul.list li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+ }
+
+ ol.steps {
+ padding-left : 1.8em;
+ }
+
+ ol.steps li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+ }
+
+
+ div.img {
+ text-align: center;
+ padding: 2em 0 2em 0;
+ }
+
+ /* */
+ dl dt {
+ padding : 0.8em 0 0 0;
+ }
+
+ /* TOC */
+ table.toc {
+ border-style : none;
+ border-collapse : separate;
+ border-spacing : 0;
+
+ margin : 0.2em 0 0.2em 0;
+ padding : 0 0 0 0;
+ }
+
+ table.toc tr {
+ padding : 0 0 0 0;
+ margin : 0 0 0 0;
+ }
+
+ table.toc * td, table.toc * th {
+ border-style : none;
+ margin : 0 0 0 0;
+ vertical-align : top;
+ }
+
+ table.toc * th {
+ font-weight : normal;
+ padding : 0em 0.1em 0em 0;
+ text-align : left;
+ white-space : nowrap;
+ }
+
+ table.toc * table.toc th {
+ padding-left : 1em;
+ }
+
+ table.toc * td {
+ padding : 0em 0 0em 0.7em;
+ text-align : left;
+ }
+
+ /* Built-in table */
+ #builtin {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+ }
+
+ #builtin th, #builtin td {
+ border: 1px solid;
+ padding : 0.9em 0.9em 0.7em 0.9em;
+ }
+
+ #builtin th {
+ background : #cde8f6;
+ }
+
+ #builtin td {
+ text-align: left;
+ }
+
+ /* XML Schema features table. */
+ #features {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+ }
+
+ #features th, #features td {
+ border: 1px solid;
+ padding : 0.6em 0.6em 0.6em 0.6em;
+ }
+
+ #features th {
+ background : #cde8f6;
+ }
+
+ #features td {
+ text-align: left;
+ }
+</style>
+
+
+</head>
+
+<body>
+<div id="container">
+ <div id="content">
+
+ <div class="noprint">
+
+ <div id="titlepage">
+ <div class="title" id="first-title">Embedded C++/Serializer Mapping</div>
+ <div class="title" id="second-title">Getting Started Guide</div>
+
+ <p>Copyright &copy; 2005-2011 CODE SYNTHESIS TOOLS CC</p>
+
+ <p>Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href="http://www.codesynthesis.com/licenses/fdl-1.2.txt">GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </p>
+
+ <p>This document is available in the following formats:
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/index.xhtml">XHTML</a>,
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/cxx-serializer-e-guide.pdf">PDF</a>, and
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/cxx/serializer/guide/cxx-serializer-e-guide.ps">PostScript</a>.</p>
+
+ </div>
+
+ <h1>Table of Contents</h1>
+
+ <table class="toc">
+ <tr>
+ <th></th><td><a href="#0">Preface</a>
+ <table class="toc">
+ <tr><th></th><td><a href="#0.1">About This Document</a></td></tr>
+ <tr><th></th><td><a href="#0.2">More Information</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>1</th><td><a href="#1">Introduction</a>
+ <table class="toc">
+ <tr><th>1.1</th><td><a href="#1.1">Mapping Overview</a></td></tr>
+ <tr><th>1.2</th><td><a href="#1.2">Benefits</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>2</th><td><a href="#2">Hello World Example</a>
+ <table class="toc">
+ <tr><th>2.1</th><td><a href="#2.1">Writing Schema</a></td></tr>
+ <tr><th>2.2</th><td><a href="#2.2">Translating Schema to C++</a></td></tr>
+ <tr><th>2.3</th><td><a href="#2.3">Implementing Application Logic</a></td></tr>
+ <tr><th>2.4</th><td><a href="#2.4">Compiling and Running</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>3</th><td><a href="#3">Serializer Skeletons</a>
+ <table class="toc">
+ <tr><th>3.1</th><td><a href="#3.1">Implementing the Gender Serializer</a></td></tr>
+ <tr><th>3.2</th><td><a href="#3.2">Implementing the Person Serializer</a></td></tr>
+ <tr><th>3.3</th><td><a href="#3.3">Implementing the People Serializer</a></td></tr>
+ <tr><th>3.4</th><td><a href="#3.4">Connecting the Serializers Together</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>4</th><td><a href="#4">Type Maps</a>
+ <table class="toc">
+ <tr><th>4.1</th><td><a href="#4.1">Object Model</a></td></tr>
+ <tr><th>4.2</th><td><a href="#4.2">Type Map File Format</a></td></tr>
+ <tr><th>4.3</th><td><a href="#4.3">Serializer Implementations</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>5</th><td><a href="#5">Serializer Callbacks</a>
+ <table class="toc">
+ <tr><th>5.1</th><td><a href="#5.1">Optional Callback</a></td></tr>
+ <tr><th>5.2</th><td><a href="#5.2">Sequence Callback</a></td></tr>
+ <tr><th>5.3</th><td><a href="#5.3">Choice Callback</a></td></tr>
+ <tr><th>5.4</th><td><a href="#5.4">Element Wildcard Callbacks</a></td></tr>
+ <tr><th>5.5</th><td><a href="#5.5">Attribute Wildcard Callbacks</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>6</th><td><a href="#6">Mapping Configuration</a>
+ <table class="toc">
+ <tr><th>6.1</th><td><a href="#6.1">Standard Template Library</a></td></tr>
+ <tr><th>6.2</th><td><a href="#6.2">Input/Output Stream Library</a></td></tr>
+ <tr><th>6.3</th><td><a href="#6.3">C++ Exceptions</a></td></tr>
+ <tr><th>6.4</th><td><a href="#6.4">XML Schema Validation</a></td></tr>
+ <tr><th>6.5</th><td><a href="#6.5">64-bit Integer Type</a></td></tr>
+ <tr><th>6.6</th><td><a href="#6.6">Serializer Reuse</a></td></tr>
+ <tr><th>6.7</th><td><a href="#6.7">Support for Polymorphism</a></td></tr>
+ <tr><th>6.8</th><td><a href="#6.8">Custom Allocators</a></td></tr>
+ <tr><th>6.9</th><td><a href="#6.9">A Minimal Example</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>7</th><td><a href="#7">Built-In XML Schema Type Serializers</a>
+ <table class="toc">
+ <tr><th>7.1</th><td><a href="#7.1">Floating-Point Type Serializers</a></td></tr>
+ <tr><th>7.2</th><td><a href="#7.2">String-Based Type Serializers</a></td></tr>
+ <tr><th>7.3</th><td><a href="#7.3"><code>QName</code> Serializer</a></td></tr>
+ <tr><th>7.4</th><td><a href="#7.4"><code>NMTOKENS</code> and <code>IDREFS</code> Serializers</a></td></tr>
+ <tr><th>7.5</th><td><a href="#7.5"><code>base64Binary</code> and <code>hexBinary</code> Serializers</a></td></tr>
+ <tr><th>7.6</th><td><a href="#7.6">Time Zone Representation</a></td></tr>
+ <tr><th>7.7</th><td><a href="#7.7"><code>date</code> Serializer</a></td></tr>
+ <tr><th>7.8</th><td><a href="#7.8"><code>dateTime</code> Serializer</a></td></tr>
+ <tr><th>7.9</th><td><a href="#7.9"><code>duration</code> Serializer</a></td></tr>
+ <tr><th>7.10</th><td><a href="#7.10"><code>gDay</code> Serializer</a></td></tr>
+ <tr><th>7.11</th><td><a href="#7.11"><code>gMonth</code> Serializer</a></td></tr>
+ <tr><th>7.12</th><td><a href="#7.12"><code>gMonthDay</code> Serializer</a></td></tr>
+ <tr><th>7.13</th><td><a href="#7.13"><code>gYear</code> Serializer</a></td></tr>
+ <tr><th>7.14</th><td><a href="#7.14"><code>gYearMonth</code> Serializer</a></td></tr>
+ <tr><th>7.15</th><td><a href="#7.15"><code>time</code> Serializer</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th>8</th><td><a href="#8">Document Serializer and Error Handling</a>
+ <table class="toc">
+ <tr><th>8.1</th><td><a href="#8.1">Document Serializer</a></td></tr>
+ <tr><th>8.2</th><td><a href="#8.2">Exceptions</a></td></tr>
+ <tr><th>8.3</th><td><a href="#8.3">Error Codes</a></td></tr>
+ <tr><th>8.4</th><td><a href="#8.4">Reusing Serializers after an Error</a></td></tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr>
+ <th></th><td><a href="#A">Appendix A &mdash; Supported XML Schema Constructs</a></td>
+ </tr>
+
+ </table>
+ </div>
+
+ <h1><a name="0">Preface</a></h1>
+
+ <h2><a name="0.1">About This Document</a></h2>
+
+ <p>The goal of this document is to provide you with an
+ understanding of the C++/Serializer programming model and allow you
+ to efficiently evaluate XSD/e against your project's technical
+ requirements. As such, this document is intended for embedded
+ C++ developers and software architects who are looking for an
+ embedded XML processing solution. Prior experience with XML
+ and C++ is required to understand this document. Basic
+ understanding of XML Schema is advantageous but not expected
+ or required.
+ </p>
+
+
+ <h2><a name="0.2">More Information</a></h2>
+
+ <p>Beyond this guide, you may also find the following sources of
+ information useful:</p>
+
+ <ul class="list">
+ <li><a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a></li>
+
+ <li>The <code>INSTALL</code> file in the XSD/e distribution provides
+ build instructions for various platforms.</li>
+
+ <li>The <code>examples/cxx/serializer/</code> directory in the XSD/e
+ distribution contains a collection of examples and a README
+ file with an overview of each example.</li>
+
+ <li>The <a href="http://www.codesynthesis.com/mailman/listinfo/xsde-users">xsde-users</a>
+ mailing list is the place to ask technical questions about XSD/e and the
+ Embedded C++/Serializer mapping. Furthermore, the
+ <a href="http://www.codesynthesis.com/pipermail/xsde-users/">archives</a>
+ may already have answers to some of your questions.</li>
+
+ </ul>
+
+ <!-- Introduction -->
+
+ <h1><a name="1">1 Introduction</a></h1>
+
+ <p>Welcome to CodeSynthesis XSD/e and the Embedded C++/Serializer mapping.
+ XSD/e is a dependency-free W3C XML Schema to C++ compiler for mobile,
+ embedded, and light-weight applications. Embedded C++/Serializer is an
+ XML Schema to C++ mapping that represents an XML vocabulary as a set of
+ serializer skeletons which you can implement to perform XML serialization
+ as required by your application logic.
+ </p>
+
+ <h2><a name="1.1">1.1 Mapping Overview</a></h2>
+
+ <p>The Embedded C++/Serializer mapping provides event-driven,
+ stream-oriented XML serialization, XML Schema validation,
+ and C++ data binding. It was specifically designed and
+ optimized for mobile and embedded systems where hardware
+ constraints require high efficiency and economical use of
+ resources. As a result, the generated serializers are 2-10
+ times faster than general-purpose validating XML serializers
+ while at the same time maintaining extremely low static and
+ dynamic memory footprints. For example, a validating serializer
+ executable can be as small as 60KB in size. The size can be
+ further reduced by disabling support for XML Schema validation.
+ </p>
+
+ <p>The generated code and the runtime library are also highly-portable
+ and, in their minimal configuration, can be used without STL, RTTI,
+ iostream, C++ exceptions, and C++ templates.</p>
+
+ <p>To speed up application development, the C++/Serializer mapping
+ can be instructed to generate sample serializer implementations
+ and a test driver which can then be filled with the application
+ logic code. The mapping also provides a wide range of
+ mechanisms for controlling and customizing the generated code.</p>
+
+ <p>The next chapter shows how to create a simple application
+ that uses the Embedded C++/Serializer mapping to validate
+ and serialize simple data to an XML document. The following
+ chapters describe the Embedded C++/Serializer mapping in more
+ detail.</p>
+
+ <h2><a name="1.2">1.2 Benefits</a></h2>
+
+ <p>Traditional XML serialization APIs such as Document Object Model (DOM)
+ or XML Writer as well as general-purpose XML Schema validators have
+ a number of drawbacks that make them less suitable for creating
+ mobile and embedded XML processing applications. These drawbacks
+ include:
+ </p>
+
+ <ul class="list">
+ <li>Text-based representation results in inefficient use of
+ resources.</li>
+
+ <li>Extra validation code that is not used by the application.</li>
+
+ <li>Generic representation of XML in terms of elements, attributes,
+ and text forces an application developer to write a substantial
+ amount of bridging code that identifies and transforms pieces
+ of information produced by the application logic to the text
+ encoding used in XML.</li>
+
+ <li>Resulting applications are hard to debug, change, and
+ maintain.</li>
+ </ul>
+
+ <p>In contrast, statically-typed, vocabulary-specific serializer
+ skeletons produced by the Embedded C++/Serializer mapping use
+ native data types (for example, integers are passed as
+ integers, not as text) and include validation code only for
+ XML Schema constructs that are used in the application. This
+ results in efficient use of resources and compact object code.</p>
+
+ <p>Furthermore, the serializer skeletons allow you to operate in your
+ domain terms instead of the generic elements, attributes, and
+ text. Automatic code generation frees you for more
+ interesting tasks (such as doing something useful with the
+ information that needs to be stored in XML) and
+ minimizes the effort needed to adapt your applications to changes
+ in the document structure. To summarize, the C++/Serializer mapping
+ has the following key advantages over generic XML serialization APIs:</p>
+
+ <ul class="list">
+ <li><b>Ease of use.</b> The generated code hides all the complexity
+ associated with recreating the document structure, maintaining the
+ state, and converting the data from types suitable for
+ manipulation by the application logic to the text representation
+ used in XML.</li>
+
+ <li><b>Natural representation.</b> The generated serializer skeletons
+ implement serializer callbacks as virtual functions with names
+ corresponding to elements and attributes in XML. As a result,
+ you serialize the data using your domain vocabulary instead
+ of generic elements, attributes, and text.
+ </li>
+
+ <li><b>Concise code.</b> With a separate serializer skeleton for each
+ XML Schema type, the application implementation is simpler
+ and thus easier to read and understand.</li>
+
+ <li><b>Safety.</b> The data is passed by serializer callbacks as
+ statically typed objects. The serializer callbacks themselves
+ are virtual functions. This helps catch programming errors
+ at compile-time rather than at runtime.</li>
+
+ <li><b>Maintainability.</b> Automatic code generation minimizes the
+ effort needed to adapt the application to changes in the
+ document structure. With static typing, the C++ compiler
+ can pin-point the places in the application code that need to be
+ changed.</li>
+
+ <li><b>Efficiency.</b> The generated serializer skeletons use native
+ data types and combine validation and data-to-text
+ conversion in a single step. This makes them much more efficient
+ than traditional architectures with separate stages for validation
+ and data conversion.</li>
+ </ul>
+
+
+ <!-- Hello World Example -->
+
+
+ <h1><a name="2">2 Hello World Example</a></h1>
+
+ <p>In this chapter we will examine how to create a very simple XML
+ document using the XSD/e-generated C++/Serializer skeletons.
+
+ All the code presented in this chapter is based on the <code>hello</code>
+ example which can be found in the <code>examples/cxx/serializer/</code>
+ directory of the XSD/e distribution.</p>
+
+ <h2><a name="2.1">2.1 Writing Schema</a></h2>
+
+ <p>First, we need to get an idea about the structure of the XML
+ document that we are going to create. The sample XML that
+ we will try to produce with our Hello application looks like
+ this:</p>
+
+ <pre class="xml">
+&lt;hello>
+
+ &lt;greeting>Hello&lt;/greeting>
+
+ &lt;name>sun&lt;/name>
+ &lt;name>moon&lt;/name>
+ &lt;name>world&lt;/name>
+
+&lt;/hello>
+ </pre>
+
+ <p>Then we can write a description of the above XML in the
+ XML Schema language and save it into <code>hello.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="hello">
+ &lt;xs:sequence>
+ &lt;xs:element name="greeting" type="xs:string"/>
+ &lt;xs:element name="name" type="xs:string" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="hello" type="hello"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Even if you are not familiar with the XML Schema language, it
+ should be easy to connect declarations in <code>hello.xsd</code>
+ to elements in the sample XML document above. The <code>hello</code>
+ type is defined as a sequence of the nested <code>greeting</code>
+ and <code>name</code> elements. Note that the term sequence in XML
+ Schema means that elements should appear in a particular order
+ as opposed to appearing multiple times. The <code>name</code>
+ element has its <code>maxOccurs</code> property set to
+ <code>unbounded</code> which means it can appear multiple times
+ in an XML document. Finally, the globally-defined <code>hello</code>
+ element prescribes the root element for our vocabulary. For an
+ easily-approachable introduction to XML Schema refer to
+ <a href="http://www.w3.org/TR/xmlschema-0/">XML Schema Part 0:
+ Primer</a>.</p>
+
+ <p>The above schema is a specification of our vocabulary; it tells
+ everybody what valid XML instances of our vocabulary should look
+ like. The next step is to compile this schema to generate C++
+ serializer skeletons.</p>
+
+ <h2><a name="2.2">2.2 Translating Schema to C++</a></h2>
+
+ <p>Now we are ready to translate our <code>hello.xsd</code> to C++
+ serializer skeletons. To do this we invoke the XSD/e compiler
+ from a terminal (UNIX) or a command prompt (Windows):
+ </p>
+
+ <pre class="terminal">
+$ xsde cxx-serializer hello.xsd
+ </pre>
+
+ <p>The XSD/e compiler produces two C++ files: <code>hello-sskel.hxx</code>
+ and <code>hello-sskel.cxx</code>. The following code fragment is taken
+ from <code>hello-sskel.hxx</code>; it should give you an idea about what
+ gets generated:
+ </p>
+
+<pre class="c++">
+class hello_sskel
+{
+public:
+ // Serializer callbacks. Override them in your implementation.
+ //
+ virtual void
+ pre ();
+
+ virtual std::string
+ greeting () = 0;
+
+ virtual bool
+ name_next () = 0;
+
+ virtual std::string
+ name () = 0;
+
+ virtual void
+ post ();
+
+ // Serializer construction API.
+ //
+ void
+ greeting_serializer (xml_schema::string_sskel&amp;);
+
+ void
+ name_serializer (xml_schema::string_sskel&amp;);
+
+ void
+ serializers (xml_schema::string_sskel&amp; /* greeting */,
+ xml_schema::string_sskel&amp; /* name */);
+
+private:
+ ...
+};
+ </pre>
+
+ <p>The first five member functions shown above are called serializer
+ callbacks. You would normally override them in your implementation
+ of the serializer. Let's go through all of them one by one.</p>
+
+ <p>The <code>pre()</code> function is an initialization callback. It is
+ called when a new element of type <code>hello</code> is about
+ to be serialized. You would normally use this function to initialize
+ data structures, such as iterators, which will be used during
+ serialization. As we will see in subsequent chapters, there is
+ also a way to pass an argument to this function which may be
+ useful if you are serializing an in-memory data structure
+ to XML. The default implementation of the initialization callback
+ does nothing.</p>
+
+ <p>The <code>post()</code> function is a finalization callback. It is
+ called when serialization of the element is completed. If necessary,
+ you can use this function to perform cleanups of data structures
+ initialized in <code>pre()</code> or during serialization.
+ The default implementation of the finalization callback also does
+ nothing.
+ </p>
+
+ <p>The <code>greeting()</code> and <code>name()</code> functions are
+ called when the <code>greeting</code> and <code>name</code> elements
+ are about to be serialized and the values for these elements need
+ to be provided. Because the <code>name</code> element can be
+ repeated several times (note the <code>maxOccurs="unbounded"</code>
+ attribute in the schema), the serializer skeleton also has the
+ <code>name_next()</code> function which is called before
+ <code>name()</code> to check if another <code>name</code> element
+ needs to be serialized.</p>
+
+ <p>The last three functions are for connecting serializers to each other.
+ For example, there is a predefined serializer for built-in XML Schema
+ type <code>string</code> in the XSD/e runtime. We will be using it to
+ serialize the values of <code>greeting</code> and <code>name</code>
+ elements, as shown in the next section.</p>
+
+ <h2><a name="2.3">2.3 Implementing Application Logic</a></h2>
+
+ <p>At this point we have all the parts we need to create our
+ sample XML document. The first step is to implement the
+ serializer:
+ </p>
+
+ <pre class="c++">
+#include &lt;string>
+#include &lt;vector>
+#include "hello-sskel.hxx"
+
+struct hello_simpl: hello_sskel
+{
+ hello_simpl ()
+ {
+ names_.push_back ("sun");
+ names_.push_back ("moon");
+ names_.push_back ("world");
+ }
+
+ virtual void
+ pre ()
+ {
+ i_ = names_.begin ();
+ }
+
+ virtual std::string
+ greeting ()
+ {
+ return "Hello";
+ }
+
+ virtual bool
+ name_next ()
+ {
+ return i_ != names_.end ();
+ }
+
+ virtual std::string
+ name ()
+ {
+ return *i_++;
+ }
+
+private:
+ typedef std::vector&lt;std::string> names;
+
+ names names_;
+ names::iterator i_;
+};
+ </pre>
+
+ <p>We use the <code>hello_simpl</code>'s constructor to initialize
+ a vector of names. Then, in the <code>pre()</code> initialization
+ callback, we initialize an iterator to point to the beginning of the
+ names vector. The <code>greeting()</code> callback
+ simply returns the string representing our greeting. The
+ <code>name_next()</code> callback checks if we reached the
+ end of the names vector and returns <code>false</code>
+ if that's the case. The <code>name()</code> callback returns
+ the next name from the names vector and advances the iterator.
+ Note that <code>name()</code> is not called if <code>name_next()</code>
+ returned false. Finally, we left <code>post()</code> with the
+ default implementations since we don't have anything to cleanup.</p>
+
+ <p>Now it is time to put this serializer implementation to work:</p>
+
+ <pre class="c++">
+#include &lt;iostream>
+
+using namespace std;
+
+int
+main ()
+{
+ try
+ {
+ // Construct the serializer.
+ //
+ xml_schema::string_simpl string_s;
+ hello_simpl hello_s;
+
+ hello_s.greeting_serializer (string_s);
+ hello_s.name_serializer (string_s);
+
+ // Create the XML document.
+ //
+ xml_schema::document_simpl doc_s (hello_s, "hello");
+
+ hello_s.pre ();
+ doc_s.serialize (cout, xml_schema::document_simpl::pretty_print);
+ hello_s.post ();
+ }
+ catch (const xml_schema::serializer_exception&amp; e)
+ {
+ cerr &lt;&lt; "error: " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>The first part of this code snippet instantiates individual serializers
+ and assembles them into a complete vocabulary serializer.
+ <code>xml_schema::string_simpl</code> is an implementation of a
+ serializer for built-in XML Schema type <code>string</code>. It is
+ provided by the XSD/e runtime along with serializers for other built-in
+ types (for more information on the built-in serializers see
+ <a href="#7">Chapter 7, "Built-In XML Schema Type Serializers"</a>).
+ We use <code>string_simpl</code> to serialize the <code>greeting</code>
+ and <code>name</code> elements as indicated by the calls to
+ <code>greeting_serializer()</code> and <code>name_serializer()</code>.
+ </p>
+
+ <p>Then we instantiate a document serializer (<code>doc_s</code>). The
+ first argument to its constructor is the serializer for the root
+ element (<code>hello_s</code> in our case). The second argument is
+ the root element name.
+ </p>
+
+ <p>The final piece is the calls to <code>pre()</code>,
+ <code>serialize()</code>, and <code>post()</code>. The call to
+ <code>serialize()</code> performs the actual XML serialization
+ with the result written to <code>std::cout</code>. The second
+ argument in this call is a flag that requests pretty-printing
+ of the resulting XML document. You would normally specify this flag
+ during testing to obtain easily-readable XML and remove it
+ in production to get faster serialization and smaller documents.
+ The calls to <code>pre()</code> and
+ <code>post()</code> make sure that the serializer for the
+ root element can perform proper initialization and cleanup.</p>
+
+ <p>While our serializer implementation and test driver are pretty small and
+ easy to write by hand, for bigger XML vocabularies it can be a
+ substantial effort. To help with this task XSD/e can automatically
+ generate sample serializer implementations and a test driver from your
+ schemas. To request the generation of a sample implementation with
+ empty function bodies specify the <code>--generate-empty-impl</code>
+ option. To request the generation of a test driver you can use the
+ <code>--generate-test-driver</code> option. For more information
+ on these options refer to the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a>.</p>
+
+ <h2><a name="2.4">2.4 Compiling and Running</a></h2>
+
+ <p>After saving all the parts from the previous section in
+ <code>driver.cxx</code>, we are ready to compile and run
+ our first application. On UNIX this can be done with the
+ following commands:
+ </p>
+
+ <pre class="terminal">
+$ c++ -I.../libxsde -c driver.cxx hello-sskel.cxx
+$ c++ -o driver driver.o hello-sskel.o .../libxsde/xsde/libxsde.a
+$ ./driver
+&lt;hello>
+ &lt;greeting>Hello&lt;/greeting>
+ &lt;name>sun&lt;/name>
+ &lt;name>moon&lt;/name>
+ &lt;name>world&lt;/name>
+&lt;/hello>
+ </pre>
+
+ <p>Here <code>.../libxsde</code> represents the path to the
+ <code>libxsde</code> directory in the XSD/e distribution.</p>
+
+ <p>
+ We can also test XML Schema validation. We can "forget" to
+ add any names to the vector so that <code>name_next()</code>
+ returns <code>false</code> on the first call:</p>
+
+<pre class="c++">
+struct hello_simpl: hello_sskel
+{
+ hello_simpl ()
+ {
+ /*
+ names_.push_back ("sun");
+ names_.push_back ("moon");
+ names_.push_back ("world");
+ */
+ }
+ ...
+};
+ </pre>
+
+ <p>This will violate our vocabulary specification which requires
+ at least one <code>name</code> element to be present. If we
+ make the above change and recompile our application, we will
+ get the following output:</p>
+
+ <pre class="terminal">
+$ ./driver
+error: expected element not encountered
+ </pre>
+
+
+ <!-- Chapater 3 -->
+
+
+ <h1><a name="3">3 Serializer Skeletons</a></h1>
+
+ <p>As we have seen in the previous chapter, the XSD/e compiler generates
+ a serializer skeleton class for each type defined in XML Schema. In
+ this chapter we will take a closer look at different functions
+ that comprise a serializer skeleton as well as the way to connect
+ our implementations of these serializer skeletons to create a complete
+ vocabulary serializer.</p>
+
+ <p>In this and subsequent chapters we will use the following
+ schema that describes a collection of person records. We
+ save it in <code>people.xsd</code>:</p>
+
+ <pre class="xml">
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:simpleType name="gender">
+ &lt;xs:restriction base="xs:string">
+ &lt;xs:enumeration value="male"/>
+ &lt;xs:enumeration value="female"/>
+ &lt;/xs:restriction>
+ &lt;/xs:simpleType>
+
+ &lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;xs:element name="gender" type="gender"/>
+ &lt;xs:element name="age" type="xs:short"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:complexType name="people">
+ &lt;xs:sequence>
+ &lt;xs:element name="person" type="person" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="people" type="people"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>A sample XML instance to go along with this schema could look like
+ this:</p>
+
+ <pre class="xml">
+&lt;people>
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+ <p>Compiling <code>people.xsd</code> with the XSD/e compiler results
+ in three serializer skeletons being generated: <code>gender_sskel</code>,
+ <code>person_sskel</code>, and <code>people_sskel</code>. We are going
+ to examine and implement each of them in the subsequent sections.</p>
+
+ <p>In the previous chapter we used pre-initialized, static data to
+ create an XML document. In this chapter we will use the standard
+ input (<code>std::cin</code>) as the source of data. This approach
+ reflects a common design theme where the data to be serialized is
+ computed on the fly instead of being stored in, for example, an
+ in-memory object model. The next chapter will examine mechanisms
+ provided by the C++/Serializer mapping for serializing in-memory
+ object models.</p>
+
+ <h2><a name="3.1">3.1 Implementing the Gender Serializer</a></h2>
+
+ <p>The generated <code>gender_sskel</code> serializer skeleton looks
+ like this:</p>
+
+ <pre class="c++">
+class gender_sskel: public xml_schema::string_sskel
+{
+public:
+ gender_sskel (xml_schema::string_sskel* base_impl)
+
+ // Serializer callbacks. Override them in your implementation.
+ //
+ virtual void
+ pre ();
+
+ virtual void
+ post ();
+};
+ </pre>
+
+ <p>Notice that <code>gender_sskel</code> inherits from
+ <code>xml_schema::string_sskel</code> which is a serializer
+ skeleton for built-in XML Schema type <code>string</code>
+ and is predefined in the XSD/e runtime library. This is an example
+ of the general rule that serializer skeletons follow: if a type
+ in XML Schema inherits from another then there will be an
+ equivalent inheritance between the corresponding serializer
+ skeleton classes. The <code>gender_sskel</code> class also
+ declares a constructor which expects a pointer to the base
+ serializer skeleton. We will discuss the purpose of this
+ constructor shortly.</p>
+
+ <p>The <code>pre()</code> and <code>post()</code> callbacks should look
+ familiar from the previous chapter. Let's now implement this
+ serializer. Our implementation will simply query the gender
+ value from the standard input stream (<code>std::cin</code>):</p>
+
+
+ <pre class="c++">
+#include &lt;string>
+#include &lt;iostream>
+
+using namespace std;
+
+class gender_simpl: public gender_sskel
+{
+public:
+ gender_simpl ()
+ : gender_sskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ pre ()
+ {
+ string g;
+ cerr &lt;&lt; "gender (male/female): ";
+ getline (cin, g);
+ base_impl_.pre (g);
+ }
+
+private:
+ xml_schema::string_simpl base_impl_;
+};
+ </pre>
+
+ <p>While the code is quite short, there is a lot going on. First,
+ notice that we define a member variable <code>base_impl_</code>
+ of type <code>xml_schema::string_simpl</code> and then pass
+ it to the <code>gender_sskel</code>'s constructor. We have
+ encountered <code>xml_schema::string_simpl</code> already; it is an
+ implementation of the <code>xml_schema::string_sskel</code> serializer
+ skeleton for built-in XML Schema type <code>string</code>. By
+ passing <code>base_impl_</code> to the <code>gender_sskel</code>'s
+ constructor we provide an implementation for the part of the
+ serializer skeleton that is inherited from <code>string_sskel</code>.</p>
+
+ <p>This is another common theme in the C++/Serializer programming model:
+ reusing implementations of the base serializers in the derived ones.
+ In our case, <code>string_simpl</code> will do all the dirty work of
+ serializing the data which we pass to it with the call to
+ <code>base_impl_.pre()</code>. For more information on serializer
+ implementation reuse refer to <a href="#6.6">Section 6.6,
+ "Serializer Reuse"</a>.</p>
+
+ <p>In case you are curious, here are the definitions for
+ <code>xml_schema::string_sskel</code> and
+ <code>xml_schema::string_simpl</code>:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sskel: public serializer_simple_content
+ {
+ public:
+ virtual void
+ pre (const std::string&amp;) = 0;
+ };
+
+ class string_simpl: public string_sskel
+ {
+ public:
+ virtual void
+ pre (const std::string&amp;);
+
+ virtual void
+ _serialize_content ();
+
+ protected:
+ std::string value_;
+ };
+}
+ </pre>
+
+ <p>There are two new pieces in this code that we haven't seen yet.
+ Those are the <code>xml_schema::serializer_simple_content</code>
+ class and the <code>_serialize_content()</code> function.
+ The <code>serializer_simple_content</code> class is defined in
+ the XSD/e runtime and is a base class for all serializer skeletons
+ that conform to the simple content model in XML Schema. Types with
+ the simple content model cannot have nested elements&mdash;only
+ text and attributes. There is also the
+ <code>xml_schema::serializer_complex_content</code> class which
+ corresponds to the complex content mode (types with nested elements,
+ for example, <code>person</code> from <code>people.xsd</code>).</p>
+
+ <p>The <code>_serialize_content()</code> function is a low-level
+ serializer callback that is called to perform actual content
+ serialization (that is to output text or nested elements). There
+ is also the <code>_serialize_attributes()</code> callback which
+ is called to serialize attributes in complex types. You will seldom
+ need to use these callbacks directly. Using implementations for the
+ built-in serializers provided by the XSD/e runtime is usually a
+ simpler and more convenient alternative.</p>
+
+ <p>Another bit of information that is useful to know about is
+ the <code>_pre()</code> and <code>_post()</code> serialization
+ callbacks. Remember we talked about the <code>pre()</code> and
+ <code>post()</code> callbacks in the previous chapter? The
+ <code>_pre()</code> and <code>_post</code> have very
+ similar but somewhat different roles. As a result, each
+ serializer skeleton has four special callbacks:</p>
+
+ <pre class="c++">
+ virtual void
+ pre ();
+
+ virtual void
+ _pre ();
+
+ virtual void
+ _post ();
+
+ virtual void
+ post ();
+ </pre>
+
+ <p><code>pre()</code> and <code>_pre()</code> are initialization
+ callbacks. They get called in that order before a new instance of the type
+ is about to be serialized. The difference between <code>pre()</code> and
+ <code>_pre()</code> is conventional: <code>pre()</code> can
+ be completely overridden by a derived serializer. The derived
+ serializer can also override <code>_pre()</code> but has to always call
+ the original version. This allows you to partition initialization
+ into customizable and required parts.</p>
+
+ <p>Similarly, <code>_post()</code> and <code>post()</code> are
+ finalization callbacks with exactly the same semantics:
+ <code>post()</code> can be completely overridden by the derived
+ serializer while the original <code>_post()</code> should always be
+ called.
+ </p>
+
+ <p>At this point you might be wondering why some <code>pre()</code>
+ callbacks, for example <code>string_sskel::pre()</code>, have an
+ argument with which they receive the data they need to serialize while
+ others, for example <code>gender_sskel::pre()</code>, have no such
+ argument. This is a valid concern and it will be addressed in the
+ next chapter.</p>
+
+ <h2><a name="3.2">3.2 Implementing the Person Serializer</a></h2>
+
+ <p>The generated <code>person_sskel</code> serializer skeleton looks like
+ this:</p>
+
+ <pre class="c++">
+class person_sskel: public xml_schema::serializer_complex_content
+{
+public:
+ // Serializer callbacks. Override them in your implementation.
+ //
+ virtual void
+ pre ();
+
+ virtual std::string
+ first_name () = 0;
+
+ virtual std::string
+ last_name () = 0;
+
+ virtual void
+ gender ();
+
+ virtual short
+ age () = 0;
+
+ virtual void
+ post ();
+
+ // Serializer construction API.
+ //
+ void
+ first_name_serializer (xml_schema::string_sskel&amp;);
+
+ void
+ last_name_serializer (xml_schema::string_sskel&amp;);
+
+ void
+ gender_serializer (gender_sskel&amp;);
+
+ void
+ age_serializer (xml_schema::short_sskel&amp;);
+
+ void
+ serializers (xml_schema::string_sskel&amp; /* first-name */,
+ xml_schema::string_sskel&amp; /* last-name */,
+ gender_sskel&amp; /* gender */,
+ xml_schema::short_sskel&amp; /* age */);
+};
+ </pre>
+
+
+ <p>As you can see, we have a serializer callback for each of the nested
+ elements found in the <code>person</code> XML Schema type.
+ The implementation of this serializer is straightforward:</p>
+
+ <pre class="c++">
+class person_simpl: public person_sskel
+{
+public:
+ virtual string
+ first_name ()
+ {
+ string fn;
+ cerr &lt;&lt; "first name: ";
+ getline (cin, fn);
+ return fn;
+ }
+
+ virtual std::string
+ last_name ()
+ {
+ string ln;
+ cerr &lt;&lt; "last name: ";
+ getline (cin, ln);
+ return ln;
+ }
+
+ virtual short
+ age ()
+ {
+ short a;
+ cerr &lt;&lt; "age: ";
+ cin >> a;
+ return a;
+ }
+};
+ </pre>
+
+ <p>Notice that we didn't need to override the <code>gender()</code>
+ callback because all the work is done by <code>gender_simpl</code>.</p>
+
+ <h2><a name="3.3">3.3 Implementing the People Serializer</a></h2>
+
+ <p>The generated <code>people_sskel</code> serializer skeleton looks like
+ this:</p>
+
+ <pre class="c++">
+class people_sskel: public xml_schema::serializer_complex_content
+{
+public:
+ // Serializer callbacks. Override them in your implementation.
+ //
+ virtual void
+ pre ();
+
+ virtual bool
+ person_next () = 0;
+
+ virtual void
+ person ();
+
+ virtual void
+ post ();
+
+ // Serializer construction API.
+ //
+ void
+ person_serializer (person_sskel&amp;);
+
+ void
+ serializers (person_sskel&amp; /* person */);
+};
+ </pre>
+
+ <p>The <code>person_next()</code> callback will be called before serializing
+ each <code>person</code> element. Our implementation of
+ <code>person_next()</code> asks the user whether to serialize
+ another person record:</p>
+
+ <pre class="c++">
+class people_simpl: public people_sskel
+{
+public:
+ virtual bool
+ person_next ()
+ {
+ string s;
+ cerr &lt;&lt; "serialize another person record (y/n): ";
+ cin >> ws; // Skip leading whitespaces.
+ getline (cin, s);
+ return s == "y";
+ }
+};
+ </pre>
+
+ <p>Now it is time to put everything together.</p>
+
+
+ <h2><a name="3.4">3.4 Connecting the Serializers Together</a></h2>
+
+ <p>At this point we have all the individual serializers implemented
+ and can proceed to assemble them into a complete serializer
+ for our XML vocabulary. The first step is to instantiate
+ all the individual serializers that we will need:</p>
+
+ <pre class="c++">
+xml_schema::short_simpl short_s;
+xml_schema::string_simpl string_s;
+
+gender_simpl gender_s;
+person_simpl person_s;
+people_simpl people_s;
+ </pre>
+
+ <p>Notice that our schema uses two built-in XML Schema types:
+ <code>string</code> for the <code>first-name</code> and
+ <code>last-name</code> elements as well as <code>short</code>
+ for <code>age</code>. We will use predefined serializers that
+ come with the XSD/e runtime to serialize these types. The next
+ step is to connect all the individual serializers. We do this
+ with the help of functions defined in the serializer
+ skeletons and marked with the "Serializer Construction API"
+ comment. One way to do it is to connect each individual
+ serializers by calling the <code>*_serializer()</code> functions:</p>
+
+ <pre class="c++">
+person_s.first_name_serializer (string_s);
+person_s.last_name_serializer (string_s);
+person_s.gender_serializer (gender_s);
+person_s.age_serializer (short_s);
+
+people_s.person_serializer (person_s);
+ </pre>
+
+ <p>You might be wondering what happens if you do not provide
+ a serializer by not calling one of the <code>*_serializer()</code>
+ functions. In that case the corresponding XML fragment will be
+ skipped.</p>
+
+ <p>An alternative, shorter, way to connect the serializers is by using
+ the <code>serializers()</code> functions which connects all the
+ serializers for a given type at once:</p>
+
+ <pre class="c++">
+person_s.serializers (string_s, string_s, gender_s, short_s);
+people_s.serializers (person_s);
+ </pre>
+
+ <p>The following figure illustrates the resulting connections. Notice
+ the correspondence between return types of element callbacks and
+ argument types of the <code>pre()</code> functions that are connected
+ by the arrows.</p>
+
+ <!-- align=center is needed for html2ps -->
+ <div class="img" align="center"><img src="figure-1.png"/></div>
+
+ <p>The last step is the construction of the document serializer and
+ invocation of the complete serializer to produce an XML
+ document:</p>
+
+ <pre class="c++">
+xml_schema::document_simpl doc_s (people_s, "people");
+
+std::ostringstream os;
+
+people_s.pre ();
+doc_s.serialize (os, xml_schema::document_simpl::pretty_print);
+people_s.post ();
+
+cout &lt;&lt; os.str ();
+ </pre>
+
+ <p>Note that we first serialize the document into an
+ <code>std::ostringstream</code> object and then write
+ the result to the standard output stream. This is done
+ to prevent the input prompts and output XML from interleaving.
+ However, writing XML directly to <code>std::cout</code> in
+ this example is a great way to observe the moments in the XML
+ document construction process at which serializer callbacks are
+ being called.</p>
+
+ <p>Let's consider <code>xml_schema::document_simpl</code> in
+ more detail. While the exact definition of this class
+ varies depending on the mapping configuration, here is
+ the part relevant to our example:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class document_simpl
+ {
+ public:
+ document_simpl (xml_schema::serializer_base&amp;,
+ const std::string&amp; root_element_name);
+
+ document_simpl (xml_schema::serializer_base&amp;,
+ const std::string&amp; root_element_namespace,
+ const std::string&amp; root_element_name);
+
+ typedef unsigned short flags;
+ static const flags pretty_print;
+
+ void
+ serialize (std::ostream&amp;, flags = 0);
+ };
+}
+ </pre>
+
+ <p><code>xml_schema::document_simpl</code> is a root serializer for
+ the vocabulary. The first argument to its constructors is the
+ serializer for the type of the root element (<code>people_simpl</code>
+ in our case). Because a type serializer is only concerned with
+ the element's content and not with the element's name, we need
+ to specify the root element name somewhere. That's
+ what is passed as the second and third arguments to the
+ <code>document_simpl</code>'s constructors.</p>
+
+ <p>There is also a number of overloaded <code>serialize()</code>
+ function defined in the <code>document_simpl</code> class.
+ At the moment we are only interested in the version that
+ writes XML to a standard output stream. For more information
+ on the <code>xml_schema::document_simpl</code> class
+ refer to <a href="#8">Chapter 8, "Document Serializer and Error
+ Handling"</a>.</p>
+
+ <p>Let's now consider a step-by-step list of actions that happen
+ as we serialize the following sample XML document:</p>
+
+ <pre class="xml">
+&lt;people>
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+
+ <ol class="steps">
+ <li><code>people_s.pre()</code> is called from
+ <code>main()</code>. We did not provide any implementation
+ for this callback so this call is a no-op.</li>
+
+ <li><code>doc_s.serialize(os)</code> is called from
+ <code>main()</code>. The document serializer
+ writes out the <code>&lt;people></code> opening tag
+ and calls <code>_pre()</code> on the root element
+ type serializer (<code>people_s</code>) which is
+ also a no-op. Serialization is delegated to
+ <code>people_s</code>.</li>
+
+ <li>The <code>people_s</code> serializer calls <code>person_next()</code>
+ to determine if another <code>person</code> element
+ needs to be serialized. Our implementation ask the user
+ (who answers <code>"y"</code>) and returns <code>true</code>.</li>
+
+ <li>The <code>people_s</code> serializer calls <code>person()</code>
+ which is a no-op. It then calls <code>pre()</code> on
+ <code>person_s</code> (no-op), writes out the
+ <code>&lt;person></code> opening tag, and calls <code>_pre()</code>
+ on <code>person_s</code> (no-op). Serialization is delegated to
+ <code>person_s</code>.</li>
+
+ <li>The <code>person_s</code> serializer calls <code>first_name()</code>
+ that returns a first name which it asks the user to enter.
+ <code>person_s</code> then calls <code>pre()</code> on
+ <code>string_s</code> and passes the name returned from
+ <code>first_name()</code> as its argument. It then writes
+ out the <code>&lt;first-name></code> opening tag and calls
+ <code>_pre()</code> on <code>string_s</code>. Serialization
+ is delegated to <code>string_s</code>.</li>
+
+ <li>The <code>_serialize_content()</code> callback is called on
+ <code>string_s</code> which writes out the string passed
+ to it in the <code>pre()</code> call.</li>
+
+ <li>Control is returned to <code>person_s</code> which
+ calls <code>_post()</code> on <code>string_s</code>, writes
+ out the <code>&lt;/first-name></code> closing tag, and calls
+ <code>post()</code> on <code>string_s</code>.</li>
+
+ <li>Steps analogous to 5-7 are performed for the <code>last-name</code>,
+ <code>gender</code>, and <code>age</code> elements.</li>
+
+ <li>Control is returned to <code>people_s</code>
+ which calls <code>_post()</code> on <code>person_s</code> (no-op),
+ writes out the <code>&lt;/person></code> closing tag, and calls
+ <code>post()</code> on <code>person_s</code> (no-op).</li>
+
+ <li>The <code>people_s</code> serializer calls <code>person_next()</code>
+ to determine if another <code>person</code> element
+ needs to be serialized. Our implementation ask the user
+ (who answers <code>"n"</code>) and returns <code>false</code>.</li>
+
+ <li>Control is returned to <code>doc_s</code> which calls
+ <code>_post()</code> on <code>people_s</code> (no-op) and
+ writes out the <code>&lt;/people></code> closing tag.</li>
+
+ <li>Control is returned to <code>main()</code> which
+ calls <code>post()</code> on <code>people_s</code> (no-op).</li>
+ </ol>
+
+
+ <!-- Chpater 4 -->
+
+
+ <h1><a name="4">4 Type Maps</a></h1>
+
+ <p>There are many useful things you can do inside serializer callbacks as they
+ are right now. There are, however, times when you want to propagate
+ some information from one serializer to another or from the caller of
+ the serializer. One common task that would greatly benefit from such a
+ possibility is serializing a tree-like in-memory object model to XML.
+ During execution, each individual serializer would be responsible
+ for disaggregating and serializing a specific portion of the tree
+ and delegating the rest to its sub-serializers.</p>
+
+ <p>In this chapter we will discuss the mechanisms offered by the
+ C++/Serializer mapping for passing information between individual
+ serializers and see how to use them to serialize a sample object
+ model for our people vocabulary.</p>
+
+ <h2><a name="4.1">4.1 Object Model</a></h2>
+
+ <p>An object model for our person record example could
+ look like this (saved in the <code>people.hxx</code> file):</p>
+
+ <pre class="c++">
+#include &lt;string>
+#include &lt;vector>
+
+enum gender
+{
+ male,
+ female
+};
+
+class person
+{
+public:
+ person (const std::string&amp; first,
+ const std::string&amp; last,
+ ::gender gender,
+ short age)
+ : first_ (first), last_ (last),
+ gender_ (gender), age_ (age)
+ {
+ }
+
+ const std::string&amp;
+ first () const
+ {
+ return first_;
+ }
+
+ const std::string&amp;
+ last () const
+ {
+ return last_;
+ }
+
+ ::gender
+ gender () const
+ {
+ return gender_;
+ }
+
+ short
+ age () const
+ {
+ return age_;
+ }
+
+private:
+ std::string first_;
+ std::string last_;
+ ::gender gender_;
+ short age_;
+};
+
+typedef std::vector&lt;person> people;
+ </pre>
+
+ <p>While it is clear which serializer is responsible for which part of
+ the object model, it is not exactly clear how, for
+ example, <code>person_simpl</code> will pass <code>gender</code>
+ to <code>gender_simpl</code>. You might have noticed that
+ <code>string_simpl</code> manages to receive its value from the
+ <code>first_name()</code> callback. Let's
+ see how we can utilize the same mechanism to propagate our
+ own data.</p>
+
+ <p>There is a way to tell the XSD/e compiler that you want to
+ exchange data between serializers. More precisely, for each
+ type defined in XML Schema, you can tell the compiler two things.
+ First, the argument type of the <code>pre()</code> callback
+ in the serializer skeleton generated for this type. And, second,
+ the return type for callbacks corresponding to elements and
+ attributes of this type. For example, for XML Schema type
+ <code>gender</code> we can specify the argument type for
+ <code>pre()</code> in the <code>gender_sskel</code>
+ skeleton and the return type for the <code>gender()</code> callback
+ in the <code>person_sskel</code> skeleton. As you might have guessed,
+ the generated code will then pass the return value from an
+ element or attribute callback (<code>person_sskel::gender()</code>
+ in our case) to the <code>pre()</code> callback of the corresponding
+ serializer skeleton (<code>gender_sskel::pre()</code> in our case).</p>
+
+ <p>The way to tell the XSD/e compiler about these XML Schema to
+ C++ mappings is with type map files. Here is a simple type
+ map for the <code>gender</code> type from the previous paragraph.</p>
+
+ <pre class="type-map">
+include "people.hxx";
+gender ::gender ::gender;
+ </pre>
+
+ <p>The first line indicates that the generated code must include
+ <code>people.hxx</code> in order to get the definition for the
+ <code>gender</code> type. The second line specifies that both
+ argument and return types for the <code>gender</code>
+ XML Schema type should be the <code>::gender</code> C++ enum
+ (we use fully-qualified C++ names to avoid name clashes).
+ The next section will describe the type map format in more detail.
+ We save this type map in <code>people.map</code> and
+ then translate our schemas with the <code>--type-map</code>
+ option to let the XSD/e compiler know about our type map:</p>
+
+ <pre class="terminal">
+$ xsde cxx-serializer --type-map people.map people.xsd
+ </pre>
+
+ <p>If we now look at the generated <code>people-sskel.hxx</code>,
+ we will see the following changes in the <code>gender_sskel</code> and
+ <code>person_sskel</code> skeletons:</p>
+
+ <pre class="c++">
+#include "people.hxx"
+
+class gender_sskel: public xml_schema::string_sskel
+{
+ virtual void
+ pre (::gender) = 0;
+
+ ...
+};
+
+class person_sskel: public xml_schema::serializer_complex_content
+{
+ virtual ::gender
+ gender () = 0;
+
+ ...
+};
+ </pre>
+
+ <p>Notice that <code>#include "people.hxx"</code> was added to
+ the generated header file from the type map to provide the
+ definition for the <code>gender</code> enum.</p>
+
+ <h2><a name="4.2">4.2 Type Map File Format</a></h2>
+
+ <p>Type map files are used to define a mapping between XML Schema
+ and C++ types. The compiler uses this information
+ to determine argument types of <code>pre()</code>
+ callbacks in serializer skeletons corresponding to XML Schema
+ types as well as return types for callbacks corresponding
+ to elements and attributes of these types.</p>
+
+ <p>The compiler has a set of predefined mapping rules that map
+ the built-in XML Schema types to suitable C++ types (discussed
+ below) and all other types to <code>void</code>.
+ By providing your own type maps you can override these predefined
+ rules. The format of the type map file is presented below:
+ </p>
+
+ <pre class="type-map">
+namespace &lt;schema-namespace> [&lt;cxx-namespace>]
+{
+ (include &lt;file-name>;)*
+ ([type] &lt;schema-type> &lt;cxx-ret-type> [&lt;cxx-arg-type>];)*
+}
+ </pre>
+
+ <p>Both <code><i>&lt;schema-namespace></i></code> and
+ <code><i>&lt;schema-type></i></code> are regex patterns while
+ <code><i>&lt;cxx-namespace></i></code>,
+ <code><i>&lt;cxx-ret-type></i></code>, and
+ <code><i>&lt;cxx-arg-type></i></code> are regex pattern
+ substitutions. All names can be optionally enclosed in
+ <code>"&nbsp;"</code>, for example, to include white-spaces.</p>
+
+ <p><code><i>&lt;schema-namespace></i></code> determines XML
+ Schema namespace. Optional <code><i>&lt;cxx-namespace></i></code>
+ is prefixed to every C++ type name in this namespace declaration.
+ <code><i>&lt;cxx-ret-type></i></code> is a C++ type name that is
+ used as a return type for the element and attribute callbacks corresponding
+ to this schema type. Optional <code><i>&lt;cxx-arg-type></i></code>
+ is an argument type for the <code>pre()</code> callback in the serializer
+ skeleton for this schema type. If <code><i>&lt;cxx-arg-type></i></code>
+ is not specified, it defaults to <code><i>&lt;cxx-ret-type></i></code>
+ if <code><i>&lt;cxx-ret-type></i></code> ends with <code>*</code> or
+ <code>&amp;</code> (that is, it is a pointer or a reference) and
+ <code>const&nbsp;<i>&lt;cxx-ret-type></i>&amp;</code>
+ otherwise.
+ <code><i>&lt;file-name></i></code> is a file name either in the
+ <code>"&nbsp;"</code> or <code>&lt;&nbsp;></code> format
+ and is added with the <code>#include</code> directive to
+ the generated code.</p>
+
+ <p>The <code><b>#</b></code> character starts a comment that ends
+ with a new line or end of file. To specify a name that contains
+ <code><b>#</b></code> enclose it in <code><b>"&nbsp;"</b></code>.
+ For example:</p>
+
+ <pre>
+namespace http://www.example.com/xmlns/my my
+{
+ include "my.hxx";
+
+ # Pass apples by value.
+ #
+ apple apple;
+
+ # Pass oranges as pointers.
+ #
+ orange orange_t*;
+}
+ </pre>
+
+ <p>In the example above, for the
+ <code>http://www.example.com/xmlns/my#orange</code>
+ XML Schema type, the <code>my::orange_t*</code> C++ type will
+ be used as both return and argument types.</p>
+
+ <p>Several namespace declarations can be specified in a single
+ file. The namespace declaration can also be completely
+ omitted to map types in a schema without a namespace. For
+ instance:</p>
+
+ <pre class="type-map">
+include "my.hxx";
+apple apple;
+
+namespace http://www.example.com/xmlns/my
+{
+ orange "const orange_t*";
+}
+ </pre>
+
+ <p>The compiler has a number of predefined mapping rules for
+ the built-in XML Schema types which can be presented as the
+ following map files:</p>
+
+ <pre class="type-map">
+namespace http://www.w3.org/2001/XMLSchema
+{
+ boolean bool bool;
+
+ byte "signed char" "signed char";
+ unsignedByte "unsigned char" "unsigned char";
+
+ short short short;
+ unsignedShort "unsigned short" "unsigned short";
+
+ int int int;
+ unsignedInt "unsigned int" "unsigned int";
+
+ long "long long" "long long";
+ unsignedLong "unsigned long long" "unsigned long long";
+
+ integer long long;
+
+ negativeInteger long long;
+ nonPositiveInteger long long;
+
+ positiveInteger "unsigned long" "unsigned long";
+ nonNegativeInteger "unsigned long" "unsigned long";
+
+ float float float;
+ double double double;
+ decimal double double;
+
+ NMTOKENS "const xml_schema::string_sequence*";
+ IDREFS "const xml_schema::string_sequence*";
+
+ base64Binary "const xml_schema::buffer*";
+ hexBinary "const xml_schema::buffer*";
+
+ date xml_schema::date;
+ dateTime xml_schema::date_time;
+ duration xml_schema::duration;
+ gDay xml_schema::gday;
+ gMonth xml_schema::gmonth;
+ gMonthDay xml_schema::gmonth_day;
+ gYear xml_schema::gyear;
+ gYearMonth xml_schema::gyear_month;
+ time xml_schema::time;
+}
+ </pre>
+
+ <p>If STL is enabled (<a href="#6.1">Section 6.1, "Standard Template
+ Library"</a>), the following mapping is used for the string-based
+ XML Schema built-in types:</p>
+
+ <pre class="type-map">
+namespace http://www.w3.org/2001/XMLSchema
+{
+ include &lt;string>;
+
+ anySimpleType std::string;
+
+ string std::string;
+ normalizedString std::string;
+ token std::string;
+ Name std::string;
+ NMTOKEN std::string;
+ NCName std::string;
+ ID std::string;
+ IDREF std::string;
+ language std::string;
+ anyURI std::string;
+
+ QName xml_schema::qname;
+}
+ </pre>
+
+ <p>Otherwise, a C string-based mapping is used:</p>
+
+ <pre class="type-map">
+namespace http://www.w3.org/2001/XMLSchema
+{
+ anySimpleType "const char*";
+
+ string "const char*";
+ normalizedString "const char*";
+ token "const char*";
+ Name "const char*";
+ NMTOKEN "const char*";
+ NCName "const char*";
+ ID "const char*";
+ IDREF "const char*";
+ language "const char*";
+ anyURI "const char*";
+
+ QName "const xml_schema::qname*";
+}
+ </pre>
+
+ <p>For more information about the mapping of the built-in XML Schema types
+ to C++ types refer to <a href="#7">Chapter 7, "Built-In XML Schema Type
+ Serializers"</a>. The last predefined rule maps anything that wasn't
+ mapped by previous rules to <code>void</code>:</p>
+
+ <pre class="type-map">
+namespace .*
+{
+ .* void void;
+}
+ </pre>
+
+
+ <p>When you provide your own type maps with the
+ <code>--type-map</code> option, they are evaluated first. This
+ allows you to selectively override any
+ of the predefined rules. Note also that if you change the mapping
+ of a built-in XML Schema type then it becomes your responsibility
+ to provide the corresponding serializer skeleton and implementation
+ in the <code>xml_schema</code> namespace. You can include the
+ custom definitions into the generated header file using the
+ <code>--hxx-prologue-*</code> options.</p>
+
+ <h2><a name="4.3">4.3 Serializer Implementations</a></h2>
+
+ <p>With the knowledge from the previous section, we can proceed
+ with creating a type map that maps types in the <code>people.xsd</code>
+ schema to our object model classes in
+ <code>people.hxx</code>. In fact, we already have the beginning
+ of our type map file in <code>people.map</code>. Let's extend
+ it with the rest of the types:</p>
+
+ <pre class="type-map">
+include "people.hxx";
+
+gender ::gender ::gender;
+person "const ::person&amp;";
+people "const ::people&amp;";
+ </pre>
+
+ <p>A few things to note about this type map. We decided to pass
+ the <code>person</code> and <code>people</code> objects by
+ constant references in order to avoid unnecessary copying.
+ We can do this because we know that our object model is
+ present for the duration of serialization. We also did not
+ provide any mappings for built-in XML Schema types
+ <code>string</code> and <code>short</code> because they
+ are handled by the predefined rules and we are happy with
+ the result. Note also that all C++ types are fully qualified.
+ This is done to avoid potential name conflicts in the generated
+ code. Now we can recompile our schema and move on to implementing
+ the serializers:</p>
+
+ <pre class="terminal">
+$ xsde cxx-serializer --type-map people.map people.xsd
+ </pre>
+
+ <p>Here is the implementation of our three serializers in full. One
+ way to save typing when implementing your own serializers is
+ to open the generated code and copy the signatures of serializer
+ callbacks into your code. Or you could always auto generate the
+ sample implementations and fill them with your code.</p>
+
+ <pre class="c++">
+#include "people-sskel.hxx"
+
+const char* gender_strings[] = {"male", "female"};
+
+class gender_simpl: public gender_sskel
+{
+public:
+ gender_simpl ()
+ : gender_sskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ pre (gender g)
+ {
+ base_impl_.pre (gender_strings[g]);
+ }
+
+private:
+ xml_schema::string_simpl base_impl_;
+};
+
+class person_simpl: public person_sskel
+{
+public:
+ virtual void
+ pre (const person&amp; p)
+ {
+ p_ = &amp;p;
+ }
+
+ virtual std::string
+ first_name ()
+ {
+ return p_->first ();
+ }
+
+ virtual std::string
+ last_name ()
+ {
+ return p_->last ();
+ }
+
+ virtual ::gender
+ gender ()
+ {
+ return p_->gender ();
+ }
+
+ virtual short
+ age ()
+ {
+ return p_->age ();
+ }
+
+private:
+ const person* p_;
+};
+
+class people_simpl: public people_sskel
+{
+public:
+ virtual void
+ pre (const people&amp; p)
+ {
+ p_ = &amp;p;
+ i_ = p_->begin ();
+ }
+
+ virtual bool
+ person_next ()
+ {
+ return i_ != p_->end ();
+ }
+
+ virtual const ::person&amp;
+ person ()
+ {
+ return *i_++;
+ }
+
+private:
+ const people* p_;
+ people::const_iterator i_;
+};
+ </pre>
+
+ <p>This code fragment should look familiar by now. Just note that
+ all the <code>pre()</code> callbacks now have arguments. Here is the
+ implementation of the test driver for this example:</p>
+
+ <pre class="c++">
+#include &lt;iostream>
+
+using namespace std;
+
+int
+main ()
+{
+ // Create a sample object model.
+ //
+ people ppl;
+
+ ppl.push_back (person ("John", "Doe", male, 32));
+ ppl.push_back (person ("Jane", "Doe", female, 28));
+
+ // Construct the serializer.
+ //
+ xml_schema::short_simpl short_s;
+ xml_schema::string_simpl string_s;
+
+ gender_simpl gender_s;
+ person_simpl person_s;
+ people_simpl people_s;
+
+ person_s.serializers (string_s, string_s, gender_s, short_s);
+ people_s.serializers (person_s);
+
+ // Create the XML document.
+ //
+ xml_schema::document_simpl doc_s (people_s, "people");
+
+ people_s.pre (ppl);
+ doc_s.serialize (cout, xml_schema::document_simpl::pretty_print);
+ people_s.post ();
+}
+ </pre>
+
+ <p>The serializer creation and assembly part is exactly the same as in
+ the previous chapter. The serialization part is a bit different:
+ <code>people_simpl::pre()</code> now has an argument which is the
+ complete object model. Also we write the resulting XML directly
+ to the standard output stream instead of first storing it in a string.
+ We can now save the last two code fragments to <code>driver.cxx</code>
+ and proceed to compile and test our new application:</p>
+
+
+ <pre class="terminal">
+$ c++ -I.../libxsde -c driver.cxx people-sskel.cxx
+$ c++ -o driver driver.o people-sskel.o .../libxsde/xsde/libxsde.a
+$ ./driver
+&lt;people>
+ &lt;person>
+ &lt;first-name>John&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>male&lt;/gender>
+ &lt;age>32&lt;/age>
+ &lt;/person>
+ &lt;person>
+ &lt;first-name>Jane&lt;/first-name>
+ &lt;last-name>Doe&lt;/last-name>
+ &lt;gender>female&lt;/gender>
+ &lt;age>28&lt;/age>
+ &lt;/person>
+&lt;/people>
+ </pre>
+
+
+ <!-- Serializer Callbacks -->
+
+ <h1><a name="5">5 Serializer Callbacks</a></h1>
+
+ <p>In previous chapters we have learned that for each attribute
+ and element in a schema type there is a callback in a serializer
+ skeleton with the same name and which optionally returns
+ this element's or attribute's value. We've also seen that
+ elements that can appear multiple times
+ (<code>maxOccurs="unbounded"</code>) have an additional
+ serializer callback in the form:</p>
+
+ <pre class="c++">
+virtual bool
+&lt;name>_next ();
+ </pre>
+
+ <p>Where <code>&lt;name></code> stands for the element's name. In
+ this chapter we will discuss other additional serializer
+ callbacks that are generated for certain XML Schema constructs.
+ We will also learn that besides elements and attributes, serializer
+ callback can be generated for the <code>all</code>, <code>choice</code>,
+ and <code>sequence</code> compositors as well as the <code>any</code>
+ and <code>anyAttribute</code> wildcards.</p>
+
+ <p>When additional serializer callback are generated for elements
+ and attributes, their names are derived from element's and
+ attribute's names. Compositors and wildcards, on the other
+ hand, do not have names and as a result the serializer
+ callback names for these constructs are based on synthesized
+ names in the form: <code>all</code> for the <code>all</code>
+ compositor, <code>sequence</code>, <code>sequence1</code>,
+ etc., for the <code>sequence</code> compositors, <code>choice</code>,
+ <code>choice1</code>, etc., for the <code>choice</code> compositors,
+ <code>any</code>, <code>any1</code>, etc., for the <code>any</code>
+ wildcards, and <code>any_attribute</code>, <code>any_attribute1</code>,
+ etc., for the <code>anyAttribute</code> wildcards. For example:</p>
+
+ <pre>
+&lt;xs:complexType name="coordinates">
+ &lt;xs:sequence maxOccurs="unbounded">
+ &lt;xs:element name="lat" type="xs:float"/>
+ &lt;xs:element name="lon" type="xs:float"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+class coordinates_sskel: public xml_schema::serializer_complex_content
+{
+public:
+ virtual void
+ pre ();
+
+ virtual bool
+ sequence_next ();
+
+ virtual float
+ lan () = 0;
+
+ virtual float
+ lon () = 0;
+
+ virtual void
+ post ();
+
+ ...
+};
+ </pre>
+
+
+ <h2><a name="5.1">5.1 Optional Callback</a></h2>
+
+ <p>For elements, compositors, and element wildcards with the minimal
+ occurrence constraint equals <code>0</code> (<code>minOccurs="0"</code>)
+ and the maximum occurrence constraint equals <code>1</code>
+ (<code>maxOccurs="1"</code>) as well as for optional attributes, the
+ optional callback is generated in the form:</p>
+
+ <pre class="c++">
+virtual bool
+&lt;name>_present ();
+ </pre>
+
+ <p>This callback is called before any other callbacks for this schema
+ construct and if it returns <code>false</code> no further callback
+ calls corresponding to this construct are made and the corresponding
+ XML fragment is omitted. For example:</p>
+
+ <pre>
+&lt;xs:complexType name="name">
+ &lt;xs:sequence minOccurs="0">
+ &lt;xs:element name="first" type="xs:string"/>
+ &lt;xs:element name="initial" type="xs:string" minOccurs="0"/>
+ &lt;xs:element name="last" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;xs:attribute name="lang" type="xs:language"/>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+class name_sskel: public xml_schema::serializer_complex_content
+{
+public:
+ virtual void
+ pre ();
+
+ virtual bool
+ lang_present ();
+
+ virtual std::string
+ lang () = 0;
+
+ virtual bool
+ sequence_present ();
+
+ virtual std::string
+ first () = 0;
+
+ virtual bool
+ initial_present ();
+
+ virtual std::string
+ initial () = 0;
+
+ virtual std::string
+ last () = 0;
+
+ virtual void
+ post ();
+
+ ...
+};
+ </pre>
+
+ <h2><a name="5.2">5.2 Sequence Callback</a></h2>
+
+ <p>For elements, compositors, and element wildcards with the the maximum
+ occurrence constraint greater than <code>1</code> (for example,
+ <code>maxOccurs="unbounded"</code>) the sequence callback is
+ generated in the form:</p>
+
+ <pre class="c++">
+virtual bool
+&lt;name>_next ();
+ </pre>
+
+ <p>This callback is called before each new item of the sequence is
+ about to be serialized. Returning <code>false</code> from this
+ callback indicates that no more items in the sequence need to
+ be serialized. For example:</p>
+
+ <pre>
+&lt;xs:complexType name="names">
+ &lt;xs:sequence maxOccurs="unbounded">
+ &lt;xs:element name="first" type="xs:string"/>
+ &lt;xs:element name="last" type="xs:string"/>
+ &lt;xs:element name="pseudonym" type="xs:string" maxOccurs="3"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+class names_sskel: public xml_schema::serializer_complex_content
+{
+public:
+ virtual void
+ pre ();
+
+ virtual bool
+ sequence_next () = 0;
+
+ virtual std::string
+ first () = 0;
+
+ virtual std::string
+ last () = 0;
+
+ virtual bool
+ pseudonym_next () = 0;
+
+ virtual std::string
+ pseudonym () = 0;
+
+ virtual void
+ post ();
+};
+ </pre>
+
+ <h2><a name="5.3">5.3 Choice Callback</a></h2>
+
+ <p>The choice compositor allows an XML document to contain one
+ of several element or compositor options. In the Embedded
+ C++/Serializer mapping, these options are called <em>choice
+ arms</em> and are identified by the <em>arm tags</em>. For
+ example:</p>
+
+ <pre>
+&lt;xs:complexType name="name">
+ &lt;xs:choice>
+ &lt;xs:element name="full-name" type="xs:string"/>
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;/xs:choice>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+class name_sskel: public xml_schema::serializer_complex_content
+{
+public:
+ virtual void
+ pre ();
+
+ enum choice_arm_tag
+ {
+ full_name_tag,
+ sequence_tag
+ };
+
+ virtual choice_arm_tag
+ choice_arm () = 0;
+
+ virtual std::string
+ full_name () = 0;
+
+ virtual std::string
+ first_name () = 0;
+
+ virtual std::string
+ last_name () = 0;
+
+ virtual void
+ post ();
+};
+ </pre>
+
+ <p>The arm tags enum name (<code>choice_arm_tag</code> above) is derived
+ from the choice compositor name (that is, <code>choice</code>,
+ <code>choice1</code>, etc.) by adding the <code>_arm_tag</code>
+ suffix. The tag names themselves are derived from the corresponding
+ elements, compositors, or element wildcards.</p>
+
+ <p>The choice compositor callback has a name in the form
+ <code>choice_tag()</code> (or <code>choice1_tag()</code>, etc., for
+ subsequent <code>choice</code> compositors in the type). It returns
+ the arm tag which identifies the choice arm that should be
+ serialized. For example, if a <code>name_sskel</code> implementation
+ returns <code>full_name_tag</code> from the <code>choice_arm()</code>
+ callback, then the first choice arm is chosen and
+ the <code>full_name()</code> callback is then called. Otherwise
+ the <code>first_name</code> and <code>last_name()</code> callbacks
+ are called.</p>
+
+
+ <h2><a name="5.4">5.4 Element Wildcard Callbacks</a></h2>
+
+ <p>An element wildcard allows an arbitrary element from the specified
+ namespace list to be present in an XML instance. Element wildcards
+ can have the same cardinality constraints as elements and, as as a
+ result, the optional or sequence callbacks can be generated. For
+ example:</p>
+
+ <pre>
+&lt;xs:complexType name="name">
+ &lt;xs:sequence>
+ &lt;xs:element name="first" type="xs:string"/>
+ &lt;xs:element name="last" type="xs:string"/>
+ &lt;xs:any namespace="##other" processContents="skip" minOccurs="0"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+class name_sskel: public xml_schema::serializer_complex_content
+{
+public:
+ virtual void
+ pre ();
+
+ virtual std::string
+ first () = 0;
+
+ virtual std::string
+ last () = 0;
+
+ virtual bool
+ any_present ();
+
+ virtual void
+ any (std::string&amp; ns, std::string&amp; name);
+
+ virtual void
+ serialize_any ();
+
+ virtual void
+ post ();
+};
+ </pre>
+
+ <p>The <code>any()</code> callback is called to obtain the element
+ name and namespace. If validation is enabled, the namespace is
+ checked against the allowed list. Then an element with these name
+ and namespace is created and the <code>serialize_any()</code>
+ callback is called to allow you to serialize the element's attributes
+ and content. There are two common ways to serialize a wildcard
+ element. The first approach is to use a serializer implementation.
+ This approach is shown in the <code>wildcard</code> example which
+ is part of the XSD/e distribution. The other approach is to use
+ the low-level XML serialization API that is available to every
+ serializer implementation via the
+ <code>xml_schema::serializer_base</code> base serializer:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class serializer_base
+ {
+ public:
+ void
+ _start_element (const char* name);
+
+ void
+ _start_element (const char* ns, const char* name);
+
+ void
+ _end_element ();
+
+ void
+ _start_attribute (const char* name);
+
+ void
+ _start_attribute (const char* ns, const char* name);
+
+ void
+ _end_attribute ();
+
+ void
+ _attribute (const char* name, const char* value);
+
+ void
+ _attribute (const char* ns, const char* name, const char* value);
+
+ void
+ _characters (const char*);
+
+ void
+ _characters (const char*, size_t);
+
+ void
+ _declare_namespace (const char* ns, const char* prefix);
+
+ void
+ _declare_default_namespace (const char* ns);
+
+ void
+ _clear_default_namespace ();
+ };
+}
+ </pre>
+
+ <p>The following example shows how we could implement the
+ <code>name_sskel</code> skeleton using this approach:</p>
+
+ <pre class="c++">
+class name_simpl: public name_sskel
+{
+public:
+ virtual std::string
+ first ()
+ {
+ return "John";
+ }
+
+ virtual ::std::string
+ last ()
+ {
+ return "Doe";
+ }
+
+ virtual bool
+ any_present ()
+ {
+ return true;
+ }
+
+ virtual void
+ any (std::string&amp; ns, std::string&amp; name)
+ {
+ ns = "http://www.example.com/extension";
+ name = "pseudonyms";
+ }
+
+ virtual void
+ serialize_any ()
+ {
+ _attribute ("id", "jd");
+
+ _start_element ("pseudonym");
+ _characters ("Johnny Doer");
+ _end_element ();
+
+ _start_element ("pseudonym");
+ _characters ("Johnty Doo");
+ _end_element ();
+ }
+};
+ </pre>
+
+
+ <h2><a name="5.5">5.5 Attribute Wildcard Callbacks</a></h2>
+
+ <p>An attribute wildcard allows an arbitrary number of attributes from
+ the specified namespace list to be present in an XML instance. As a
+ result, the serializer callbacks for an attribute wildcard resemble
+ those of an element with <code>maxOccurs="unbounded"</code>. For
+ example:</p>
+
+ <pre>
+&lt;xs:complexType name="name">
+ &lt;xs:sequence>
+ &lt;xs:element name="first" type="xs:string"/>
+ &lt;xs:element name="last" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;xs:anyAttribute namespace="##any" processContents="skip"/>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The above schema fragment, when compiled, results in the following
+ serializer skeleton:</p>
+
+ <pre class="c++">
+class name_sskel: public xml_schema::serializer_complex_content
+{
+public:
+ virtual void
+ pre ();
+
+ virtual bool
+ any_attribute_next ();
+
+ virtual void
+ any_attribute (std::string&amp; ns, std::string&amp; name);
+
+ virtual void
+ serialize_any_attribute ();
+
+ virtual std::string
+ first () = 0;
+
+ virtual std::string
+ last () = 0;
+
+ virtual void
+ post ();
+};
+ </pre>
+
+ <p>Every time the <code>any_attribute_next()</code> callback returns
+ <code>true</code>, <code>any_attribute()</code> is called to obtain
+ the attribute name and namespace. If validation is enabled, the
+ namespace is checked against the allowed list. Then an attribute
+ with these name and namespace is created and the
+ <code>serialize_any_attribute()</code> callback is called to allow
+ you to write the attribute value, for example using one of the
+ serializer implementations (see the <code>wildcard</code> example
+ on how to do it) or the low-level <code>_characters()</code> function
+ (for more information about the low-level XML serialization
+ API see the previous section). The following example show
+ how we could implement the <code>name_sskel</code> skeleton
+ using the latter approach:</p>
+
+ <pre class="c++">
+class name_simpl: public name_sskel
+{
+public:
+ virtual void
+ pre ()
+ {
+ id_written_ = false;
+ }
+
+ virtual bool
+ any_attribute_next ()
+ {
+ return !id_written_;
+ }
+
+ virtual void
+ any_attribute (std::string&amp; ns, std::string&amp; name)
+ {
+ ns = "";
+ name = "id";
+ }
+
+ virtual void
+ serialize_any_attribute ()
+ {
+ _characters ("jd");
+ id_written_ = true;
+ }
+
+ virtual std::string
+ first ()
+ {
+ return "John";
+ }
+
+ virtual ::std::string
+ last ()
+ {
+ return "Doe";
+ }
+
+private:
+ bool id_written_;
+};
+ </pre>
+
+
+ <!-- Mapping Configuration -->
+
+
+ <h1><a name="6">6 Mapping Configuration</a></h1>
+
+ <p>The Embedded C++/Serializer mapping has a number of configuration
+ parameters that determine the overall properties and behavior
+ of the generated code, such as the use of Standard Template
+ Library (STL), Input/Output Stream Library (iostream), C++
+ exceptions, XML Schema validation, 64-bit integer types, serializer
+ implementation reuse styles, and support for XML Schema polymorphism.
+ Previous chapters assumed that the use of STL, iostream, C++
+ exceptions, and XML Schema validation were enabled.
+ This chapter will discuss the changes in the Embedded C++/Serializer
+ programming model that result from the changes to these configuration
+ parameters. A complete example that uses the minimal mapping
+ configuration is presented at the end of this chapter.</p>
+
+ <p>In order to enable or disable a particular feature, the corresponding
+ configuration parameter should be set accordingly in the XSD/e runtime
+ library as well as specified during schema compilation with the XSD/e
+ command line options as described in the
+ <a href="http://www.codesynthesis.com/projects/xsde/documentation/xsde.xhtml">XSD/e
+ Compiler Command Line Manual</a>.
+ </p>
+
+ <p>The Embedded C++/Serializer mapping always expects character data
+ supplied by the application to be in the same encoding. The
+ application encoding can either be UTF-8 (default) or ISO-8859-1.
+ To select a particular encoding, configure the XSD/e runtime library
+ accordingly and pass the <code>--char-encoding</code> option to the
+ XSD/e compiler when translating your schemas. The underlying XML
+ serializer used by the Embedded C++/Serializer mapping produces
+ the resulting XML documents in the UTF-8 encoding.</p>
+
+ <h2><a name="6.1">6.1 Standard Template Library</a></h2>
+
+ <p>To disable the use of STL you will need to configure the XSD/e
+ runtime without support for STL as well as pass the
+ <code>--no-stl</code> option to the XSD/e compiler when
+ translating your schemas. When STL is disabled, all string-based
+ XML Schema types are mapped to C-style <code>const char*</code>
+ instead of <code>std::string</code>, as described in
+ <a href="#4.2">Section 4.2, "Type Map File Format"</a>. The
+ following code fragment shows changes in the
+ signatures of the <code>first_name()</code> and <code>last_name()</code>
+ callbacks from the person record example.</p>
+
+ <pre class="c++">
+class person_sskel
+{
+public:
+ virtual const char*
+ first_name ();
+
+ virtual const char*
+ last_name ();
+
+ ...
+};
+ </pre>
+
+ <p>When STL is disabled, the serializer implementations for the string-based
+ built-in XML Schema types can be instructed to release the string
+ after serialization using operator <code>delete[]</code>. For more
+ information on how to do this refer to <a href="#7.2">Section 7.2,
+ "String-Based Type Serializers"</a>.
+ </p>
+
+ <h2><a name="6.2">6.2 Input/Output Stream Library</a></h2>
+
+ <p>To disable the use of iostream you will need to configure the
+ XSD/e runtime library without support for iostream as well as
+ pass the <code>--no-iostream</code> option to the XSD/e compiler
+ when translating your schemas. When iostream is disabled, the
+ following <code>serialize()</code> function in the
+ <code>xml_schema::document_simpl</code> class become unavailable:</p>
+
+ <pre class="c++">
+void
+serialize (std::ostream&amp;, flags);
+ </pre>
+
+ <p>See <a href="#8.1">Section 8.1, "Document Serializer"</a>
+ for more information.</p>
+
+ <h2><a name="6.3">6.3 C++ Exceptions</a></h2>
+
+ <p>To disable the use of C++ exceptions, you will need to configure
+ the XSD/e runtime without support for exceptions as well as pass
+ the <code>--no-exceptions</code> option to the XSD/e compiler
+ when translating your schemas. When C++ exceptions are disabled,
+ the error conditions are indicated with error codes instead of
+ exceptions, as described in <a href="#8.3">Section 8.3,
+ "Error Codes"</a>.
+ </p>
+
+ <h2><a name="6.4">6.4 XML Schema Validation</a></h2>
+
+ <p>To disable support for XML Schema validation, you will need to
+ configure the XSD/e runtime accordingly as well as pass
+ the <code>--suppress-validation</code> option to the XSD/e compiler
+ when translating your schemas. Disabling XML Schema validation
+ allows to further increase the serialization performance and
+ reduce footprint in cases where the data being serialized is
+ known to be valid.
+ </p>
+
+ <h2><a name="6.5">6.5 64-bit Integer Type</a></h2>
+
+ <p>By default the 64-bit <code>long</code> and <code>unsignedLong</code>
+ XML Schema built-in types are mapped to the 64-bit <code>long long</code>
+ and <code>unsigned long long</code> fundamental C++ types. To
+ disable the use of these types in the mapping you will need to
+ configure the XSD/e runtime accordingly as well as pass
+ the <code>--no-long-long</code> option to the XSD/e compiler
+ when translating your schemas. When the use of 64-bit integral
+ C++ types is disabled the <code>long</code> and
+ <code>unsignedLong</code> XML Schema built-in types are mapped
+ to <code>long</code> and <code>unsigned long</code> fundamental
+ C++ types.</p>
+
+ <h2><a name="6.6">6.6 Serializer Reuse</a></h2>
+
+ <p>When one type in XML Schema inherits from another, it is
+ often desirable to be able to reuse the serializer implementation
+ corresponding to the base type in the serializer implementation
+ corresponding to the derived type. XSD/e provides support
+ for two serializer reuse styles: the so-called <em>mixin</em>
+ (generated when the <code>--reuse-style-mixin</code> option
+ is specified) and <em>tiein</em> (generated by default) styles.</p>
+
+ <p>The compiler can also be instructed not to generate any support
+ for serializer reuse with the <code>--reuse-style-none</code> option.
+ This is mainly useful to further reduce the generated code size
+ when your vocabulary does not use inheritance or when you plan
+ to implement each serializer from scratch. Note also that the
+ XSD/e runtime should be configured in accordance with the
+ serializer reuse style used in the generated code. The remainder
+ of this section discusses the mixin and tiein serializer reuse
+ styles in more detail.</p>
+
+
+ <p>To provide concrete examples for each reuse style we will use the
+ following schema fragment:</p>
+
+ <pre class="xml">
+&lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="first-name" type="xs:string"/>
+ &lt;xs:element name="last-name" type="xs:string"/>
+ &lt;xs:element name="age" type="xs:short"/>
+ &lt;/xs:sequence>
+&lt;/xs:complexType>
+
+&lt;xs:complexType name="emplyee">
+ &lt;complexContent>
+ &lt;extension base="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="position" type="xs:string"/>
+ &lt;xs:element name="salary" type="xs:unsignedLong"/>
+ &lt;/xs:sequence>
+ &lt;/extension>
+ &lt;/complexContent>
+&lt;/xs:complexType>
+ </pre>
+
+ <p>The mixin serializer reuse style uses the C++ mixin idiom that
+ relies on multiple and virtual inheritance. Because
+ virtual inheritance can result in a significant object
+ code size increase, this reuse style should be considered
+ when such an overhead is acceptable and/or the vocabulary
+ consists of only a handful of types. When the mixin reuse
+ style is used, the generated serializer skeletons use virtual
+ inheritance, for example:</p>
+
+ <pre class="c++">
+class person_sskel: public virtual serializer_complex_content
+{
+ ...
+};
+
+class employee_sskel: public virtual person_sskel
+{
+ ...
+};
+ </pre>
+
+
+ <p>When you implement the base serializer you also need to use
+ virtual inheritance. The derived serializer is implemented
+ by inheriting from both the derived serializer skeleton and
+ the base serializer implementation (that is, <em>mixing in</em>
+ the base serializer implementation), for example:</p>
+
+ <pre class="c++">
+class person_simpl: public virtual person_sskel
+{
+ ...
+};
+
+class employee_simpl: public employee_sskel,
+ public person_simpl
+{
+ ...
+};
+ </pre>
+
+
+ <p>The tiein serializer reuse style uses delegation and normally
+ results in a significantly smaller object code while being
+ almost as convenient to use as the mixin style. When the
+ tiein reuse style is used, the generated derived serializer
+ skeleton declares a constructor which allows you to specify
+ the implementation of the base serializer:</p>
+
+ <pre class="c++">
+class person_sskel: public serializer_complex_content
+{
+ ...
+};
+
+class employee_sskel: public person_sskel
+{
+public:
+ employee_sskel (person_sskel* base_impl)
+
+ ...
+};
+ </pre>
+
+ <p>If you pass the implementation of the base serializer to this
+ constructor then the generated code will transparently
+ forward all the callbacks corresponding to the base serializer
+ skeleton to this implementation. You can also pass
+ <code>0</code> to this constructor in which case you will
+ need to implement the derived serializer from scratch. The
+ following example shows how we could implement the
+ <code>person</code> and <code>employee</code> serializers
+ using the tiein style:</p>
+
+ <pre class="c++">
+class person_simpl: public person_sskel
+{
+ ...
+};
+
+class employee_simpl: public employee_sskel
+{
+public:
+ employee_simpl ()
+ : employee_sskel (&amp;base_impl_)
+ {
+ }
+
+ ...
+
+private:
+ person_simpl base_impl_;
+};
+ </pre>
+
+ <p>Note that you cannot use the <em>tied in</em> base serializer
+ instance (<code>base_impl_</code> in the above code) for
+ serializing anything except the derived type.</p>
+
+ <p>The ability to override the base serializer callbacks in the
+ derived serializer is also available in the tiein style. For
+ example, the following code fragment shows how we can
+ override the <code>age()</code> callback if we didn't
+ like the implementation provided by the base serializer:</p>
+
+ <pre class="c++">
+class employee_simpl: public employee_sskel
+{
+public:
+ employee_simpl ()
+ : employee_sskel (&amp;base_impl_)
+ {
+ }
+
+ virtual short
+ age ()
+ {
+ ...
+ }
+
+ ...
+
+private:
+ person_simpl base_impl_;
+};
+ </pre>
+
+ <p>In the above example the <code>age</code> element will be
+ handled by <code>emplyee_simpl</code> while the <code>first-name</code>
+ and <code>last-name</code> callbacks will still go to
+ <code>base_impl_</code>.</p>
+
+ <p>It is also possible to inherit from the base serializer implementation
+ instead of declaring it as a member variable. This can be useful
+ if you need to access protected members in the base implementation
+ or need to override a virtual function that is not part of
+ the serializer skeleton interface. Note, however, that in this case
+ you will need to resolve a number of ambiguities with explicit
+ qualifications or using-declarations. For example:</p>
+
+
+ <pre class="c++">
+class person_simpl: public person_sskel
+{
+public:
+ virtual void
+ pre (person* p)
+ {
+ person_ = p;
+ }
+
+ ...
+
+protected:
+ person* person_;
+};
+
+class employee_simpl: public employee_sskel,
+ public person_simpl
+{
+public:
+ employee_simpl ()
+ : employee_sskel (static_cast&lt;person_simpl*> (this))
+ {
+ }
+
+ // Resolve ambiguities.
+ //
+ using emplyee_sskel::serializers;
+
+ virtual void
+ pre (employee* e)
+ {
+ person_simpl::pre (e);
+ }
+
+ virtual std::string
+ position ()
+ {
+ return static_cast&lt;employee*> (person_)->position ();
+ }
+
+ virtual unsigned int
+ salary ()
+ {
+ return static_cast&lt;employee*> (person_)->salary ();
+ }
+};
+ </pre>
+
+ <h2><a name="6.7">6.7 Support for Polymorphism</a></h2>
+
+ <p>By default the XSD/e compiler generates non-polymorphic code. If your
+ vocabulary uses XML Schema polymorphism in the form of <code>xsi:type</code>
+ and/or substitution groups, then you will need to configure the XSD/e
+ runtime with support for polymorphism, compile your schemas with the
+ <code>--generate-polymorphic</code> option to produce polymorphism-aware
+ code, as well as pass <code>true</code> as the last argument to the
+ <code>xml_schema::document</code>'s constructors. If some of your
+ schemas do not require support for polymorphism then you can compile
+ them with the <code>--runtime-polymorphic</code> option and still
+ use the XSD/e runtime configured with polymorphism support.
+ </p>
+
+ <p>When using the polymorphism-aware generated code, you can specify
+ several serializers for a single element by passing a serializer map
+ instead of an individual serializer to the serializer connection function
+ for the element. One of the serializers will then be looked up and used
+ depending on the user-provided type information that can optionally be
+ set in the callback function for the element. Consider the following
+ schema as an example:</p>
+
+ <pre class="xml">
+&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ &lt;xs:complexType name="person">
+ &lt;xs:sequence>
+ &lt;xs:element name="name" type="xs:string"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;!-- substitution group root -->
+ &lt;xs:element name="person" type="person"/>
+
+ &lt;xs:complexType name="superman">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="person">
+ &lt;xs:attribute name="can-fly" type="xs:boolean"/>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="superman"
+ type="superman"
+ substitutionGroup="person"/>
+
+ &lt;xs:complexType name="batman">
+ &lt;xs:complexContent>
+ &lt;xs:extension base="superman">
+ &lt;xs:attribute name="wing-span" type="xs:unsignedInt"/>
+ &lt;/xs:extension>
+ &lt;/xs:complexContent>
+ &lt;/xs:complexType>
+
+ &lt;xs:complexType name="supermen">
+ &lt;xs:sequence>
+ &lt;xs:element ref="person" maxOccurs="unbounded"/>
+ &lt;/xs:sequence>
+ &lt;/xs:complexType>
+
+ &lt;xs:element name="supermen" type="supermen"/>
+
+&lt;/xs:schema>
+ </pre>
+
+ <p>Conforming XML documents can use the <code>superman</code>
+ and <code>batman</code> types in place of the <code>person</code>
+ type either by specifying the type with the <code>xsi:type</code>
+ attributes or by using the elements from the substitution
+ group, for instance:</p>
+
+ <pre class="xml">
+&lt;supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ &lt;person>
+ &lt;name>John Doe&lt;/name>
+ &lt;/person>
+
+ &lt;superman can-fly="false">
+ &lt;name>James "007" Bond&lt;/name>
+ &lt;/superman>
+
+ &lt;person can-fly="true" wing-span="10" xsi:type="batman">
+ &lt;name>Bruce Wayne&lt;/name>
+ &lt;/person>
+
+&lt;/supermen>
+ </pre>
+
+ <p>The C++ object model for this vocabulary might look as follows:</p>
+
+ <pre class="c++">
+#include &lt;string>
+#include &lt;vector>
+
+enum type_id
+{
+ person_type,
+ superman_type,
+ batman_type
+};
+
+class person
+{
+public:
+ virtual
+ ~person () {}
+
+ person (const std::string&amp; name)
+ : name_ (name)
+ {
+ }
+
+ const std::string&amp;
+ name () const
+ {
+ return name_;
+ }
+
+ void
+ name (const std::string&amp; n)
+ {
+ name_ = n;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return person_type;
+ }
+
+private:
+ std::string name_;
+};
+
+class superman: public person
+{
+public:
+ superman (const std::string&amp; name, bool can_fly)
+ : person (name), can_fly_ (can_fly)
+ {
+ }
+
+ bool
+ can_fly () const
+ {
+ return can_fly_;
+ }
+
+ void
+ can_fly (bool cf)
+ {
+ can_fly_ = cf;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return superman_type;
+ }
+
+private:
+ bool can_fly_;
+};
+
+class batman: public superman
+{
+public:
+ batman (const std::string&amp; name, unsigned int wing_span)
+ : superman (name, true), wing_span_ (wing_span)
+ {
+ }
+
+ unsigned int
+ wing_span () const
+ {
+ return wing_span_;
+ }
+
+ void
+ wing_span (unsigned int ws)
+ {
+ wing_span_ = ws;
+ }
+
+ virtual type_id
+ type () const
+ {
+ return batman_type;
+ }
+
+private:
+ unsigned int wing_span_;
+};
+
+// Poor man's polymorphic sequence which also assumes ownership
+// of the elements.
+//
+class supermen: public std::vector&lt;person*>
+{
+public:
+ ~supermen ()
+ {
+ for (iterator i = begin (); i != end (); ++i)
+ delete *i;
+ }
+};
+ </pre>
+
+ <p>Here we choose to provide our own type information. We can instead
+ use the standard C++ <code>typeid</code>/<code>type_info</code>
+ mechanism if it is available. The type map corresponding to this
+ object model is presented below. Notice that the <code>superman</code>
+ and <code>batman</code> objects are passed as a reference to
+ <code>person</code>:</p>
+
+ <pre>
+person "const ::person&amp;";
+superman "const ::person&amp;";
+batman "const ::person&amp;";
+supermen "const ::supermen&amp;";
+ </pre>
+
+ <p>The serializer implementations that serialize the above
+ C++ object model to XML are presented next:</p>
+
+ <pre class="c++">
+class person_simpl: public person_sskel
+{
+public:
+ virtual void
+ pre (const person&amp; p)
+ {
+ person_ = &amp;p;
+ }
+
+ virtual std::string
+ name ()
+ {
+ return person_->name ();
+ }
+
+ // Derived serializer implementations need access to this
+ // member variable.
+ //
+public:
+ const person* person_;
+};
+
+class superman_simpl: public superman_sskel
+{
+public:
+ superman_simpl ()
+ : superman_sskel (&amp;base_impl_)
+ {
+ }
+
+ virtual bool
+ can_fly ()
+ {
+ return superman_ ().can_fly ();
+ }
+
+ const superman&amp;
+ superman_ ()
+ {
+ return *static_cast&lt;const superman*> (base_impl_.person_);
+ }
+
+private:
+ person_simpl base_impl_;
+};
+
+class batman_simpl: public batman_sskel
+{
+public:
+ batman_simpl ()
+ : batman_sskel (&amp;base_impl_)
+ {
+ }
+
+ virtual unsigned int
+ wing_span ()
+ {
+ return batman_ ().wing_span ();
+ }
+
+ const batman&amp;
+ batman_ ()
+ {
+ return static_cast&lt;const batman&amp;> (base_impl_.superman_ ());
+ }
+
+private:
+ superman_simpl base_impl_;
+};
+
+class supermen_simpl: public supermen_sskel
+{
+public:
+ virtual void
+ pre (const supermen&amp; s)
+ {
+ supermen_ = &amp;s;
+ i_ = s.begin ();
+ }
+
+ virtual bool
+ person_next ()
+ {
+ return i_ != supermen_->end ();
+ }
+
+ virtual const ::person&amp;
+ person ()
+ {
+ const ::person&amp; p = **i_++;
+ xml_schema::serializer_context&amp; ctx = _context ();
+
+ switch (p.type ())
+ {
+ case person_type:
+ {
+ ctx.type_id (person_sskel::_static_type ());
+ break;
+ }
+ case superman_type:
+ {
+ ctx.type_id (superman_sskel::_static_type ());
+ break;
+ }
+ case batman_type:
+ {
+ ctx.type_id (batman_sskel::_static_type ());
+ break;
+ }
+ }
+
+ return p;
+ }
+
+private:
+ const supermen* supermen_;
+ supermen::const_iterator i_;
+};
+ </pre>
+
+ <p>Most of the code in these serializer implementations is the same
+ as in the non-polymorphic case. The only part that explicitly deals
+ with polymorphism is the <code>person()</code> callback in the
+ <code>superman_simpl</code> class. In it we are translating
+ the type information as provided by the C++ object mode to
+ the type information used in the default implementation of
+ the serializer map (we will talk more about serializer maps
+ as well as the <code>_static_type()</code> function shortly).
+ The <code>type_id()</code> function from
+ <code>xml_schema::serializer_context</code> allows you to
+ specify optional type information which is used to look up
+ the corresponding serializer. Its argument is of type
+ <code>const void*</code> which allows you to pass
+ application-specific type information as an opaque pointer.</p>
+
+ <p>The following code fragment shows how to connect the serializers
+ together and then use them to serialize a sample object model.
+ Notice that for the <code>person</code> element in the
+ <code>instance_s</code> serializer we specify a serializer map
+ instead of a specific serializer and we pass <code>true</code> as
+ the last argument to the document serializer constructor to indicate
+ that we are serializing potentially-polymorphic XML documents:</p>
+
+ <pre class="c++">
+int
+main ()
+{
+ // Create a sample supermen catalog. To keep things simple
+ // the following code is not exception-safe.
+ //
+ supermen sm;
+
+ sm.push_back (new person ("John Doe"));
+ sm.push_back (new superman ("James 007 Bond", false));
+ sm.push_back (new batman ("Bruce Wayne", 10));
+
+ // Construct the serializer.
+ //
+ xml_schema::string_simpl string_s;
+ xml_schema::boolean_simpl boolean_s;
+ xml_schema::unsigned_int_simpl unsigned_int_s;
+
+ person_simpl person_s;
+ superman_simpl superman_s;
+ batman_simpl batman_s;
+
+ xml_schema::serializer_map_impl person_map (5); // 5 hashtable buckets
+ supermen_simpl supermen_s;
+
+ person_s.serializers (string_s);
+ superman_s.serializers (string_s, boolean_s);
+ batman_s.serializers (string_s, boolean_s, unsigned_int_s);
+
+ // Here we are specifying several serializers that can be
+ // used to serialize the person element.
+ //
+ person_map.insert (person_s);
+ person_map.insert (superman_s);
+ person_map.insert (batman_s);
+
+ supermen_s.person_serializer (person_map);
+
+ // Create the XML instance document. The last argument to the
+ // document's constructor indicates that we are serializing
+ // polymorphic XML documents.
+ //
+ xml_schema::document_simpl doc_s (supermen_s, "supermen", true);
+
+ supermen_s.pre (sm);
+ doc_s.serialize (std::cout, xml_schema::document_simpl::pretty_print);
+ supermen_s.post ();
+}
+ </pre>
+
+ <p>When polymorphism-aware code is generated, each element's
+ <code>*_serializer()</code> function is overloaded to also accept
+ an object of the <code>xml_schema::serializer_map</code> type.
+ For example, the <code>supermen_sskel</code> class from the
+ above example looks like this:</p>
+
+ <pre class="c++">
+class supermen_sskel: public xml_schema::serializer_complex_content
+{
+public:
+
+ ...
+
+ // Serializer construction API.
+ //
+ void
+ serializers (person_sskel&amp;);
+
+ // Individual element serializers.
+ //
+ void
+ person_serializer (person_sskel&amp;);
+
+ void
+ person_serializer (xml_schema::serializer_map&amp;);
+
+ ...
+};
+ </pre>
+
+ <p>Note that you can specify both the individual (static) serializer and
+ the serializer map. The individual serializer will be used when the static
+ element type and the dynamic type of the object being serialized are
+ the same. This is the case when the <code>type_id()</code> function
+ hasn't been called or the type information pointer is set to
+ <code>0</code>. Because the individual serializer for an element
+ is cached and no map lookup is necessary, it makes sense to specify
+ both the individual serializer and the serializer map when most of
+ the objects being serialized are of the static type and optimal
+ performance is important. The following code fragment shows how
+ to change the above example to set both the individual serializer
+ and the serializer map:</p>
+
+ <pre class="c++">
+int
+main ()
+{
+ ...
+
+ // Here we are specifying several serializers that can be
+ // used to serialize the person element.
+ //
+ person_map.insert (superman_s);
+ person_map.insert (batman_s);
+
+ supermen_s.person_serializer (person_s);
+ supermen_s.person_serializer (person_map);
+
+ ...
+}
+ </pre>
+
+
+ <p>The <code>xml_schema::serializer_map</code> interface and its
+ default implementation, <code>xml_schema::serializer_map_impl</code>,
+ are presented below:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class serializer_map
+ {
+ public:
+ virtual serializer_base*
+ find (const void* type_id) const = 0;
+
+ virtual void
+ reset () const = 0;
+ };
+
+ class serializer_map_impl: public serializer_map
+ {
+ public:
+ serializer_map_impl (size_t buckets);
+
+ // Note that the type_id string is not copied so it should
+ // be valid for the lifetime of the map.
+ //
+ void
+ insert (const char* type_id, serializer_base&amp;);
+
+ // This version of insert is a shortcut that uses the string
+ // returned by the serializer's _dynamic_type() function.
+ //
+ void
+ insert (serializer_base&amp;);
+
+ virtual serializer_base*
+ find (const void* type_id) const;
+
+ virtual void
+ reset () const;
+
+ private:
+ serializer_map_impl (const serializer_map_impl&amp;);
+
+ serializer_map_impl&amp;
+ operator= (const serializer_map_impl&amp;);
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>type_id</code> argument in the <code>find()</code> virtual
+ function is the application-specific type information for the object
+ being serialized that is specified using the <code>type_id()</code>
+ function in the element callback. It is passed as an opaque
+ <code>const void*</code>. The <code>reset()</code> virtual function
+ is used to reset the serializers contained in the map (as opposed to
+ resetting or clearing the map itself). For more information on serializer
+ resetting refer to <a href="#8.4">Section 8.4, "Reusing Serializers
+ after an Error"</a>.</p>
+
+ <p>The XSD/e runtime provides the default implementation for the
+ <code>xml_schema::serializer_map</code> interface,
+ <code>xml_schema::serializer_map_impl</code>, which uses a C string
+ (<code>const char*</code>) as type information. One way to
+ obtain a serializer's dynamic type in the form
+ <code>"&lt;name>&nbsp;&lt;namespace>"</code> with the space and the
+ namespace part absent if the type does not have a namespace
+ is to call the <code>_dynamic_type()</code> function on this
+ serializer. The static type can be obtained by calling the static
+ <code>_static_type()</code> function, for example
+ <code>person_sskel::_static_type()</code>. Both functions return
+ a C string (<code>const char*</code>) which is valid for as long
+ as the application is running.</p>
+
+ <p>The default serializer map implementation is a hashmap. It requires
+ that you specify the number of buckets it will contain and it does
+ not support automatic table resizing. To obtain good performance the
+ elements to buckets ratio should be between 0.7 and 0.9. It is also
+ recommended to use prime numbers for bucket counts:
+ 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317,
+ 196613, 393241.
+ </p>
+
+ <p>If C++ exceptions are disabled (<a href="#5.3">Section 5.3,
+ "C++ Exceptions"</a>), the <code>xml_schema::serializer_map_impl</code>
+ class has the following additional error querying API. It can be used
+ to detect the out of memory errors after calls to the
+ <code>serializer_map_impl</code>'s constructor and <code>insert()</code>
+ functions.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class serializer_map_impl: public serializer_map
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ error
+ _error () const;
+
+ ...
+ };
+}
+ </pre>
+
+ <p>You can also provide your own serializer map implementation which uses
+ custom type information. The following example shows how we can
+ implement our own serializer map for the above example that uses
+ the type information provided by the C++ object model:</p>
+
+ <pre class="c++">
+#include &lt;map>
+
+class person_serializer_map: public xml_schema::serializer_map
+{
+public:
+ void
+ insert (person_sskel&amp; p)
+ {
+ const char* dt = p._dynamic_type ();
+ type_id ti;
+
+ if (strcmp (dt, person_sskel::_static_type ()) == 0)
+ ti = person_type;
+ else if (strcmp (dt, superman_sskel::_static_type ()) == 0)
+ ti = superman_type;
+ else if (strcmp (dt, batman_sskel::_static_type ()) == 0)
+ ti = batman_type;
+ else
+ return;
+
+ map_[ti] = &amp;p;
+ }
+
+ virtual xml_schema::serializer_base*
+ find (const char* x) const
+ {
+ const person* p = static_cast&lt;const person*> (x);
+ map::const_iterator i = map_.find (p->type ());
+ return i != map_.end () ? i->second : 0;
+ }
+
+ virtual void
+ reset () const
+ {
+ for (map::const_iterator i (map_.begin ()), e (map_.end ());
+ i != e; ++i)
+ {
+ person_sskel* s = i->second;
+ s->_reset ();
+ }
+ }
+
+private:
+ typedef std::map&lt;type_id, person_sskel*> map;
+ map map_;
+};
+ </pre>
+
+ <p>Our custom implementation of the serializer map expects that
+ we pass the actual object to the <code>find()</code> function.
+ To account for this will need to change the
+ <code>supermen_simpl::person()</code> callback as follows:</p>
+
+ <pre class="c++">
+ virtual const ::person&amp;
+ person ()
+ {
+ const ::person&amp; p = **i_++;
+ _context ().type_id (&amp;p);
+ return p;
+ }
+ </pre>
+
+
+ <p>To support polymorphic serialization the XSD/e runtime and generated
+ code maintain a number of hashmaps that contain substitution and, if
+ XML Schema validation is enabled (<a href="#5.4">Section 5.4,
+ "XML Schema Validation"</a>), inheritance information. Because
+ the number of elements in these hashmaps depends on the schemas
+ being compiled and thus is fairly static, these hashmaps do not
+ perform automatic table resizing and instead the number of buckets
+ is specified when the XSD/e runtime is configured. To obtain good
+ performance the elements to buckets ratio in these hashmaps should
+ be between 0.7 and 0.9. The recommended way to ensure this range
+ is to add diagnostics code to your application as shown in the
+ following example:</p>
+
+ <pre class="c++">
+int
+main ()
+{
+ // Check that the load in substitution and inheritance hashmaps
+ // is not too high.
+ //
+#ifndef NDEBUG
+ float load = xml_schema::serializer_smap_elements ();
+ load /= xml_schema::serializer_smap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr &lt;&lt; "substitution hashmap load is " &lt;&lt; load &lt;&lt; endl;
+ cerr &lt;&lt; "time to increase XSDE_SERIALIZER_SMAP_BUCKETS" &lt;&lt; endl;
+ }
+
+ load = xml_schema::serializer_smap_bucket_elements ();
+ load /= xml_schema::serializer_smap_bucket_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr &lt;&lt; "substitution inner hashmap load is " &lt;&lt; load &lt;&lt; endl;
+ cerr &lt;&lt; "time to increase XSDE_SERIALIZER_SMAP_BUCKET_BUCKETS" &lt;&lt; endl;
+ }
+
+ load = xml_schema::serializer_imap_elements ();
+ load /= xml_schema::serializer_imap_buckets ();
+
+ if (load > 0.8)
+ {
+ cerr &lt;&lt; "inheritance hashmap load is " &lt;&lt; load &lt;&lt; endl;
+ cerr &lt;&lt; "time to increase XSDE_SERIALIZER_IMAP_BUCKETS" &lt;&lt; endl;
+ }
+#endif
+
+ ...
+}
+ </pre>
+
+ <p>Most of the code presented in this section is taken from the
+ <code>polymorphism</code> example which can be found in the
+ <code>examples/cxx/serializer/</code> directory of the XSD/e distribution.
+ Handling of <code>xsi:type</code> and substitution groups when used
+ on root elements requires a number of special actions as shown in
+ the <code>polyroot</code> example.</p>
+
+ <h2><a name="6.8">6.8 Custom Allocators</a></h2>
+
+ <p>By default the XSD/e runtime and generated code use
+ the standard operators <code>new</code> and <code>delete</code>
+ to manage dynamic memory. However, it is possible to instead
+ use custom allocator functions provided by your application.
+ To achieve this, configure the XSD/e runtime library to use
+ custom allocator functions as well as pass the
+ <code>--custom-allocator</code> option to the XSD/e compiler
+ when translating your schemas. The signatures of the custom
+ allocator functions that should be provided by your application
+ are listed below. Their semantics should be equivalent to the
+ standard C <code>malloc()</code>, <code>realloc()</code>, and
+ <code>free()</code> functions.</p>
+
+ <pre class="c++">
+extern "C" void*
+xsde_alloc (size_t);
+
+extern "C" void*
+xsde_realloc (void*, size_t);
+
+extern "C" void
+xsde_free (void*);
+ </pre>
+
+ <p>Note also that when custom allocators are enabled, any
+ dynamically-allocated object of which the XSD/e runtime
+ or generated code assume ownership should be allocated
+ using the custom allocation function. Similarly, if your
+ application assumes ownership of any dynamically-allocated
+ object returned by the XSD/e runtime or the generated code,
+ then such an object should be disposed of using the custom
+ deallocation function. To help with these tasks the generated
+ <code>xml_schema</code> namespace defines the following two
+ helper functions and, if C++ exceptions are enabled, automatic
+ pointer class:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ void*
+ alloc (size_t);
+
+ void
+ free (void*);
+
+ struct alloc_guard
+ {
+ alloc_guard (void*);
+ ~alloc_guard ();
+
+ void*
+ get () const;
+
+ void
+ release ();
+
+ private:
+ ...
+ };
+}
+ </pre>
+
+ <p>If C++ exceptions are disabled, these functions are equivalent
+ to <code>xsde_alloc()</code> and <code>xsde_free()</code>.
+ If exceptions are enabled, <code>xml_schema::alloc()</code>
+ throws <code>std::bad_alloc</code> on memory allocation failure.</p>
+
+ <p>The following code fragment shows how to create and destroy a
+ dynamically-allocated object with custom allocators when C++
+ exceptions are disabled:</p>
+
+ <pre class="c++">
+void* v = xml_schema::alloc (sizeof (type));
+
+if (v == 0)
+{
+ // Handle out of memory condition.
+}
+
+type* x = new (v) type (1, 2);
+
+...
+
+if (x)
+{
+ x->~type ();
+ xml_schema::free (x);
+}
+ </pre>
+
+ <p>The equivalent code fragment for configurations with C++ exceptions
+ enabled is shown below:</p>
+
+ <pre class="c++">
+xml_schema::alloc_guard g (xml_schema::alloc (sizeof (type)));
+type* x = new (g.get ()) type (1, 2);
+g.release ();
+
+...
+
+if (x)
+{
+ x->~type ();
+ xml_schema::free (x);
+}
+ </pre>
+
+ <h2><a name="6.9">6.9 A Minimal Example</a></h2>
+
+ <p>The following example is a re-implementation of the person
+ records example presented in <a href="#4">Chapter 4,
+ "Type Maps"</a>. It is intended to work without STL,
+ iostream, and C++ exceptions. It can be found in the
+ <code>examples/cxx/serializer/minimal/</code> directory of the
+ XSD/e distribution. The <code>people.xsd</code> schema is
+ compiled with the <code>--no-stl</code>, <code>--no-iostream</code>,
+ and <code>--no-exceptions</code> options. The object model
+ types in <code>people.hxx</code> have also been reimplemented
+ in order not to use STL types:</p>
+
+ <pre class="c++">
+#include &lt;stddef.h> // size_t
+
+enum gender
+{
+ male,
+ female
+};
+
+struct person
+{
+ const char* first_name_;
+ const char* last_name_;
+ gender gender_;
+ unsigned short age_;
+};
+
+struct people
+{
+ person* people_;
+ size_t size_;
+};
+ </pre>
+
+
+ <p>The following listing presents the implementation of serializer
+ skeletons and the test driver in full:</p>
+
+ <pre class="c++">
+#include &lt;stdio.h>
+#include "people-sskel.hxx"
+
+const char* gender_strings[] = {"male", "female"};
+
+class gender_simpl: public gender_sskel
+{
+public:
+ gender_simpl ()
+ : gender_sskel (&amp;base_impl_)
+ {
+ }
+
+ virtual void
+ pre (gender g)
+ {
+ base_impl_.pre (gender_strings[g]);
+ }
+
+private:
+ public xml_schema::string_simpl base_impl_;
+};
+
+class person_simpl: public person_sskel
+{
+public:
+ virtual void
+ pre (const person&amp; p)
+ {
+ person_ = &amp;p;
+ }
+
+ virtual const char*
+ first_name ()
+ {
+ return person_->first_name_;
+ }
+
+ virtual const char*
+ last_name ()
+ {
+ return person_->last_name_;
+ }
+
+ virtual ::gender
+ gender ()
+ {
+ return person_->gender_;
+ }
+
+ virtual unsigned short
+ age ()
+ {
+ return person_->age_;
+ }
+
+private:
+ const person* person_;
+};
+
+class people_simpl: public people_sskel
+{
+public:
+ virtual void
+ pre (const people&amp; p)
+ {
+ i_ = 0;
+ people_ = &amp;p;
+ }
+
+ virtual bool
+ person_next ()
+ {
+ return i_ &lt; people_->size_;
+ }
+
+ virtual const ::person&amp;
+ person ()
+ {
+ return people_->people_[i_++];
+ }
+
+private:
+ size_t i_;
+ const people* people_;
+};
+
+class writer: public xml_schema::writer
+{
+public:
+ virtual bool
+ write (const char* s, size_t n)
+ {
+ return fwrite (s, n, 1, stdout) == 1;
+ }
+
+ virtual bool
+ flush ()
+ {
+ return fflush (stdout) == 0;
+ }
+};
+
+int
+main ()
+{
+ // Create a sample person list.
+ //
+ people p;
+
+ p.size_ = 2;
+ p.people_ = new person[p.size_];
+
+ if (p.people_ == 0)
+ {
+ fprintf (stderr, "error: no memory\n");
+ return 1;
+ }
+
+ p.people_[0].first_name_ = "John";
+ p.people_[0].last_name_ = "Doe";
+ p.people_[0].gender_ = male;
+ p.people_[0].age_ = 32;
+
+ p.people_[1].first_name_ = "Jane";
+ p.people_[1].last_name_ = "Doe";
+ p.people_[1].gender_ = female;
+ p.people_[1].age_ = 28;
+
+ // Construct the serializer.
+ //
+ xml_schema::unsigned_short_simpl unsigned_short_s;
+ xml_schema::string_simpl string_s;
+
+ gender_simpl gender_s;
+ person_simpl person_s;
+ people_simpl people_s;
+
+ person_s.serializers (string_s, string_s, gender_s, unsigned_short_s);
+ people_s.serializers (person_s);
+
+ // Serialize.
+ //
+ typedef xml_schema::serializer_error error;
+
+ error e;
+ writer w;
+
+ do
+ {
+ xml_schema::document_simpl doc_s (people_s, "people");
+
+ if (e = doc_s._error ())
+ break;
+
+ people_s.pre (p);
+
+ if (e = people_s._error ())
+ break;
+
+ doc_s.serialize (w, xml_schema::document_simpl::pretty_print);
+
+ if (e = doc_s._error ())
+ break;
+
+ people_s.post ();
+
+ e = people_s._error ();
+
+ } while (false);
+
+ delete[] p.people_;
+
+ // Handle errors.
+ //
+ if (e)
+ {
+ switch (e.type ())
+ {
+ case error::sys:
+ {
+ fprintf (stderr, "error: %s\n", e.sys_text ());
+ break;
+ }
+ case error::xml:
+ {
+ fprintf (stderr, "error: %s\n", e.xml_text ());
+ break;
+ }
+ case error::schema:
+ {
+ fprintf (stderr, "error: %s\n", e.schema_text ());
+ break;
+ }
+ case error::app:
+ {
+ fprintf (stderr, "application error: %d\n", e.app_code ());
+ break;
+ }
+ default:
+ break;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+ </pre>
+
+
+ <!-- Built-in XML Schema Type Serializers -->
+
+
+ <h1><a name="7">7 Built-In XML Schema Type Serializers</a></h1>
+
+ <p>The XSD/e runtime provides serializer implementations for all built-in
+ XML Schema types as summarized in the following table. Declarations
+ for these types are automatically included into each generated
+ header file. As a result you don't need to include any headers
+ to gain access to these serializer implementations.</p>
+
+ <!-- border="1" is necessary for html2ps -->
+ <table id="builtin" border="1">
+ <tr>
+ <th>XML Schema type</th>
+ <th>Serializer implementation in the <code>xml_schema</code> namespace</th>
+ <th>Serializer argument type</th>
+ </tr>
+
+ <tr>
+ <th colspan="3">anyType and anySimpleType types</th>
+ </tr>
+ <tr>
+ <td><code>anyType</code></td>
+ <td><code>any_type_simpl</code></td>
+ <td><code>void</code></td>
+ </tr>
+ <tr>
+ <td><code>anySimpleType</code></td>
+ <td><code>any_simple_type_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-length integral types</th>
+ </tr>
+ <!-- 8-bit -->
+ <tr>
+ <td><code>byte</code></td>
+ <td><code>byte_simpl</code></td>
+ <td><code>signed&nbsp;char</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedByte</code></td>
+ <td><code>unsigned_byte_simpl</code></td>
+ <td><code>unsigned&nbsp;char</code></td>
+ </tr>
+
+ <!-- 16-bit -->
+ <tr>
+ <td><code>short</code></td>
+ <td><code>short_simpl</code></td>
+ <td><code>short</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedShort</code></td>
+ <td><code>unsigned_short_simpl</code></td>
+ <td><code>unsigned&nbsp;short</code></td>
+ </tr>
+
+ <!-- 32-bit -->
+ <tr>
+ <td><code>int</code></td>
+ <td><code>int_simpl</code></td>
+ <td><code>int</code></td>
+ </tr>
+ <tr>
+ <td><code>unsignedInt</code></td>
+ <td><code>unsigned_int_simpl</code></td>
+ <td><code>unsigned&nbsp;int</code></td>
+ </tr>
+
+ <!-- 64-bit -->
+ <tr>
+ <td><code>long</code></td>
+ <td><code>long_simpl</code></td>
+ <td><code>long&nbsp;long</code> or <code>long</code><br/>
+ <a href="#6.5">Section 6.5, "64-bit Integer Type"</a></td>
+ </tr>
+ <tr>
+ <td><code>unsignedLong</code></td>
+ <td><code>unsigned_long_simpl</code></td>
+ <td><code>unsigned&nbsp;long&nbsp;long</code> or
+ <code>unsigned&nbsp;long</code><br/>
+ <a href="#6.5">Section 6.5, "64-bit Integer Type"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-length integral types</th>
+ </tr>
+ <tr>
+ <td><code>integer</code></td>
+ <td><code>integer_simpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonPositiveInteger</code></td>
+ <td><code>non_positive_integer_simpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+ <tr>
+ <td><code>nonNegativeInteger</code></td>
+ <td><code>non_negative_integer_simpl</code></td>
+ <td><code>unsigned&nbsp;long</code></td>
+ </tr>
+ <tr>
+ <td><code>positiveInteger</code></td>
+ <td><code>positive_integer_simpl</code></td>
+ <td><code>unsigned&nbsp;long</code></td>
+ </tr>
+ <tr>
+ <td><code>negativeInteger</code></td>
+ <td><code>negative_integer_simpl</code></td>
+ <td><code>long</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">boolean types</th>
+ </tr>
+ <tr>
+ <td><code>boolean</code></td>
+ <td><code>boolean_simpl</code></td>
+ <td><code>bool</code></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">fixed-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>float</code></td>
+ <td><code>float_simpl</code></td>
+ <td><code>float</code><br/>
+ <a href="#7.1">Section 7.1, "Floating-Point Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>double</code></td>
+ <td><code>double_simpl</code></td>
+ <td><code>double</code><br/>
+ <a href="#7.1">Section 7.1, "Floating-Point Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">arbitrary-precision floating-point types</th>
+ </tr>
+ <tr>
+ <td><code>decimal</code></td>
+ <td><code>decimal_simpl</code></td>
+ <td><code>double</code><br/>
+ <a href="#7.1">Section 7.1, "Floating-Point Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">string-based types</th>
+ </tr>
+ <tr>
+ <td><code>string</code></td>
+ <td><code>string_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>normalizedString</code></td>
+ <td><code>normalized_string_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>token</code></td>
+ <td><code>token_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>Name</code></td>
+ <td><code>name_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>NMTOKEN</code></td>
+ <td><code>nmtoken_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>NCName</code></td>
+ <td><code>ncname_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <td><code>language</code></td>
+ <td><code>language_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">qualified name</th>
+ </tr>
+ <tr>
+ <td><code>QName</code></td>
+ <td><code>qname_simpl</code></td>
+ <td><code>const xml_schema::qname&amp;</code> or<br/>
+ <code>const xml_schema::qname*</code><br/>
+ <a href="#7.3">Section 7.3, "<code>QName</code> Serializer"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">ID/IDREF types</th>
+ </tr>
+ <tr>
+ <td><code>ID</code></td>
+ <td><code>id_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREF</code></td>
+ <td><code>idref_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">list types</th>
+ </tr>
+ <tr>
+ <td><code>NMTOKENS</code></td>
+ <td><code>nmtokens_simpl</code></td>
+ <td><code>const xml_schema::string_sequence*</code><br/><a href="#7.4">Section
+ 7.4, "<code>NMTOKENS</code> and <code>IDREFS</code> Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>IDREFS</code></td>
+ <td><code>idrefs_simpl</code></td>
+ <td><code>const xml_schema::string_sequence*</code><br/><a href="#7.4">Section
+ 7.4, "<code>NMTOKENS</code> and <code>IDREFS</code> Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">URI types</th>
+ </tr>
+ <tr>
+ <td><code>anyURI</code></td>
+ <td><code>uri_simpl</code></td>
+ <td><code>const std::string&amp;</code> or<br/> <code>const char*</code><br/>
+ <a href="#7.2">Section 7.2, "String-Based Type Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">binary types</th>
+ </tr>
+ <tr>
+ <td><code>base64Binary</code></td>
+ <td><code>base64_binary_simpl</code></td>
+ <td><code>const xml_schema::buffer*</code><br/>
+ <a href="#7.5">Section 7.5, "<code>base64Binary</code> and
+ <code>hexBinary</code> Serializers"</a></td>
+ </tr>
+ <tr>
+ <td><code>hexBinary</code></td>
+ <td><code>hex_binary_simpl</code></td>
+ <td><code>const xml_schema::buffer*</code><br/>
+ <a href="#7.5">Section 7.5, "<code>base64Binary</code> and
+ <code>hexBinary</code> Serializers"</a></td>
+ </tr>
+
+ <tr>
+ <th colspan="3">date/time types</th>
+ </tr>
+ <tr>
+ <td><code>date</code></td>
+ <td><code>date_simpl</code></td>
+ <td><code>const xml_schema::date&amp;</code><br/>
+ <a href="#7.7">Section 7.7, "<code>date</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>dateTime</code></td>
+ <td><code>date_time_simpl</code></td>
+ <td><code>const xml_schema::date_time&amp;</code><br/>
+ <a href="#7.8">Section 7.8, "<code>dateTime</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>duration</code></td>
+ <td><code>duration_simpl</code></td>
+ <td><code>const xml_schema::duration&amp;</code><br/>
+ <a href="#7.9">Section 7.9, "<code>duration</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>gDay</code></td>
+ <td><code>gday_simpl</code></td>
+ <td><code>const xml_schema::gday&amp;</code><br/>
+ <a href="#7.10">Section 7.10, "<code>gDay</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonth</code></td>
+ <td><code>gmonth_simpl</code></td>
+ <td><code>const xml_schema::gmonth&amp;</code><br/>
+ <a href="#7.11">Section 7.11, "<code>gMonth</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>gMonthDay</code></td>
+ <td><code>gmonth_day_simpl</code></td>
+ <td><code>const xml_schema::gmonth_day&amp;</code><br/>
+ <a href="#7.12">Section 7.12, "<code>gMonthDay</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYear</code></td>
+ <td><code>gyear_simpl</code></td>
+ <td><code>const xml_schema::gyear&amp;</code><br/>
+ <a href="#7.13">Section 7.13, "<code>gYear</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>gYearMonth</code></td>
+ <td><code>gyear_month_simpl</code></td>
+ <td><code>const xml_schema::gyear_month&amp;</code><br/>
+ <a href="#7.14">Section 7.14, "<code>gYearMonth</code> Serializer"</a></td>
+ </tr>
+ <tr>
+ <td><code>time</code></td>
+ <td><code>time_simpl</code></td>
+ <td><code>const xml_schema::time&amp;</code><br/>
+ <a href="#7.15">Section 7.15, "<code>time</code> Serializer"</a></td>
+ </tr>
+
+ </table>
+
+ <h2><a name="7.1">7.1 Floating-Point Type Serializers</a></h2>
+
+ <p>The serializer implementations for the <code>float</code>,
+ <code>double</code>, and <code>decimal</code> built-in
+ XML Schema types allow you to specify the resulting
+ notation (fixed or scientific) as well as precision.
+ This is done by passing the corresponding arguments
+ to their constructors:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class float_simpl: public float_sskel
+ {
+ enum notation
+ {
+ notation_auto,
+ notation_fixed,
+ notation_scientific
+ };
+
+ float_simpl (notation = notation_auto,
+ unsigned int precision = FLT_DIG);
+
+ virtual void
+ pre (float);
+
+ ...
+ };
+
+ class double_simpl: public double_sskel
+ {
+ enum notation
+ {
+ notation_auto,
+ notation_fixed,
+ notation_scientific
+ };
+
+ double_simpl (notation = notation_auto,
+ unsigned int precision = DBL_DIG);
+
+ virtual void
+ pre (double);
+
+ ...
+ };
+
+ class decimal_simpl: public decimal_sskel
+ {
+ decimal_simpl (unsigned int precision = DBL_DIG);
+
+ virtual void
+ pre (double);
+
+ ...
+ };
+}
+ </pre>
+
+ <p>By default the notation for the <code>float</code> and <code>double</code>
+ types is automatically selected to produce the shortest representation.
+ Note that the <code>decimal</code> values are always serialized in
+ the fixed-point notation.</p>
+
+ <h2><a name="7.2">7.2 String-Based Type Serializers</a></h2>
+
+ <p>When STL is enabled (<a href="#6.1">Section 6.1, "Standard Template
+ Library"</a>), the serializer argument type for the <code>string</code>,
+ <code>normalizedString</code>, <code>token</code>,
+ <code>Name</code>, <code>NMTOKEN</code>, <code>NCName</code>,
+ <code>ID</code>, <code>IDREF</code>, <code>language</code>,
+ <code>anyURI</code>, and <code>anySimpleType</code> built-in XML Schema
+ types is
+ <code>const std::string&amp;</code>. When STL is disabled, the value
+ is passed as a constant C-string: <code>const char*</code>.
+ In this case, you can also instruct the serializer
+ implementations for string-based types to release the
+ string with operator <code>delete[]</code> by passing
+ <code>true</code> to their constructors. For instance,
+ using the person records example from the previous chapter:</p>
+
+ <pre class="c++">
+class person_simpl: public person_sskel
+{
+public:
+ virtual const char*
+ first_name ()
+ {
+ char* r = new char[5];
+ strcpy (r, "John");
+ return r;
+ }
+
+ virtual const char*
+ last_name ()
+ {
+ char* r = new char[4];
+ strcpy (r, "Doe");
+ return r;
+ }
+
+ ...
+};
+
+int
+main ()
+{
+ // Construct the serializer.
+ //
+ xml_schema::unsigned_short_simpl unsigned_short_s;
+ xml_schema::string_simpl string_s (true); // Release the string passed.
+
+ gender_simpl gender_s;
+ person_simpl person_s;
+ people_simpl people_s;
+
+ person_s.serializers (string_s, string_s, gender_s, unsigned_short_s);
+
+ ...
+}
+ </pre>
+
+ <h2><a name="7.3">7.3 <code>QName</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>qname_simpl</code> serializer
+ implementation is either <code>const xml_schema::qname&amp;</code>
+ when STL is enabled (<a href="#6.1">Section 6.1, "Standard Template
+ Library"</a>) or <code>const xml_schema::qname*</code> when STL
+ is disabled. The <code>qname</code> class represents an XML
+ qualified name. When the argument type is <code>const
+ xml_schema::qname*</code>, you can optionally instruct the
+ serializer to release the <code>qname</code> object with operator
+ <code>delete</code> by passing <code>true</code> to its
+ constructor.</p>
+
+ <p>With STL enabled, the <code>qname</code> type has the following
+ interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (const std::string&amp; name);
+ qname (const std::string&amp; prefix, const std::string&amp; name);
+
+ void
+ swap (qname&amp;);
+
+ const std::string&amp;
+ prefix () const;
+
+ std::string&amp;
+ prefix ();
+
+ void
+ prefix (const std::string&amp;);
+
+ const std::string&amp;
+ name () const;
+
+ std::string&amp;
+ name ();
+
+ void
+ name (const std::string&amp;);
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <p>When STL is disabled and C++ exceptions are enabled
+ (<a href="#6.3">Section 6.3, "C++ Exceptions"</a>), the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (char* name);
+ qname (char* prefix, char* name);
+
+ void
+ swap (qname&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ public:
+ char*
+ prefix ();
+
+ const char*
+ prefix () const;
+
+ void
+ prefix (char*);
+
+ void
+ prefix_copy (const char*);
+
+ char*
+ prefix_detach ();
+
+ public:
+ char*
+ name ();
+
+ const char*
+ name () const;
+
+ void
+ name (char*);
+
+ void
+ name_copy (const char*);
+
+ char*
+ name_detach ();
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+</pre>
+
+ <p>The modifier functions and constructors that have the <code>char*</code>
+ argument assume ownership of the passed strings which should be allocated
+ with operator <code>new char[]</code> and will be deallocated with
+ operator <code>delete[]</code> by the <code>qname</code> object.
+ If you detach the underlying prefix or name strings, then they
+ should eventually be deallocated with operator <code>delete[]</code>.
+ </p>
+
+ <p>Finally, if both STL and C++ exceptions are disabled, the
+ <code>qname</code> type has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class qname
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ qname ();
+
+ explicit
+ qname (char* name);
+ qname (char* prefix, char* name);
+
+ void
+ swap (qname&amp;);
+
+ private:
+ qname (const qname&amp;);
+
+ qname&amp;
+ operator= (const qname&amp;);
+
+ public:
+ char*
+ prefix ();
+
+ const char*
+ prefix () const;
+
+ void
+ prefix (char*);
+
+ error
+ prefix_copy (const char*);
+
+ char*
+ prefix_detach ();
+
+ public:
+ char*
+ name ();
+
+ const char*
+ name () const;
+
+ void
+ name (char*);
+
+ error
+ name_copy (const char*);
+
+ char*
+ name_detach ();
+ };
+
+ bool
+ operator== (const qname&amp;, const qname&amp;);
+
+ bool
+ operator!= (const qname&amp;, const qname&amp;);
+}
+ </pre>
+
+ <h2><a name="7.4">7.4 <code>NMTOKENS</code> and <code>IDREFS</code> Serializers</a></h2>
+
+ <p>The argument type of the <code>nmtokens_simpl</code> and
+ <code>idrefs_simpl</code> serializer implementations is
+ <code>const xml_schema::string_sequence*</code>. You can
+ optionally instruct these serializers to release the
+ <code>string_sequence</code> object with operator <code>delete</code>
+ by passing <code>true</code> to their constructors. With STL and C++ exceptions enabled
+ (<a href="#6.1">Section 6.1, "Standard Template Library"</a>,
+ <a href="#6.3">Section 6.3, "C++ Exceptions"</a>), the
+ <code>string_sequence</code> type has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ typedef std::string value_type;
+ typedef std::string* pointer;
+ typedef const std::string* const_pointer;
+ typedef std::string&amp; reference;
+ typedef const std::string&amp; const_reference;
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef std::string* iterator;
+ typedef const std::string* const_iterator;
+
+ public:
+ string_sequence ();
+
+ void
+ swap (string_sequence&amp;);
+
+ private:
+ string_sequence (string_sequence&amp;);
+
+ string_sequence&amp;
+ operator= (string_sequence&amp;);
+
+ public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ std::string&amp;
+ front ();
+
+ const std::string&amp;
+ front () const;
+
+ std::string&amp;
+ back ();
+
+ const std::string&amp;
+ back () const;
+
+ std::string&amp;
+ operator[] (size_t);
+
+ const std::string&amp;
+ operator[] (size_t) const;
+
+ public:
+ bool
+ empty () const;
+
+ size_t
+ size () const;
+
+ size_t
+ capacity () const;
+
+ size_t
+ max_size () const;
+
+ public:
+ void
+ clear ();
+
+ void
+ pop_back ();
+
+ iterator
+ erase (iterator);
+
+ void
+ push_back (const std::string&amp;);
+
+ iterator
+ insert (iterator, const std::string&amp;);
+
+ void
+ reserve (size_t);
+ };
+
+ bool
+ operator== (const string_sequence&amp;, const string_sequence&amp;);
+
+ bool
+ operator!= (const string_sequence&amp;, const string_sequence&amp;);
+}
+ </pre>
+
+ <p>When STL is enabled and C++ exceptions are disabled, the signatures
+ of the <code>push_back()</code>, <code>insert()</code>, and
+ <code>reserve()</code> functions change as follows:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ ...
+
+ public:
+ error
+ push_back (const std::string&amp;);
+
+ error
+ insert (iterator, const std::string&amp;);
+
+ error
+ insert (iterator, const std::string&amp;, iterator&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+ <p>When STL is disabled and C++ exceptions are enabled, the
+ <code>string_sequence</code> type has the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ typedef char* value_type;
+ typedef char** pointer;
+ typedef const char** const_pointer;
+ typedef char* reference;
+ typedef const char* const_reference;
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef char** iterator;
+ typedef const char* const* const_iterator;
+
+ string_sequence ();
+
+ void
+ swap (string_sequence&amp;);
+
+ private:
+ string_sequence (string_sequence&amp;);
+
+ string_sequence&amp;
+ operator= (string_sequence&amp;);
+
+ public:
+ iterator
+ begin ();
+
+ const_iterator
+ begin () const;
+
+ iterator
+ end ();
+
+ const_iterator
+ end () const;
+
+ char*
+ front ();
+
+ const char*
+ front () const;
+
+ char*
+ back ();
+
+ const char*
+ back () const;
+
+ char*
+ operator[] (size_t);
+
+ const char*
+ operator[] (size_t) const;
+
+ public:
+ bool
+ empty () const;
+
+ size_t
+ size () const;
+
+ size_t
+ capacity () const;
+
+ size_t
+ max_size () const;
+
+ public:
+ void
+ clear ();
+
+ void
+ pop_back ();
+
+ iterator
+ erase (iterator);
+
+ void
+ push_back (char*);
+
+ void
+ push_back_copy (const char*);
+
+ iterator
+ insert (iterator, char*);
+
+ void
+ reserve (size_t);
+
+ // Detach a string from the sequence at a given position.
+ // The string pointer at this position in the sequence is
+ // set to 0.
+ //
+ char*
+ detach (iterator);
+ };
+
+ bool
+ operator== (const string_sequence&amp;, const string_sequence&amp;);
+
+ bool
+ operator!= (const string_sequence&amp;, const string_sequence&amp;);
+}
+ </pre>
+
+ <p>The <code>push_back()</code> and <code>insert()</code> functions
+ assume ownership of the passed string which should be allocated
+ with operator <code>new char[]</code> and will be deallocated
+ with operator <code>delete[]</code> by the <code>string_sequence</code>
+ object. These two functions free the passed object if the reallocation
+ of the underlying sequence buffer fails. The <code>push_back_copy()</code>
+ function makes a copy of the passed string.
+ If you detach the underlying element string, then it should
+ eventually be deallocated with operator <code>delete[]</code>.</p>
+
+ <p>When both STL and C++ exceptions are disabled, the signatures
+ of the <code>push_back()</code>, <code>push_back_copy()</code>,
+ <code>insert()</code>, and <code>reserve()</code> functions change
+ as follows:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class string_sequence
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_no_memory
+ };
+
+ ...
+
+ public:
+ error
+ push_back (char*);
+
+ error
+ push_back_copy (const char*);
+
+ error
+ insert (iterator, char*);
+
+ error
+ insert (iterator, char*, iterator&amp; result);
+
+ error
+ reserve (size_t);
+ };
+}
+ </pre>
+
+
+ <h2><a name="7.5">7.5 <code>base64Binary</code> and <code>hexBinary</code> Serializers</a></h2>
+
+ <p>The argument type of the <code>base64_binary_simpl</code> and
+ <code>hex_binary_simpl</code> serializer implementations is
+ <code>const xml_schema::buffer*</code>. You can optionally
+ instruct these serializers to release the <code>buffer</code>
+ object with operator <code>delete</code> by passing <code>true</code>
+ to their constructors. With C++ exceptions enabled (<a href="#6.3">Section
+ 6.3, "C++ Exceptions"</a>), the <code>buffer</code> type has the
+ following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class buffer
+ {
+ public:
+ class bounds {}; // Out of bounds exception.
+
+ public:
+ buffer ();
+
+ explicit
+ buffer (size_t size);
+ buffer (size_t size, size_t capacity);
+ buffer (const void* data, size_t size);
+ buffer (const void* data, size_t size, size_t capacity);
+
+ enum ownership_value { assume_ownership };
+
+ // This constructor assumes ownership of the memory passed.
+ //
+ buffer (void* data, size_t size, size_t capacity, ownership_value);
+
+ private:
+ buffer (const buffer&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ void
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+ void
+ swap (buffer&amp;);
+
+ public:
+ size_t
+ capacity () const;
+
+ bool
+ capacity (size_t);
+
+ public:
+ size_t
+ size () const;
+
+ bool
+ size (size_t);
+
+ public:
+ const char*
+ data () const;
+
+ char*
+ data ();
+
+ const char*
+ begin () const;
+
+ char*
+ begin ();
+
+ const char*
+ end () const;
+
+ char*
+ end ();
+ };
+
+ bool
+ operator== (const buffer&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <p>The last constructor and the <code>attach()</code> member function
+ make the <code>buffer</code> instance assume the ownership of the
+ memory block pointed to by the <code>data</code> argument and
+ eventually release it by calling <code>operator delete()</code>.
+ The <code>detach()</code> member function detaches and returns the
+ underlying memory block which should eventually be released by
+ calling <code>operator delete()</code>.
+ </p>
+
+ <p>The <code>capacity()</code> and <code>size()</code> modifier functions
+ return <code>true</code> if the underlying buffer has moved. The
+ <code>bounds</code> exception is thrown if the constructor or
+ <code>attach()</code> member function arguments violate the
+ <code>(size&nbsp;&lt;=&nbsp;capacity)</code> constraint.</p>
+
+ <p>If C++ exceptions are disabled, the <code>buffer</code> type has
+ the following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class buffer
+ {
+ public:
+ enum error
+ {
+ error_none,
+ error_bounds,
+ error_no_memory
+ };
+
+ buffer ();
+
+ private:
+ buffer (const buffer&amp;);
+
+ buffer&amp;
+ operator= (const buffer&amp;);
+
+ public:
+ error
+ attach (void* data, size_t size, size_t capacity);
+
+ void*
+ detach ();
+
+ void
+ swap (buffer&amp;);
+
+ public:
+ size_t
+ capacity () const;
+
+ error
+ capacity (size_t);
+
+ error
+ capacity (size_t, bool&amp; moved);
+
+ public:
+ size_t
+ size () const;
+
+ error
+ size (size_t);
+
+ error
+ size (size_t, bool&amp; moved);
+
+ public:
+ const char*
+ data () const;
+
+ char*
+ data ();
+
+ const char*
+ begin () const;
+
+ char*
+ begin ();
+
+ const char*
+ end () const;
+
+ char*
+ end ();
+ };
+
+ bool
+ operator== (const buffer&amp;, const buffer&amp;);
+
+ bool
+ operator!= (const buffer&amp;, const buffer&amp;);
+}
+ </pre>
+
+ <h2><a name="7.6">7.6 Time Zone Representation</a></h2>
+
+ <p>The <code>date</code>, <code>dateTime</code>, <code>gDay</code>,
+ <code>gMonth</code>, <code>gMonthDay</code>, <code>gYear</code>,
+ <code>gYearMonth</code>, and <code>time</code> XML Schema built-in
+ types all include an optional time zone component. The following
+ <code>xml_schema::time_zone</code> base class is used to represent
+ this information:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class time_zone
+ {
+ public:
+ time_zone ();
+ time_zone (short hours, short minutes);
+
+ bool
+ zone_present () const;
+
+ void
+ zone_reset ();
+
+ short
+ zone_hours () const;
+
+ void
+ zone_hours (short);
+
+ short
+ zone_minutes () const;
+
+ void
+ zone_minutes (short);
+ };
+
+ bool
+ operator== (const time_zone&amp;, const time_zone&amp;);
+
+ bool
+ operator!= (const time_zone&amp;, const time_zone&amp;);
+}
+ </pre>
+
+ <p>The <code>zone_present()</code> accessor function returns <code>true</code>
+ if the time zone is specified. The <code>zone_reset()</code> modifier
+ function resets the time zone object to the <em>not specified</em>
+ state. If the time zone offset is negative then both hours and
+ minutes components are represented as negative integers.</p>
+
+ <h2><a name="7.7">7.7 <code>date</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>date_simpl</code> serializer implementation
+ is <code>const xml_schema::date&amp;</code>. The <code>date</code> class
+ represents a year, a day, and a month with an optional time zone. Its
+ interface is presented below. For more information on the base
+ <code>xml_schema::time_zone</code> class refer to <a href="#7.6">Section
+ 7.6, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class date: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ date ();
+
+ date (int year, unsigned short month, unsigned short day);
+
+ date (int year, unsigned short month, unsigned short day,
+ short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+ };
+
+ bool
+ operator== (const date&amp;, const date&amp;);
+
+ bool
+ operator!= (const date&amp;, const date&amp;);
+}
+ </pre>
+
+ <h2><a name="7.8">7.8 <code>dateTime</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>date_time_simpl</code> serializer
+ implementation is <code>const xml_schema::date_time&amp;</code>.
+ The <code>date_time</code> class represents a year, a month, a day,
+ hours, minutes, and seconds with an optional time zone. Its interface
+ is presented below. For more information on the base
+ <code>xml_schema::time_zone</code> class refer to <a href="#7.6">Section
+ 7.6, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class date_time: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ date_time ();
+
+ date_time (int year, unsigned short month, unsigned short day,
+ unsigned short hours, unsigned short minutes,
+ double seconds);
+
+ date_time (int year, unsigned short month, unsigned short day,
+ unsigned short hours, unsigned short minutes,
+ double seconds, short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+
+ unsigned short
+ hours () const;
+
+ void
+ hours (unsigned short);
+
+ unsigned short
+ minutes () const;
+
+ void
+ minutes (unsigned short);
+
+ double
+ seconds () const;
+
+ void
+ seconds (double);
+ };
+
+ bool
+ operator== (const date_time&amp;, const date_time&amp;);
+
+ bool
+ operator!= (const date_time&amp;, const date_time&amp;);
+}
+ </pre>
+
+ <h2><a name="7.9">7.9 <code>duration</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>duration_simpl</code> serializer
+ implementation is <code>const xml_schema::duration&amp;</code>.
+ The <code>duration</code> class represents a potentially
+ negative duration in the form of years, months, days, hours, minutes,
+ and seconds. Its interface is presented below.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class duration
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ duration ();
+
+ duration (bool negative,
+ unsigned int years, unsigned int months, unsigned int days,
+ unsigned int hours, unsigned int minutes, double seconds);
+
+ bool
+ negative () const;
+
+ void
+ negative (bool);
+
+ unsigned int
+ years () const;
+
+ void
+ years (unsigned int);
+
+ unsigned int
+ months () const;
+
+ void
+ months (unsigned int);
+
+ unsigned int
+ days () const;
+
+ void
+ days (unsigned int);
+
+ unsigned int
+ hours () const;
+
+ void
+ hours (unsigned int);
+
+ unsigned int
+ minutes () const;
+
+ void
+ minutes (unsigned int);
+
+ double
+ seconds () const;
+
+ void
+ seconds (double);
+ };
+
+ bool
+ operator== (const duration&amp;, const duration&amp;);
+
+ bool
+ operator!= (const duration&amp;, const duration&amp;);
+}
+ </pre>
+
+
+ <h2><a name="7.10">7.10 <code>gDay</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>gday_simpl</code> serializer
+ implementation is <code>const xml_schema::gday&amp;</code> The
+ <code>gday</code> class represents a day of the month with
+ an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#7.6">Section 7.6, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gday: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gday ();
+
+ explicit
+ gday (unsigned short day);
+
+ gday (unsigned short day, short zone_hours, short zone_minutes);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+ };
+
+ bool
+ operator== (const gday&amp;, const gday&amp;);
+
+ bool
+ operator!= (const gday&amp;, const gday&amp;);
+}
+ </pre>
+
+ <h2><a name="7.11">7.11 <code>gMonth</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>gmonth_simpl</code> serializer
+ implementation is <code>const xml_schema::gmonth&amp;</code>. The
+ <code>gmonth</code> class represents a month of the year with
+ an optional time zone. Its interface is presented below. For
+ more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#7.6">Section 7.6, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gmonth: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gmonth ();
+
+ explicit
+ gmonth (unsigned short month);
+
+ gmonth (unsigned short month,
+ short zone_hours, short zone_minutes);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+ };
+
+ bool
+ operator== (const gmonth&amp;, const gmonth&amp;);
+
+ bool
+ operator!= (const gmonth&amp;, const gmonth&amp;);
+}
+ </pre>
+
+ <h2><a name="7.12">7.12 <code>gMonthDay</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>gmonth_day_simpl</code> serializer
+ implementation is <code>const xml_schema::gmonth_day&amp;</code>.
+ The <code>gmonth_day</code> class represents a day and a month of
+ the year with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#7.6">Section 7.6, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gmonth_day: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gmonth_day ();
+
+ gmonth_day (unsigned short month, unsigned short day);
+
+ gmonth_day (unsigned short month, unsigned short day,
+ short zone_hours, short zone_minutes);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+
+ unsigned short
+ day () const;
+
+ void
+ day (unsigned short);
+ };
+
+ bool
+ operator== (const gmonth_day&amp;, const gmonth_day&amp;);
+
+ bool
+ operator!= (const gmonth_day&amp;, const gmonth_day&amp;);
+}
+ </pre>
+
+ <h2><a name="7.13">7.13 <code>gYear</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>gyear_simpl</code> serializer
+ implementation is <code>const xml_schema::gyear&amp;</code>. The
+ <code>gyear</code> class represents a year with an optional
+ time zone. Its interface is presented below. For more information
+ on the base <code>xml_schema::time_zone</code> class refer to
+ <a href="#7.6">Section 7.6, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gyear: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gyear ();
+
+ explicit
+ gyear (int year);
+
+ gyear (int year, short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+ };
+
+ bool
+ operator== (const gyear&amp;, const gyear&amp;);
+
+ bool
+ operator!= (const gyear&amp;, const gyear&amp;);
+}
+ </pre>
+
+ <h2><a name="7.14">7.14 <code>gYearMonth</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>gyear_month_simpl</code> serializer
+ implementation is <code>const xml_schema::gyear_month&amp;</code>.
+ The <code>gyear_month</code> class represents a year and a month
+ with an optional time zone. Its interface is presented below.
+ For more information on the base <code>xml_schema::time_zone</code>
+ class refer to <a href="#7.6">Section 7.6, "Time Zone
+ Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class gyear_month: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ gyear_month ();
+
+ gyear_month (int year, unsigned short month);
+
+ gyear_month (int year, unsigned short month,
+ short zone_hours, short zone_minutes);
+
+ int
+ year () const;
+
+ void
+ year (int);
+
+ unsigned short
+ month () const;
+
+ void
+ month (unsigned short);
+ };
+
+ bool
+ operator== (const gyear_month&amp;, const gyear_month&amp;);
+
+ bool
+ operator!= (const gyear_month&amp;, const gyear_month&amp;);
+}
+ </pre>
+
+
+ <h2><a name="7.15">7.15 <code>time</code> Serializer</a></h2>
+
+ <p>The argument type of the <code>time_simpl</code> serializer implementation
+ is <code>const xml_schema::time&amp;</code>. The <code>time</code> class
+ represents hours, minutes, and seconds with an optional time zone. Its
+ interface is presented below. For more information on the base
+ <code>xml_schema::time_zone</code> class refer to <a href="#7.6">Section
+ 7.6, "Time Zone Representation"</a>.</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class time: public time_zone
+ {
+ public:
+ // The default constructor creates an uninitialized object.
+ // Use modifiers to initialize it.
+ //
+ time ();
+
+ time (unsigned short hours, unsigned short minutes, double seconds);
+
+ time (unsigned short hours, unsigned short minutes, double seconds,
+ short zone_hours, short zone_minutes);
+
+ unsigned short
+ hours () const;
+
+ void
+ hours (unsigned short);
+
+ unsigned short
+ minutes () const;
+
+ void
+ minutes (unsigned short);
+
+ double
+ seconds () const;
+
+ void
+ seconds (double);
+ };
+
+ bool
+ operator== (const time&amp;, const time&amp;);
+
+ bool
+ operator!= (const time&amp;, const time&amp;);
+}
+ </pre>
+
+
+ <!-- Error Handling -->
+
+
+ <h1><a name="8">8 Document Serializer and Error Handling</a></h1>
+
+ <p>In this chapter we will discuss the <code>xml_schema::document_simpl</code>
+ type, the error handling mechanisms provided by the mapping, as well as
+ how to reuse a serializer after an error has occurred.</p>
+
+ <p>There are four categories of errors that can result from running
+ a serializer to produce an XML instance: system, xml, schema, and
+ application. The system category contains memory allocation and
+ input/output operation errors. The xml category is for XML serialization
+ and well-formedness checking errors. Similarly, the schema category is
+ for XML Schema validation errors. Finally, the application category
+ is for application logic errors that you may want to propagate
+ from serializer implementations to the caller of the serializer.
+ </p>
+
+ <p>The C++/Serializer mapping supports two methods of reporting errors:
+ using C++ exceptions and with error codes. The method used depends
+ on whether or not you have configured the XSD/e runtime and
+ the generated code with C++ exceptions enabled, as described
+ in <a href="#6.3">Section 6.3, "C++ Exceptions"</a>.</p>
+
+ <h2><a name="8.1">8.1 Document Serializer</a></h2>
+
+ <p>The <code>xml_schema::document_simpl</code> serializer is a root
+ serializer for the vocabulary. As mentioned in <a href="#3.4">Section
+ 3.4, "Connecting the Serializer Together"</a>, its interface varies
+ depending on the mapping configuration (<a href="#6">Chapter 6, "Mapping
+ Configuration"</a>). When STL, C++ exceptions, and the iostream library
+ are enabled, the <code>xml_schema::document_simpl</code> class has the
+ following interface:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class serializer_base;
+
+ class writer
+ {
+ public:
+ // The first write function is called to write a '\0'-terminated
+ // string. Its default implementation calls the second versions:
+ // write (s, strlen (s)). These functions use exceptions to
+ // indicate a write failure.
+ //
+ virtual void
+ write (const char* s);
+
+ virtual void
+ write (const char* s, size_t n) = 0;
+
+ virtual void
+ flush () = 0;
+ };
+
+ class document_simpl
+ {
+ public:
+ document_simpl (serializer_base&amp;,
+ const char* root_element_name);
+
+ document_simpl (serializer_base&amp;,
+ const char* root_element_namespace,
+ const char* root_element_name);
+
+ document_simpl (serializer_base&amp;,
+ const std::string&amp; root_element_name);
+
+ document_simpl (serializer_base&amp;,
+ const std::string&amp; root_element_namespace,
+ const std::string&amp; root_element_name);
+
+ public:
+ void
+ add_prefix (const char* prefix, const char* namespace_);
+
+ void
+ add_default_prefix (const char* namespace_);
+
+ void
+ add_schema (const char* namespace_, const char* location);
+
+ void
+ add_no_namespace_schema (const char* location);
+
+ void
+ add_prefix (const std::string&amp; prefix,
+ const std::string&amp; namespace_);
+
+ void
+ add_default_prefix (const std::string&amp; namespace_);
+
+ void
+ add_schema (const std::string&amp; namespace_,
+ const std::string&amp; location);
+
+ void
+ add_no_namespace_schema (const std::string&amp; location);
+
+ public:
+ // Serialization flags.
+ //
+ typedef unsigned short flags;
+
+ static const flags pretty_print;
+
+ public:
+ // Serialize to std::ostream. The std::ios_base::failure
+ // exception is used to report io errors (badbit and failbit)
+ // if C++ exceptions are enabled. Otherwise error codes are
+ // used.
+ //
+ void
+ serialize (std::ostream&amp;, flags = 0);
+
+ public:
+ // Serialize by calling writer::write() and writer::flush() to
+ // output XML.
+ //
+ void
+ serialize (writer&amp;, flags = 0);
+
+ // Serialize by calling the write and flush functions. If the
+ // unbounded write function is not provided, the bounded version
+ // is called: write_bound_func (s, strlen (s)). user_data is
+ // passed as a first argument to these functions. These functions
+ // use exceptions to indicate a write failure.
+ //
+ typedef void (*write_func) (void*, const char*);
+ typedef void (*write_bound_func) (void*, const char*, size_t);
+ typedef void (*flush_func) (void*);
+
+ void
+ serialize (write_bound_func,
+ flush_func,
+ void* user_data,
+ flags = 0);
+
+ void
+ serialize (write_func,
+ write_bound_func,
+ flush_func,
+ void* user_data,
+ flags = 0);
+ public:
+ // Low-level, genx-specific serialization. With this method
+ // it is your responsibility to call genxStartDoc*() and
+ // genxEndDocument().
+ //
+ void
+ serialize (genxWriter);
+ };
+}
+ </pre>
+
+ <p>When the use of STL is disabled, the constructors, as well as
+ the <code>add_prefix()</code> and <code>add_schema()</code>
+ functions that use <code>std::string</code> in their signatures
+ are not available. When the use of iostream is disabled, the
+ <code>serialize()</code> functions that serializes to
+ <code>std::ostream</code> is not available.</p>
+
+ <p>When C++ exceptions are disabled, the <code>write()</code> and
+ <code>flush()</code> virtual functions in the <code>writer</code>
+ interface as well as <code>write_func</code>,
+ <code>write_bound_func</code>, and <code>flush_func</code>
+ function pointers use <code>bool</code> return type
+ for error reporting. These functions should return <code>true</code>
+ if the operation was successful and <code>false</code> otherwise.
+ The relevant parts in the <code>writer</code> and
+ <code>document_simpl</code> interfaces change as follows:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class serializer_base;
+
+ class writer
+ {
+ public:
+ // The first write function is called to write a '\0'-terminated
+ // string. Its default implementation calls the second versions:
+ // write (s, strlen (s)). These functions return true if the
+ // operation was successful and false otherwise.
+ //
+ // indicate a write failure.
+ //
+ virtual bool
+ write (const char* s);
+
+ virtual bool
+ write (const char* s, size_t n) = 0;
+
+ virtual bool
+ flush () = 0;
+ };
+
+ class document_simpl
+ {
+ ...
+
+ // Serialize by calling the write and flush functions. If the
+ // unbounded write function is not provided, the bounded version
+ // is called: write_bound_func (s, strlen (s)). user_data is
+ // passed as a first argument to these functions. These functions
+ // return true if the operation was successful and false otherwise.
+ //
+ typedef bool (*write_func) (void*, const char*);
+ typedef bool (*write_bound_func) (void*, const char*, size_t);
+ typedef bool (*flush_func) (void*);
+
+ ...
+
+ public:
+ const serializer_error&amp;
+ _error () const;
+ };
+}
+ </pre>
+
+ <p>For more information on error handling with C++ exceptions and
+ error codes see <a href="#8.2">Section 8.2, "Exceptions"</a>
+ and <a href="#8.3">Section 8.3, "Error Codes"</a> below.</p>
+
+ <p>When support for XML Schema polymorphism is enabled, the
+ overloaded <code>document_simpl</code> constructors have
+ additional arguments which control polymorphic serialization.
+ For more information refer to <a href="#6.7">Section 6.7,
+ "Support for Polymorphism"</a>.
+ </p>
+
+ <p>The first argument to all overloaded constructors is the
+ serializer for the type of the root element. The
+ <code>serializer_base</code> class is the base type for all
+ serializer skeletons. The second and third arguments to the
+ <code>document_simpl</code>'s constructors are the root element's
+ name and namespace.</p>
+
+ <p>The <code>add_prefix()</code> and <code>add_default_prefix()</code>
+ functions allow you to establish custom prefixes for XML
+ namespaces. If none is provided, and namespaces are used
+ by your vocabulary, the serializer will automatically
+ assign namespace prefixes in an implementation-specific
+ manner. For example:</p>
+
+ <pre class="c++">
+xml_schema::document_simpl doc_s (
+ root_s,
+ "http://www.example.com/example",
+ "root");
+
+doc_s.add_prefix ("ex", "http://www.example.com/example");
+ </pre>
+
+ <p>The resulting XML will have the following namespace declaration:</p>
+
+ <pre class="xml">
+&lt;ex:root xmlns:ex="http://www.example.com/example" ...>
+ ...
+&lt;/ex:root>
+ </pre>
+
+ <p>Similarly, the <code>add_schema()</code> and
+ <code>add_no_namespace_schema()</code> functions allow you to embed
+ schema location information for a particular namespace into resulting
+ XML. The schema location information is placed into the
+ <code>xsi:schemaLocation</code> and
+ <code>xsi:noNamespaceSchemaLocation</code> attributes. For example:</p>
+
+ <pre class="c++">
+xml_schema::document_simpl doc_s (
+ root_s,
+ "http://www.example.com/example",
+ "root");
+
+doc_s.add_prefix ("ex", "http://www.example.com/example");
+doc_s.add_schema ("http://www.example.com/example", "example.xsd");
+ </pre>
+
+ <p>The resulting XML will have the following namespace declaration:</p>
+
+ <pre class="xml">
+&lt;ex:root
+ xmlns:ex="http://www.example.com/example"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.example.com/example example.xsd" ...>
+ ...
+&lt;/ex:root>
+ </pre>
+
+ <h2><a name="8.2">8.2 Exceptions</a></h2>
+
+ <p>When C++ exceptions are used for error reporting, the system
+ errors are mapped to the standard exceptions. The out of memory
+ condition is indicated by throwing an instance
+ of <code>std::bad_alloc</code>. The stream operation errors
+ are reported by throwing an instance of
+ <code>std::ios_base::failure</code>.</p>
+
+ <p>The xml and schema errors are reported by throwing the
+ <code>xml_schema::serializer_xml</code> and
+ <code>xml_schema::serializer_schema</code>
+ exceptions, respectively. These two exceptions derive from
+ <code>xml_schema::serializer_exception</code> which, in turn, derives
+ from <code>std::exception</code>. As a result, you can handle
+ any error from these two categories by either catching
+ <code>std::exception</code>, <code>xml_schema::serializer_exception</code>,
+ or individual exceptions. The further down the hierarchy you go
+ the more detailed error information is available to you. The
+ following listing shows the definitions of these exceptions:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class serializer_exception: public std::exception
+ {
+ public:
+ virtual const char*
+ text () const = 0;
+
+ ...
+ };
+
+ std::ostream&amp;
+ operator&lt;&lt; (std::ostream&amp;, const serializer_exception&amp;);
+
+
+ typedef &lt;implementation-details> serializer_xml_error;
+
+ class serializer_xml: public serializer_exception
+ {
+ public:
+ serializer_xml_error
+ code () const;
+
+ virtual const char*
+ text () const;
+
+ virtual const char*
+ what () const throw ();
+
+ ...
+ };
+
+
+ typedef &lt;implementation-details> serializer_schema_error;
+
+ class serializer_schema: public serializer_exception
+ {
+ public:
+ serializer_schema_error
+ code () const;
+
+ virtual const char*
+ text () const;
+
+ virtual const char*
+ what () const throw ();
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>serializer_xml_error</code> and
+ <code>serializer_schema_error</code> are implementation-specific error
+ code types. The <code>operator&lt;&lt;</code> defined for the
+ <code>serializer_exception</code> class simply prints the error
+ description as returned by the <code>text()</code> function. The
+ following example shows how we can catch these exceptions:</p>
+
+ <pre class="c++">
+int
+main ()
+{
+ try
+ {
+ // Serialize.
+ }
+ catch (const xml_schema::serializer_exception&amp; e)
+ {
+ cout &lt;&lt; "error: " &lt;&lt; e.text () &lt;&lt; endl;
+ return 1;
+ }
+}
+ </pre>
+
+ <p>Finally, for reporting application errors from serializer callbacks,
+ you can throw any exceptions of your choice. They are propagated
+ to the caller of the serializer without any alterations.</p>
+
+ <h2><a name="8.3">8.3 Error Codes</a></h2>
+
+ <p>When C++ exceptions are not available, error codes are used to
+ report error conditions. Each serializer skeleton and the root
+ <code>document_simpl</code> serializer have the following member
+ function for querying the error status:</p>
+
+ <pre class="c++">
+xml_schema::serializer_error
+_error () const;
+ </pre>
+
+ <p>To handle all possible error conditions, you will need to obtain
+ the error status after calls to: the <code>document_simpl</code>'s
+ constructor (it performs memory allocations which may fail),
+ calls to <code>add_prefix()</code> and <code>add_schema()</code>
+ functions if any, the call to the root serializer <code>pre()</code>
+ callback, the call to the <code>serialize()</code> function, and,
+ finally, the call to the root serializer <code>post()</code> callback.
+ The definition of <code>xml_schema::serializer_error</code> class
+ is presented below:</p>
+
+ <pre class="c++">
+namespace xml_schema
+{
+ class sys_error
+ {
+ public:
+ enum value
+ {
+ none,
+ no_memory,
+ open_failed,
+ read_failed,
+ write_failed
+ };
+
+ sys_error (value);
+
+ operator value () const;
+
+ static const char*
+ text (value);
+
+ ...
+ };
+
+ typedef &lt;implementation-details> serializer_xml_error;
+ typedef &lt;implementation-details> serializer_schema_error;
+
+ class serializer_error
+ {
+ public:
+ enum error_type
+ {
+ none,
+ sys,
+ xml,
+ schema,
+ app
+ };
+
+ error_type
+ type () const;
+
+ // Returns true if there is an error so that you can write
+ // if (s.error ()) or if (error e = s.error ()).
+ //
+ typedef void (error::*bool_convertible) ();
+ operator bool_convertible () const;
+
+ // system
+ //
+ sys_error
+ sys_code () const;
+
+ const char*
+ sys_text () const;
+
+ // xml
+ //
+ serializer_xml_error
+ xml_code () const;
+
+ const char*
+ xml_text () const;
+
+ // schema
+ //
+ serializer_schema_error
+ schema_code () const;
+
+ const char*
+ schema_text () const;
+
+ // app
+ //
+ int
+ app_code () const;
+
+ ...
+ };
+}
+ </pre>
+
+ <p>The <code>serializer_xml_error</code> and
+ <code>serializer_schema_error</code> are implementation-specific
+ error code types. The <code>serializer_error</code> class incorporates
+ four categories of errors which you can query by calling the
+ <code>type()</code> function. The following example shows how to
+ handle error conditions with error codes. It is based on the
+ person record example presented in <a href="#3">Chapter 3, "Serializer
+ Skeletons"</a>.</p>
+
+ <pre class="c++">
+int
+main ()
+{
+ // Construct the serializer.
+ //
+ xml_schema::short_simpl short_s;
+ xml_schema::string_simpl string_s;
+
+ gender_simpl gender_s;
+ person_simpl person_s;
+ people_simpl people_s;
+
+ person_s.serializers (string_s, string_s, gender_s, short_s);
+ people_s.serializers (person_s);
+
+ // Serialize.
+ //
+ using xml_schema::serializer_error;
+ serializer_error e;
+
+ do
+ {
+ xml_schema::document_simpl doc_s (people_s, "people");
+ if (e = doc_s._error ())
+ break;
+
+ people_s.pre ();
+ if (e = people_s._error ())
+ break;
+
+ doc_s.serialize (cout);
+ if (e = doc_s._error ())
+ break;
+
+ people_s.post ();
+ e = people_s._error ();
+
+ } while (false);
+
+ // Handle errors.
+ //
+ if (e)
+ {
+ switch (e.type ())
+ {
+ case serializer_error::sys:
+ {
+ cerr &lt;&lt; "system error: " &lt;&lt; e.sys_text () &lt;&lt; endl;
+ break;
+ }
+ case serializer_error::xml:
+ {
+ cerr &lt;&lt; "xml error: " &lt;&lt; e.xml_text () &lt;&lt; endl;
+ break;
+ }
+ case serializer_error::schema:
+ {
+ cerr &lt;&lt; "schema error: " &lt;&lt; e.schema_text () &lt;&lt; endl;
+ break;
+ }
+ case serializer_error::app:
+ {
+ cerr &lt;&lt; "application error: " &lt;&lt; e.app_code () &lt;&lt; endl;
+ break;
+ }
+ }
+ return 1;
+ }
+}
+ </pre>
+
+ <p>The error type for application errors is <code>int</code> with
+ the value <code>0</code> indicated the absence of error. You can
+ set the application error by calling the <code>_app_error()</code>
+ function inside a serializer callback. For example, if it was invalid
+ to have a person younger than 18 in our people catalog, then we
+ could have implemented this check as follows: </p>
+
+ <pre class="c++">
+class person_simpl: public person_sskel
+{
+public:
+ virtual short
+ age ()
+ {
+ short a = ...;
+
+ if (a &lt; 18)
+ _app_error (1);
+
+ return a;
+ }
+};
+ </pre>
+
+ <p>You can also set a system error by calling the <code>_sys_error()</code>
+ function inside a serializer callback. This function has one argument of
+ type <code>xml_schema::sys_error</code> which was presented above.
+ For example:</p>
+
+ <pre class="c++">
+class person_simpl: public person_sskel
+{
+public:
+ virtual const char*
+ first_name ()
+ {
+ char* r = new char[5];
+
+ if (r == 0)
+ {
+ _sys_error (xml_schema::sys_error::no_memory);
+ return 0;
+ }
+
+ strcpy (r, "John");
+ return r;
+ }
+};
+ </pre>
+
+ <h2><a name="8.4">8.4 Reusing Serializers after an Error</a></h2>
+
+ <p>After a successful execution a serializer returns into the initial
+ state and can be used to serialize another document without any
+ extra actions. On the other hand, if an error occurred during
+ serialization and you would like to reuse the serializer to serialize another
+ document, you need to explicitly reset it into the initial
+ state as shown in the following code fragment:</p>
+
+ <pre class="c++">
+int
+main ()
+{
+ ...
+
+ xml_schema::document_simpl doc_s (people_s, "people");
+
+ for (size_t i = 0; i &lt; 4; ++i)
+ {
+ try
+ {
+ people_s.pre ();
+ doc_s.serialize (cout);
+ people_s.post ();
+ }
+ catch (const xml_schema::serializer_exception&amp;)
+ {
+ doc_s.reset ();
+ }
+ }
+}
+ </pre>
+
+ <p>If you do not need to reuse serializers after an error for example
+ because your application terminates or you create a new serializer
+ instance in such situations, then you can avoid generating
+ serializer reset code by specifying the <code>--suppress-reset</code>
+ XSD/e compiler option.</p>
+
+ <p>Your individual serializer implementations may also require extra
+ actions in order to bring them into a usable state after an
+ error. To accomplish this you can override the <code>_reset()</code>
+ virtual function as shown below. Notice that when you override the
+ <code>_reset()</code> function in your implementation, you should
+ always call the base skeleton version to allow it to reset
+ its state:</p>
+
+<pre class="c++">
+class person_simpl: public person_sskel
+{
+public:
+ virtual void
+ pre (person* p)
+ {
+ p_ = p;
+ }
+
+ virtual void
+ post ()
+ {
+ delete p_;
+ p_ = 0;
+ }
+
+ virtual void
+ _reset ()
+ {
+ person_sskel::_reset ();
+ delete p_;
+ p_ = 0;
+ }
+
+ ...
+
+private:
+ person* p_;
+};
+ </pre>
+
+ <p>Note also that the <code>_reset()</code> mechanism is used only when
+ an error has occurred. To make sure that your serializer implementations
+ arrive at the initial state during successful execution, use the
+ initialization (<code>pre()</code> and <code>_pre()</code>) and
+ finalization (<code>post_*()</code> and <code>_post()</code>)
+ callbacks.</p>
+
+
+ <!-- Appendix A -->
+
+
+ <h1><a name="A">Appendix A &mdash; Supported XML Schema Constructs</a></h1>
+
+ <p>The Embedded C++/Serializer mapping supports validation of the following
+ W3C XML Schema constructs in the generated code.</p>
+
+ <!-- border="1" is necessary for html2ps -->
+ <table id="features" border="1">
+ <tr><th>Construct</th><th>Notes</th></tr>
+ <tr><th colspan="2">Structure</th></tr>
+
+ <tr><td>element</td><td></td></tr>
+ <tr><td>attribute</td><td></td></tr>
+
+ <tr><td>any</td><td></td></tr>
+ <tr><td>anyAttribute</td><td></td></tr>
+
+ <tr><td>all</td><td></td></tr>
+ <tr><td>sequence</td><td></td></tr>
+ <tr><td>choice</td><td></td></tr>
+
+ <tr><td>complex type, empty content</td><td></td></tr>
+ <tr><td>complex type, mixed content</td><td></td></tr>
+ <tr><td>complex type, simple content extension</td><td></td></tr>
+ <tr><td>complex type, simple content restriction</td><td></td></tr>
+ <tr><td>complex type, complex content extension</td><td></td></tr>
+ <tr><td>complex type, complex content restriction</td><td></td></tr>
+
+ <tr><td>list</td><td></td></tr>
+
+ <tr><th colspan="2">Facets</th></tr>
+
+ <tr><td>length</td><td>String-based types.</td></tr>
+ <tr><td>minLength</td><td>String-based types.</td></tr>
+ <tr><td>maxLength</td><td>String-based types.</td></tr>
+ <tr><td>pattern</td><td>String-based types.</td></tr>
+ <tr><td>enumeration</td><td>String-based types.</td></tr>
+
+ <tr><td>minExclusive</td><td>Integer and floating-point types.</td></tr>
+ <tr><td>minInclusive</td><td>Integer and floating-point types.</td></tr>
+ <tr><td>maxExclusive</td><td>Integer and floating-point types.</td></tr>
+ <tr><td>maxInclusive</td><td>Integer and floating-point types.</td></tr>
+
+ <tr><th colspan="2">Datatypes</th></tr>
+
+ <tr><td>byte</td><td></td></tr>
+ <tr><td>unsignedByte</td><td></td></tr>
+ <tr><td>short</td><td></td></tr>
+ <tr><td>unsignedShort</td><td></td></tr>
+ <tr><td>int</td><td></td></tr>
+ <tr><td>unsignedInt</td><td></td></tr>
+ <tr><td>long</td><td></td></tr>
+ <tr><td>unsignedLong</td><td></td></tr>
+ <tr><td>integer</td><td></td></tr>
+ <tr><td>nonPositiveInteger</td><td></td></tr>
+ <tr><td>nonNegativeInteger</td><td></td></tr>
+ <tr><td>positiveInteger</td><td></td></tr>
+ <tr><td>negativeInteger</td><td></td></tr>
+
+ <tr><td>boolean</td><td></td></tr>
+
+ <tr><td>float</td><td></td></tr>
+ <tr><td>double</td><td></td></tr>
+ <tr><td>decimal</td><td></td></tr>
+
+ <tr><td>string</td><td></td></tr>
+ <tr><td>normalizedString</td><td></td></tr>
+ <tr><td>token</td><td></td></tr>
+ <tr><td>Name</td><td></td></tr>
+ <tr><td>NMTOKEN</td><td></td></tr>
+ <tr><td>NCName</td><td></td></tr>
+ <tr><td>language</td><td></td></tr>
+ <tr><td>anyURI</td><td></td></tr>
+
+ <tr><td>ID</td><td>Identity constraint is not enforced.</td></tr>
+ <tr><td>IDREF</td><td>Identity constraint is not enforced.</td></tr>
+
+ <tr><td>NMTOKENS</td><td></td></tr>
+ <tr><td>IDREFS</td><td>Identity constraint is not enforced.</td></tr>
+
+ <tr><td>QName</td><td></td></tr>
+
+ <tr><td>base64Binary</td><td></td></tr>
+ <tr><td>hexBinary</td><td></td></tr>
+
+ <tr><td>date</td><td></td></tr>
+ <tr><td>dateTime</td><td></td></tr>
+ <tr><td>duration</td><td></td></tr>
+ <tr><td>gDay</td><td></td></tr>
+ <tr><td>gMonth</td><td></td></tr>
+ <tr><td>gMonthDay</td><td></td></tr>
+ <tr><td>gYear</td><td></td></tr>
+ <tr><td>gYearMonth</td><td></td></tr>
+ <tr><td>time</td><td></td></tr>
+ </table>
+
+ </div>
+</div>
+
+
+</body>
+</html>
diff --git a/doc/cxx/serializer/guide/makefile b/doc/cxx/serializer/guide/makefile
new file mode 100644
index 0000000..7502a53
--- /dev/null
+++ b/doc/cxx/serializer/guide/makefile
@@ -0,0 +1,48 @@
+# file : doc/cxx/serializer/guide/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2006-2011 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../../build/bootstrap.make
+
+default := $(out_base)/
+dist := $(out_base)/.dist
+dist-win := $(out_base)/.dist-win
+cleandoc := $(out_base)/.cleandoc
+
+# Build.
+#
+$(default): $(out_base)/cxx-serializer-e-guide.ps \
+ $(out_base)/cxx-serializer-e-guide.pdf
+
+
+$(out_base)/cxx-serializer-e-guide.ps: $(src_base)/index.xhtml \
+ $(src_base)/figure-1.png \
+ $(src_base)/guide.html2ps \
+ | $(out_base)/.
+ $(call message,html2ps $<,html2ps -f $(src_base)/guide.html2ps -o $@ $<)
+
+$(out_base)/cxx-serializer-e-guide.pdf: $(out_base)/cxx-serializer-e-guide.ps | $(out_base)/.
+ $(call message,ps2pdf $<,ps2pdf14 $< $@)
+
+# Dist.
+#
+$(dist): path := $(subst $(src_root)/,,$(src_base))
+$(dist): $(out_base)/cxx-serializer-e-guide.ps $(out_base)/cxx-serializer-e-guide.pdf
+ $(call install-data,$(src_base)/figure-1.png,$(dist_prefix)/$(path)/figure-1.png)
+ $(call install-data,$(src_base)/index.xhtml,$(dist_prefix)/$(path)/index.xhtml)
+ $(call install-data,$(out_base)/cxx-serializer-e-guide.ps,$(dist_prefix)/$(path)/cxx-serializer-e-guide.ps)
+ $(call install-data,$(out_base)/cxx-serializer-e-guide.pdf,$(dist_prefix)/$(path)/cxx-serializer-e-guide.pdf)
+
+$(dist-win): $(dist)
+
+
+# Clean.
+#
+$(cleandoc):
+ $(call message,rm $$1,rm -f $$1,$(out_base)/cxx-serializer-e-guide.ps)
+ $(call message,rm $$1,rm -f $$1,$(out_base)/cxx-serializer-e-guide.pdf)
+
+# How to.
+#
+$(call include,$(bld_root)/install.make)
diff --git a/doc/default.css b/doc/default.css
new file mode 100644
index 0000000..bb3805b
--- /dev/null
+++ b/doc/default.css
@@ -0,0 +1,319 @@
+html {
+ margin : 0;
+ padding : 0;
+ background : white;
+}
+
+body {
+ font-family : "Lucida Grande", Verdana, "Bitstream Vera Sans", sans-serif;
+ font-weight : normal;
+ font-size : 13px;
+ line-height : 19px;
+
+ color : black;
+
+ margin : 0 2em 0 2em;
+ padding : 0;
+}
+
+
+body {
+ min-width: 40em;
+}
+
+#container {
+ max-width : 46em;
+ margin : 0 auto;
+ padding : 0 1em 0 1em;
+}
+
+
+
+/*
+ * Footer
+ *
+ */
+#footer {
+ color : #3a84a7;
+
+ padding : 1em 0 0.5em 0;
+
+ font-size : 10px;
+ line-height : 15px;
+
+ text-align: center;
+}
+
+#footer a:link, #footer a:visited {
+
+ color:#1d6699;
+ text-decoration: underline;
+}
+
+#footer a {
+ margin-left: 0.7em;
+ margin-right: 0.7em;
+}
+
+#footer p {
+ padding: 0;
+ margin: 0.3em 0 0 0;
+}
+
+/* Distribution terms. */
+#footer #terms {
+ text-align: justify;
+
+ font-size : 110%;
+ font-family : monospace;
+
+ padding : 1em 0 0.5em 0;
+}
+
+
+/*
+ * Content
+ *
+ */
+
+#content {
+ padding : 0em 0.1em 0 1.3em;
+ margin : 1.4em 0 0 0;
+}
+
+#content p,
+#content ol,
+#content ul,
+#content dl {
+ text-align: justify;
+}
+
+#content h1 {
+ margin-left: -0.89em;
+}
+
+a:link {
+ color:#0536d2;
+}
+
+
+/*
+ * Headings
+ *
+ */
+
+h1, h2, h3, h4, h5, h6 {
+ font-weight : 500;
+}
+
+h1 { font-size : 155%; }
+h2 { font-size : 130%; }
+h3 { font-size : 125%; }
+h4 { font-size : 110%; }
+h5 { font-size : 106%; }
+h6 { font-size : 100%; }
+
+h1 { margin : 1.8em 0 0.8em 0;}
+h2 { margin-top : 1.4em;}
+h3 { margin-top : 1em;}
+
+p.indent {
+ margin-left : 1.5em;
+}
+
+
+/*
+ * Fix for IE 5.5 table font problem
+ *
+ */
+
+table {
+ font-size : 13px;
+}
+
+
+/*
+ * table of content
+ *
+ */
+
+ul.toc li {
+ padding : .4em 0em 0em 0em;
+}
+
+
+/* Toc links don't need to show when they are visited. */
+.toc a:visited {
+ color:#0536d2;
+}
+
+
+/*
+ * lists
+ *
+ */
+
+
+/* list of links */
+ul.menu {
+ list-style-type : none;
+}
+
+ul.menu li {
+ padding-top : 0.3em;
+ padding-bottom : 0.3em;
+}
+
+
+
+/* @@ I should probably use child selector here */
+/* list with multiline list-elements */
+ul.multiline li, ol.multiline li, dl.multiline dd {
+ padding-top : 0.16em;
+ padding-bottom : 0.16em;
+
+ font-size : 11px;
+ line-height : 15px;
+}
+
+
+
+/* C++ code snippet */
+pre.cxx {
+ margin-top : 0em;
+ margin-bottom : 2em;
+
+ margin-left : 1em;
+}
+
+
+
+/* make code snippet */
+pre.make {
+ margin-top : 0em;
+ margin-bottom : 2em;
+
+ margin-left : 1em;
+}
+
+
+
+/* terminal output */
+pre.term {
+ margin-top : 0em;
+ margin-bottom : 2em;
+
+ margin-left : 1em;
+}
+
+
+/* Images */
+div.center {
+ text-align: center;
+}
+
+/* Document info. */
+#docinfo {
+ margin-top: 4em;
+ border-top: 1px dashed #000000;
+ font-size: 70%;
+}
+
+
+/* Footnote */
+
+#footnote {
+ margin-top : 2.5em;
+}
+
+#footnote hr, hr.footnote {
+ margin-left: 0;
+ margin-bottom: 0.6em;
+ width: 8em;
+ border-top: 1px solid #000000;
+ border-right: none;
+ border-bottom: none;
+ border-left: none;
+
+}
+
+#footnote ol {
+ margin-left: 0;
+ padding-left: 1.45em;
+}
+
+#footnote li {
+ text-align : left;
+ font-size : 11px;
+ line-height : 15px;
+
+ padding : .4em 0 .4em 0;
+}
+
+
+/* Normal table with borders, etc. */
+
+table.std {
+ margin: 2em 0 2em 0;
+
+ border-collapse : collapse;
+ border : 1px solid;
+ border-color : #000000;
+
+ font-size : 11px;
+ line-height : 14px;
+}
+
+table.std th, table.std td {
+ border : 1px solid;
+ padding : 0.6em 0.8em 0.6em 0.8em;
+}
+
+table.std th {
+ background : #cde8f6;
+}
+
+table.std td {
+ text-align: left;
+}
+
+
+/*
+ * "item | description" table.
+ *
+ */
+
+table.description {
+ border-style : none;
+ border-collapse : separate;
+ border-spacing : 0;
+
+ font-size : 13px;
+
+ margin : 0.6em 0 0.6em 0;
+ padding : 0 0 0 0;
+}
+
+table.description tr {
+ padding : 0 0 0 0;
+ margin : 0 0 0 0;
+}
+
+table.description * td, table.description * th {
+ border-style : none;
+ margin : 0 0 0 0;
+ vertical-align : top;
+}
+
+table.description * th {
+ font-weight : normal;
+ padding : 0.4em 1em 0.4em 0;
+ text-align : left;
+ white-space : nowrap;
+ background : none;
+}
+
+table.description * td {
+ padding : 0.4em 0 0.4em 1em;
+ text-align : justify;
+}
diff --git a/doc/makefile b/doc/makefile
new file mode 100644
index 0000000..ee3c5bd
--- /dev/null
+++ b/doc/makefile
@@ -0,0 +1,158 @@
+# file : doc/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+default := $(out_base)/
+dist := $(out_base)/.dist
+dist-win := $(out_base)/.dist-win
+install := $(out_base)/.install
+cleandoc := $(out_base)/.cleandoc
+
+# Import.
+#
+$(call import,\
+ $(scf_root)/import/cli/stub.make,\
+ cli: cli,cli-rules: cli_rules)
+
+# Build.
+#
+$(default): \
+$(out_base)/cxx/ \
+$(out_base)/xsde.xhtml \
+$(out_base)/xsde.1
+
+# Man/html pages.
+#
+$(out_base)/xsde.xhtml $(out_base)/xsde.1: cli := $(cli)
+$(out_base)/xsde.xhtml $(out_base)/xsde.1: cli_options += -I $(src_root)/xsde
+
+$(out_base)/xsde.xhtml $(out_base)/xsde.1: \
+$(src_root)/xsde/options.cli \
+$(src_root)/xsde/cxx/options.cli \
+$(src_root)/xsde/cxx/hybrid/options.cli \
+$(src_root)/xsde/cxx/parser/options.cli \
+$(src_root)/xsde/cxx/serializer/options.cli
+
+# Assemble the options from different files in a specific order.
+#
+
+# XHTML
+#
+$(out_base)/xsde.xhtml: $(src_base)/xsde-prologue.xhtml \
+ $(src_base)/xsde-epilogue.xhtml \
+ $(src_base)/xsde-hybrid-header.xhtml \
+ $(src_base)/xsde-parser-header.xhtml \
+ $(src_base)/xsde-serializer-header.xhtml \
+ | $(out_base)/.
+# Common options.
+#
+ $(call message,cli-html $$1,$(cli) $(cli_options) --generate-html \
+--stdout --suppress-undocumented --exclude-base --class CXX::options \
+--class options --html-prologue-file $(src_base)/xsde-prologue.xhtml \
+$$1 >$@, $(src_root)/xsde/cxx/options.cli)
+
+# C++/Hybrid options.
+#
+ $(call message,cli-html $$1,$(cli) $(cli_options) --generate-html \
+--stdout --suppress-undocumented --exclude-base \
+--html-prologue-file $(src_base)/xsde-hybrid-header.xhtml \
+$$1 >>$@, $(src_root)/xsde/cxx/hybrid/options.cli)
+
+# C++/Parser options.
+#
+ $(call message,cli-html $$1,$(cli) $(cli_options) --generate-html \
+--stdout --suppress-undocumented --exclude-base \
+--html-prologue-file $(src_base)/xsde-parser-header.xhtml \
+$$1 >>$@, $(src_root)/xsde/cxx/parser/options.cli)
+
+# C++/Serializer options.
+#
+ $(call message,cli-html $$1,$(cli) $(cli_options) --generate-html \
+--stdout --suppress-undocumented --exclude-base \
+--html-prologue-file $(src_base)/xsde-serializer-header.xhtml \
+--html-epilogue-file $(src_base)/xsde-epilogue.xhtml \
+$$1 >>$@, $(src_root)/xsde/cxx/serializer/options.cli)
+
+
+# MAN
+#
+$(out_base)/xsde.1: $(src_base)/xsde-prologue.1 \
+ $(src_base)/xsde-epilogue.1 \
+ $(src_base)/xsde-hybrid-header.1 \
+ $(src_base)/xsde-parser-header.1 \
+ $(src_base)/xsde-serializer-header.1 \
+ | $(out_base)/.
+# Common options.
+#
+ $(call message,cli-man $$1,$(cli) $(cli_options) --generate-man \
+--stdout --suppress-undocumented --exclude-base --class CXX::options \
+--class options --man-prologue-file $(src_base)/xsde-prologue.1 \
+$$1 >$@, $(src_root)/xsde/cxx/options.cli)
+
+# C++/Hybrid options.
+#
+ $(call message,cli-man $$1,$(cli) $(cli_options) --generate-man \
+--stdout --suppress-undocumented --exclude-base \
+--man-prologue-file $(src_base)/xsde-hybrid-header.1 \
+$$1 >>$@, $(src_root)/xsde/cxx/hybrid/options.cli)
+
+# C++/Parser options.
+#
+ $(call message,cli-man $$1,$(cli) $(cli_options) --generate-man \
+--stdout --suppress-undocumented --exclude-base \
+--man-prologue-file $(src_base)/xsde-parser-header.1 \
+$$1 >>$@, $(src_root)/xsde/cxx/parser/options.cli)
+
+# C++/Serializer options.
+#
+ $(call message,cli-man $$1,$(cli) $(cli_options) --generate-man \
+--stdout --suppress-undocumented --exclude-base \
+--man-prologue-file $(src_base)/xsde-serializer-header.1 \
+--man-epilogue-file $(src_base)/xsde-epilogue.1 \
+$$1 >>$@, $(src_root)/xsde/cxx/serializer/options.cli)
+
+
+# Dist.
+#
+dist-common := $(out_base)/.dist-common
+
+$(dist-common): $(out_base)/xsde.xhtml \
+ $(out_base)/xsde.1
+ $(call install-data,$(src_base)/default.css,$(dist_prefix)/doc/default.css)
+ $(call install-data,$(out_base)/xsde.xhtml,$(dist_prefix)/doc/xsde.xhtml)
+ $(call install-data,$(out_base)/xsde.1,$(dist_prefix)/doc/xsde.1)
+
+$(dist): $(dist-common) $(out_base)/cxx/.dist
+$(dist-win): $(dist-common) $(out_base)/cxx/.dist
+
+# Install.
+#
+$(install): $(out_base)/xsde.xhtml \
+ $(out_base)/xsde.1
+ $(call install-dir,$(src_base)/cxx,$(install_doc_dir)/xsde/cxx)
+ $(call install-data,$(src_base)/default.css,$(install_doc_dir)/xsde/default.css)
+ $(call install-data,$(out_base)/xsde.xhtml,$(install_doc_dir)/xsde/xsde.xhtml)
+ $(call install-data,$(out_base)/xsde.1,$(install_man_dir)/man1/xsde.1)
+
+# Clean.
+#
+$(cleandoc): $(src_base)/cxx/.cleandoc
+ $(call message,rm $$1,rm -f $$1,$(out_base)/xsde.1)
+ $(call message,rm $$1,rm -f $$1,$(out_base)/xsde.xhtml)
+
+# Generated .gitignore.
+#
+ifeq ($(out_base),$(src_base))
+$(out_base)/xsde.xhtml $(out_base)/xsde.1: | $(out_base)/.gitignore
+
+$(out_base)/.gitignore: files := xsde.1 xsde.xhtml
+$(clean): $(out_base)/.gitignore.clean
+
+$(call include,$(bld_root)/git/gitignore.make)
+endif
+
+$(call include,$(bld_root)/install.make)
+$(call import,$(src_base)/cxx/makefile)
diff --git a/doc/xsde-epilogue.1 b/doc/xsde-epilogue.1
new file mode 100644
index 0000000..3049ab0
--- /dev/null
+++ b/doc/xsde-epilogue.1
@@ -0,0 +1,540 @@
+.\"
+.\" Type map
+.\"
+.SH TYPE MAP
+
+Type map files are used to define a mapping between XML Schema and
+C++ types. For C++/Parser, the compiler uses this information to
+determine the return types of
+.B post_*
+functions in parser skeletons corresponding to XML Schema types as
+well as argument types for callbacks corresponding to elements and
+attributes of these types. For C++/Serializer, type maps are used
+to determine the argument type of
+.B pre
+functions in serializer skeletons corresponding to XML Schema types
+as well as return types for callbacks corresponding to elements and
+attributes of these types.
+
+The compiler has a set of predefined mapping rules that map the
+built-in XML Schema types to suitable C++ types (discussed in
+the following sub-sections) and all other types to
+.BR void .
+By providing your own type maps you can override these predefined
+rules. The format of the type map file is presented below:
+
+
+.RS
+.B namespace
+.I schema-namespace
+[
+.I cxx-namespace
+]
+.br
+.B {
+.br
+ (
+.B include
+.IB file-name ;
+)*
+.br
+ ([
+.B type
+]
+.I schema-type cxx-ret-type
+[
+.I cxx-arg-type
+.RB ] ;
+)*
+.br
+.B }
+.br
+.RE
+
+Both
+.I schema-namespace
+and
+.I schema-type
+are regex patterns while
+.IR cxx-namespace ,
+.IR cxx-ret-type ,
+and
+.I cxx-arg-type
+are regex pattern substitutions. All names can be optionally enclosed
+in \fR" "\fR, for example, to include white-spaces.
+
+.I schema-namespace
+determines XML Schema namespace. Optional
+.I cxx-namespace
+is prefixed to every C++ type name in this namespace declaration.
+.I cxx-ret-type
+is a C++ type name that is used as a return type for the
+.B post_*
+function in C++/Parser or for element/attribute callbacks in C++/Serializer.
+Optional
+.I cxx-arg-type
+is an argument type for element/attribute callbacks in C++/Parser or for the
+.B pre
+function in C++/Serializer. If
+.I cxx-arg-type
+is not specified, it defaults to
+.I cxx-ret-type
+if
+.I cxx-ret-type
+ends with
+.B *
+or
+.B &
+(that is, it is a pointer or a reference) and
+.B const
+\fIcxx-ret-type\fB&\fR otherwise.
+.I file-name
+is a file name either in the \fR" "\fR or < > format and is added with the
+.B #include
+directive to the generated code.
+
+The \fB#\fR character starts a comment that ends with a new line or end of
+file. To specify a name that contains \fB#\fR enclose it in \fR" "\fR. For
+example:
+
+.RS
+namespace http://www.example.com/xmlns/my my
+.br
+{
+.br
+ include "my.hxx";
+.br
+
+ # Pass apples by value.
+ #
+ apple apple;
+.br
+
+ # Pass oranges as pointers.
+ #
+ orange orange_t*;
+.br
+}
+.br
+.RE
+
+In the example above, for the
+.B http://www.example.com/xmlns/my#orange
+XML Schema type, the
+.B my::orange_t*
+C++ type will be used as both return and argument types.
+
+Several namespace declarations can be specified in a single file.
+The namespace declaration can also be completely omitted to map
+types in a schema without a namespace. For instance:
+
+.RS
+include "my.hxx";
+.br
+apple apple;
+.br
+
+namespace http://www.example.com/xmlns/my
+.br
+{
+.br
+ orange "const orange_t*";
+.br
+}
+.br
+.RE
+
+The compiler has a number of predefined mapping rules for the built-in
+XML Schema types that vary depending on the mapping used. They are
+described in the following subsections. The last predefined rule
+for all the mappings maps anything that wasn't mapped by previous rules to
+.BR void :
+
+.RS
+namespace .*
+.br
+{
+.br
+ .* void void;
+.br
+}
+.br
+.RE
+
+When you provide your own type maps with the
+.B --type-map
+option, they are evaluated first. This allows you to selectively override
+predefined rules.
+
+.\"
+.\" Predefined C++/Parser Type Maps
+.\"
+.SS Predefined C++/Parser Type Maps
+
+The C++/Parser mapping provides a number of predefined type map rules
+for the built-in XML Schema types. They can be presented as the
+following map files:
+
+.RS
+namespace http://www.w3.org/2001/XMLSchema
+.br
+{
+.br
+ boolean bool bool;
+.br
+
+ byte "signed char" "signed char";
+.br
+ unsignedByte "unsigned char" "unsigned char";
+.br
+
+ short short short;
+.br
+ unsignedShort "unsigned short" "unsigned short";
+.br
+
+ int int int;
+.br
+ unsignedInt "unsigned int" "unsigned int";
+.br
+
+ long "long long" "long long";
+.br
+ unsignedLong "unsigned long long" "unsigned long long";
+.br
+
+ integer long long;
+.br
+
+ negativeInteger long long;
+.br
+ nonPositiveInteger long long;
+.br
+
+ positiveInteger "unsigned long" "unsigned long";
+.br
+ nonNegativeInteger "unsigned long" "unsigned long";
+.br
+
+ float float float;
+.br
+ double double double;
+.br
+ decimal double double;
+.br
+
+ NMTOKENS xml_schema::string_sequence*;
+.br
+ IDREFS xml_schema::string_sequence*;
+.br
+
+ base64Binary xml_schema::buffer*;
+.br
+ hexBinary xml_schema::buffer*;
+.br
+
+ date xml_schema::date;
+.br
+ dateTime xml_schema::date_time;
+.br
+ duration xml_schema::duration;
+.br
+ gDay xml_schema::gday;
+.br
+ gMonth xml_schema::gmonth;
+.br
+ gMonthDay xml_schema::gmonth_day;
+.br
+ gYear xml_schema::gyear;
+.br
+ gYearMonth xml_schema::gyear_month;
+.br
+ time xml_schema::time;
+.br
+}
+.br
+.RE
+
+If the
+.B --no-stl
+option is not specified, the following mapping is used for the
+string-based XML Schema built-in types:
+
+.RS
+namespace http://www.w3.org/2001/XMLSchema
+.br
+{
+.br
+ include <string>;
+.br
+
+ string std::string;
+.br
+ normalizedString std::string;
+.br
+ token std::string;
+.br
+ Name std::string;
+.br
+ NMTOKEN std::string;
+.br
+ NCName std::string;
+.br
+ ID std::string;
+.br
+ IDREF std::string;
+.br
+ language std::string;
+.br
+ anyURI std::string;
+.br
+
+ QName xml_schema::qname;
+.br
+}
+.br
+.RE
+
+Otherwise, a C string-based mapping is used:
+
+.RS
+namespace http://www.w3.org/2001/XMLSchema
+.br
+{
+.br
+ string char*;
+.br
+ normalizedString char*;
+.br
+ token char*;
+.br
+ Name char*;
+.br
+ NMTOKEN char*;
+.br
+ NCName char*;
+.br
+ ID char*;
+.br
+ IDREF char*;
+.br
+ language char*;
+.br
+ anyURI char*;
+.br
+
+ QName xml_schema::qname*;
+.br
+}
+.br
+.RE
+
+.\"
+.\" Predefined C++/Serializer Type Maps
+.\"
+.SS Predefined C++/Serializer Type Maps
+
+The C++/Serializer mapping provides a number of predefined type map
+rules for the built-in XML Schema types. They can be presented as the
+following map files:
+
+.RS
+namespace http://www.w3.org/2001/XMLSchema
+.br
+{
+.br
+ boolean bool bool;
+.br
+
+ byte "signed char" "signed char";
+.br
+ unsignedByte "unsigned char" "unsigned char";
+.br
+
+ short short short;
+.br
+ unsignedShort "unsigned short" "unsigned short";
+.br
+
+ int int int;
+.br
+ unsignedInt "unsigned int" "unsigned int";
+.br
+
+ long "long long" "long long";
+.br
+ unsignedLong "unsigned long long" "unsigned long long";
+.br
+
+ integer long long;
+.br
+
+ negativeInteger long long;
+.br
+ nonPositiveInteger long long;
+.br
+
+ positiveInteger "unsigned long" "unsigned long";
+.br
+ nonNegativeInteger "unsigned long" "unsigned long";
+.br
+
+ float float float;
+.br
+ double double double;
+.br
+ decimal double double;
+.br
+
+ NMTOKENS "const xml_schema::string_sequence*";
+.br
+ IDREFS "const xml_schema::string_sequence*";
+.br
+
+ base64Binary "const xml_schema::buffer*";
+.br
+ hexBinary "const xml_schema::buffer*";
+.br
+
+ date xml_schema::date;
+.br
+ dateTime xml_schema::date_time;
+.br
+ duration xml_schema::duration;
+.br
+ gDay xml_schema::gday;
+.br
+ gMonth xml_schema::gmonth;
+.br
+ gMonthDay xml_schema::gmonth_day;
+.br
+ gYear xml_schema::gyear;
+.br
+ gYearMonth xml_schema::gyear_month;
+.br
+ time xml_schema::time;
+.br
+}
+.br
+.RE
+
+If the
+.B --no-stl
+option is not specified, the following mapping is used for the
+string-based XML Schema built-in types:
+
+.RS
+namespace http://www.w3.org/2001/XMLSchema
+.br
+{
+.br
+ include <string>;
+.br
+
+ string std::string;
+.br
+ normalizedString std::string;
+.br
+ token std::string;
+.br
+ Name std::string;
+.br
+ NMTOKEN std::string;
+.br
+ NCName std::string;
+.br
+ ID std::string;
+.br
+ IDREF std::string;
+.br
+ language std::string;
+.br
+ anyURI std::string;
+.br
+
+ QName xml_schema::qname;
+.br
+}
+.br
+.RE
+
+Otherwise, a C string-based mapping is used:
+
+.RS
+namespace http://www.w3.org/2001/XMLSchema
+.br
+{
+.br
+ string "const char*";
+.br
+ normalizedString "const char*";
+.br
+ token "const char*";
+.br
+ Name "const char*";
+.br
+ NMTOKEN "const char*";
+.br
+ NCName "const char*";
+.br
+ ID "const char*";
+.br
+ IDREF "const char*";
+.br
+ language "const char*";
+.br
+ anyURI "const char*";
+.br
+
+ QName "const xml_schema::qname*";
+.br
+}
+.br
+.RE
+
+.\"
+.\" REGEX AND SHELL QUOTING
+.\"
+.SH REGEX AND SHELL QUOTING
+When entering a regular expression argument in the shell command line
+it is often necessary to use quoting (enclosing the argument in " "
+or ' ') in order to prevent the shell from interpreting certain
+characters, for example, spaces as argument separators and $ as
+variable expansions.
+
+Unfortunately it is hard to achieve this in a manner that is portable
+across POSIX shells, such as those found on GNU/Linux and UNIX, and
+Windows shell. For example, if you use " " for quoting you will get
+a wrong result with POSIX shells if your expression contains $. The
+standard way of dealing with this on POSIX systems is to use ' '
+instead. Unfortunately, Windows shell does not remove ' ' from
+arguments when they are passed to applications. As a result you may
+have to use ' ' for POSIX and " " for Windows ($ is not treated as
+a special character on Windows).
+
+Alternatively, you can save regular expression options into a file,
+one option per line, and use this file with the
+.B --options-file
+option. With this approach you don't need to worry about shell quoting.
+
+.\"
+.\" DIAGNOSTICS
+.\"
+.SH DIAGNOSTICS
+If the input file is not a valid W3C XML Schema definition,
+.B xsde
+will issue diagnostic messages to
+.B STDERR
+and exit with non-zero exit code.
+
+.SH BUGS
+Send bug reports to the xsde-users@codesynthesis.com mailing list.
+
+.SH COPYRIGHT
+Copyright (c) 2005-2011 Code Synthesis Tools CC.
+
+Permission is granted to copy, distribute and/or modify this
+document under the terms of the GNU Free Documentation License,
+version 1.2; with no Invariant Sections, no Front-Cover Texts and
+no Back-Cover Texts. Copy of the license can be obtained from
+http://codesynthesis.com/licenses/fdl-1.2.txt
diff --git a/doc/xsde-epilogue.xhtml b/doc/xsde-epilogue.xhtml
new file mode 100644
index 0000000..93701c0
--- /dev/null
+++ b/doc/xsde-epilogue.xhtml
@@ -0,0 +1,365 @@
+ <h1>TYPE MAP</h1>
+
+ <p>Type map files are used to define a mapping between XML Schema
+ and C++ types. For C++/Parser, the compiler uses
+ this information to determine the return types of
+ <code><b>post_*</b></code> functions in parser skeletons
+ corresponding to XML Schema types as well as argument types
+ for callbacks corresponding to elements and attributes of these
+ types. For C++/Serializer, type maps are used to determine
+ the argument type of <code><b>pre</b></code> functions in
+ serializer skeletons corresponding to XML Schema types as
+ well as return types for callbacks corresponding to elements
+ and attributes of these types.</p>
+
+ <p>The compiler has a set of predefined mapping rules that map
+ the built-in XML Schema types to suitable C++ types (discussed
+ in the following sub-sections) and all other types to
+ <code><b>void</b></code>. By providing your own type maps you
+ can override these predefined rules. The format of the type map
+ file is presented below:
+ </p>
+
+ <pre>
+namespace &lt;schema-namespace> [&lt;cxx-namespace>]
+{
+ (include &lt;file-name>;)*
+ ([type] &lt;schema-type> &lt;cxx-ret-type> [&lt;cxx-arg-type>];)*
+}
+ </pre>
+
+ <p>Both <code><i>&lt;schema-namespace></i></code> and
+ <code><i>&lt;schema-type></i></code> are regex patterns while
+ <code><i>&lt;cxx-namespace></i></code>,
+ <code><i>&lt;cxx-ret-type></i></code>, and
+ <code><i>&lt;cxx-arg-type></i></code> are regex pattern
+ substitutions. All names can be optionally enclosed in
+ <code><b>"&nbsp;"</b></code>, for example, to include white-spaces.</p>
+
+ <p><code><i>&lt;schema-namespace></i></code> determines XML
+ Schema namespace. Optional <code><i>&lt;cxx-namespace></i></code>
+ is prefixed to every C++ type name in this namespace declaration.
+ <code><i>&lt;cxx-ret-type></i></code> is a C++ type name that is
+ used as a return type for the <code><b>post_*</b></code> function
+ in C++/Parser or for element/attribute callbacks in C++/Serializer.
+ Optional <code><i>&lt;cxx-arg-type></i></code> is an argument type
+ for element/attribute callbacks in C++/Parser or for the
+ <code><b>pre</b></code> function in C++/Serializer. If
+ <code><i>&lt;cxx-arg-type></i></code> is not specified, it defaults
+ to <code><i>&lt;cxx-ret-type></i></code> if <code><i>&lt;cxx-ret-type></i></code>
+ ends with <code><b>*</b></code> or <code><b>&amp;</b></code> (that is,
+ it is a pointer or a reference) and
+ <code><b>const</b>&nbsp;<i>&lt;cxx-ret-type></i><b>&amp;</b></code>
+ otherwise.
+ <code><i>&lt;file-name></i></code> is a file name either in the
+ <code><b>"&nbsp;"</b></code> or <code><b>&lt;&nbsp;></b></code> format
+ and is added with the <code><b>#include</b></code> directive to
+ the generated code.</p>
+
+ <p>The <code><b>#</b></code> character starts a comment that ends
+ with a new line or end of file. To specify a name that contains
+ <code><b>#</b></code> enclose it in <code><b>"&nbsp;"</b></code>.
+ For example:</p>
+
+ <pre>
+namespace http://www.example.com/xmlns/my my
+{
+ include "my.hxx";
+
+ # Pass apples by value.
+ #
+ apple apple;
+
+ # Pass oranges as pointers.
+ #
+ orange orange_t*;
+}
+ </pre>
+
+ <p>In the example above, for the
+ <code><b>http://www.example.com/xmlns/my#orange</b></code>
+ XML Schema type, the <code><b>my::orange_t*</b></code> C++ type will
+ be used as both return and argument types.</p>
+
+ <p>Several namespace declarations can be specified in a single
+ file. The namespace declaration can also be completely
+ omitted to map types in a schema without a namespace. For
+ instance:</p>
+
+ <pre>
+include "my.hxx";
+apple apple;
+
+namespace http://www.example.com/xmlns/my
+{
+ orange "const orange_t*";
+}
+ </pre>
+
+ <p>The compiler has a number of predefined mapping rules
+ for the built-in XML Schema types that vary depending on
+ the mapping used. They are described in the following
+ subsections. The last predefined rule for all the mappings
+ maps anything that wasn't mapped by previous rules to
+ <code><b>void</b></code>:</p>
+
+ <pre>
+namespace .*
+{
+ .* void void;
+}
+ </pre>
+
+ <p>When you provide your own type maps with the
+ <code><b>--type-map</b></code> option, they are evaluated first.
+ This allows you to selectively override predefined rules.</p>
+
+
+ <h2>Predefined C++/Parser Type Maps</h2>
+
+ <p>The C++/Parser mapping provides a number of predefined type
+ map rules for the built-in XML Schema types. They can be
+ presented as the following map files:</p>
+
+ <pre>
+namespace http://www.w3.org/2001/XMLSchema
+{
+ boolean bool bool;
+
+ byte "signed char" "signed char";
+ unsignedByte "unsigned char" "unsigned char";
+
+ short short short;
+ unsignedShort "unsigned short" "unsigned short";
+
+ int int int;
+ unsignedInt "unsigned int" "unsigned int";
+
+ long "long long" "long long";
+ unsignedLong "unsigned long long" "unsigned long long";
+
+ integer long long;
+
+ negativeInteger long long;
+ nonPositiveInteger long long;
+
+ positiveInteger "unsigned long" "unsigned long";
+ nonNegativeInteger "unsigned long" "unsigned long";
+
+ float float float;
+ double double double;
+ decimal double double;
+
+ NMTOKENS xml_schema::string_sequence*;
+ IDREFS xml_schema::string_sequence*;
+
+ base64Binary xml_schema::buffer*;
+ hexBinary xml_schema::buffer*;
+
+ date xml_schema::date;
+ dateTime xml_schema::date_time;
+ duration xml_schema::duration;
+ gDay xml_schema::gday;
+ gMonth xml_schema::gmonth;
+ gMonthDay xml_schema::gmonth_day;
+ gYear xml_schema::gyear;
+ gYearMonth xml_schema::gyear_month;
+ time xml_schema::time;
+}
+ </pre>
+
+ <p>If the <code><b>--no-stl</b></code> option is not specified,
+ the following mapping is used for the string-based XML Schema
+ built-in types:</p>
+
+ <pre>
+namespace http://www.w3.org/2001/XMLSchema
+{
+ include &lt;string>;
+
+ string std::string;
+ normalizedString std::string;
+ token std::string;
+ Name std::string;
+ NMTOKEN std::string;
+ NCName std::string;
+ ID std::string;
+ IDREF std::string;
+ language std::string;
+ anyURI std::string;
+
+ QName xml_schema::qname;
+}
+ </pre>
+
+ <p>Otherwise, a C string-based mapping is used:</p>
+
+ <pre>
+namespace http://www.w3.org/2001/XMLSchema
+{
+ string char*;
+ normalizedString char*;
+ token char*;
+ Name char*;
+ NMTOKEN char*;
+ NCName char*;
+ ID char*;
+ IDREF char*;
+ language char*;
+ anyURI char*;
+
+ QName xml_schema::qname*;
+}
+ </pre>
+
+ <h2>Predefined C++/Serializer Type Maps</h2>
+
+ <p>The C++/Serializer mapping provides a number of predefined type
+ map rules for the built-in XML Schema types. They can be
+ presented as the following map files:</p>
+
+ <pre>
+namespace http://www.w3.org/2001/XMLSchema
+{
+ boolean bool bool;
+
+ byte "signed char" "signed char";
+ unsignedByte "unsigned char" "unsigned char";
+
+ short short short;
+ unsignedShort "unsigned short" "unsigned short";
+
+ int int int;
+ unsignedInt "unsigned int" "unsigned int";
+
+ long "long long" "long long";
+ unsignedLong "unsigned long long" "unsigned long long";
+
+ integer long long;
+
+ negativeInteger long long;
+ nonPositiveInteger long long;
+
+ positiveInteger "unsigned long" "unsigned long";
+ nonNegativeInteger "unsigned long" "unsigned long";
+
+ float float float;
+ double double double;
+ decimal double double;
+
+ NMTOKENS "const xml_schema::string_sequence*";
+ IDREFS "const xml_schema::string_sequence*";
+
+ base64Binary "const xml_schema::buffer*";
+ hexBinary "const xml_schema::buffer*";
+
+ date xml_schema::date;
+ dateTime xml_schema::date_time;
+ duration xml_schema::duration;
+ gDay xml_schema::gday;
+ gMonth xml_schema::gmonth;
+ gMonthDay xml_schema::gmonth_day;
+ gYear xml_schema::gyear;
+ gYearMonth xml_schema::gyear_month;
+ time xml_schema::time;
+}
+ </pre>
+
+ <p>If the <code><b>--no-stl</b></code> option is not specified,
+ the following mapping is used for the string-based XML Schema
+ built-in types:</p>
+
+ <pre>
+namespace http://www.w3.org/2001/XMLSchema
+{
+ include &lt;string>;
+
+ string std::string;
+ normalizedString std::string;
+ token std::string;
+ Name std::string;
+ NMTOKEN std::string;
+ NCName std::string;
+ ID std::string;
+ IDREF std::string;
+ language std::string;
+ anyURI std::string;
+
+ QName xml_schema::qname;
+}
+ </pre>
+
+ <p>Otherwise, a C string-based mapping is used:</p>
+
+ <pre>
+namespace http://www.w3.org/2001/XMLSchema
+{
+ string "const char*";
+ normalizedString "const char*";
+ token "const char*";
+ Name "const char*";
+ NMTOKEN "const char*";
+ NCName "const char*";
+ ID "const char*";
+ IDREF "const char*";
+ language "const char*";
+ anyURI "const char*";
+
+ QName "const xml_schema::qname*";
+}
+ </pre>
+
+ <h1>REGEX AND SHELL QUOTING</h1>
+
+ <p>When entering a regular expression argument in the shell
+ command line it is often necessary to use quoting (enclosing
+ the argument in <code><b>"&nbsp;"</b></code> or
+ <code><b>'&nbsp;'</b></code>) in order to prevent the shell
+ from interpreting certain characters, for example, spaces as
+ argument separators and <code><b>$</b></code> as variable
+ expansions.</p>
+
+ <p>Unfortunately it is hard to achieve this in a manner that is
+ portable across POSIX shells, such as those found on
+ GNU/Linux and UNIX, and Windows shell. For example, if you
+ use <code><b>"&nbsp;"</b></code> for quoting you will get a
+ wrong result with POSIX shells if your expression contains
+ <code><b>$</b></code>. The standard way of dealing with this
+ on POSIX systems is to use <code><b>'&nbsp;'</b></code> instead.
+ Unfortunately, Windows shell does not remove <code><b>'&nbsp;'</b></code>
+ from arguments when they are passed to applications. As a result you
+ may have to use <code><b>'&nbsp;'</b></code> for POSIX and
+ <code><b>"&nbsp;"</b></code> for Windows (<code><b>$</b></code> is
+ not treated as a special character on Windows).</p>
+
+ <p>Alternatively, you can save regular expression options into
+ a file, one option per line, and use this file with the
+ <code><b>--options-file</b></code> option. With this approach
+ you don't need to worry about shell quoting.</p>
+
+ <h1>DIAGNOSTICS</h1>
+
+ <p>If the input file is not a valid W3C XML Schema definition,
+ <code><b>xsde</b></code> will issue diagnostic messages to STDERR
+ and exit with non-zero exit code.</p>
+
+ <h1>BUGS</h1>
+
+ <p>Send bug reports to the
+ <a href="mailto:xsde-users@codesynthesis.com">xsde-users@codesynthesis.com</a> mailing list.</p>
+
+ </div>
+ <div id="footer">
+ &copy;2005-2011 <a href="http://codesynthesis.com">CODE SYNTHESIS TOOLS CC</a>
+
+ <div id="terms">
+ Permission is granted to copy, distribute and/or modify this
+ document under the terms of the
+ <a href="http://codesynthesis.com/licenses/fdl-1.2.txt">GNU Free
+ Documentation License, version 1.2</a>; with no Invariant Sections,
+ no Front-Cover Texts and no Back-Cover Texts.
+ </div>
+ </div>
+</div>
+</body>
+</html>
diff --git a/doc/xsde-hybrid-header.1 b/doc/xsde-hybrid-header.1
new file mode 100644
index 0000000..2853956
--- /dev/null
+++ b/doc/xsde-hybrid-header.1
@@ -0,0 +1,4 @@
+.\"
+.\" C++/Hybrid options.
+.\"
+.SS cxx-hybrid command options
diff --git a/doc/xsde-hybrid-header.xhtml b/doc/xsde-hybrid-header.xhtml
new file mode 100644
index 0000000..b208c2a
--- /dev/null
+++ b/doc/xsde-hybrid-header.xhtml
@@ -0,0 +1 @@
+ <h2>CXX-HYBRID COMMAND OPTIONS</h2>
diff --git a/doc/xsde-parser-header.1 b/doc/xsde-parser-header.1
new file mode 100644
index 0000000..b9785f1
--- /dev/null
+++ b/doc/xsde-parser-header.1
@@ -0,0 +1,4 @@
+.\"
+.\" C++/Parser options.
+.\"
+.SS cxx-parser command options
diff --git a/doc/xsde-parser-header.xhtml b/doc/xsde-parser-header.xhtml
new file mode 100644
index 0000000..94fa2c1
--- /dev/null
+++ b/doc/xsde-parser-header.xhtml
@@ -0,0 +1 @@
+ <h2>CXX-PARSER COMMAND OPTIONS</h2>
diff --git a/doc/xsde-prologue.1 b/doc/xsde-prologue.1
new file mode 100644
index 0000000..e03f9e5
--- /dev/null
+++ b/doc/xsde-prologue.1
@@ -0,0 +1,171 @@
+.\" Process this file with
+.\" groff -man -Tascii xsde.1
+.\"
+.TH XSD/e 1 "September 2011" "XSD/e 3.3.0"
+.SH NAME
+xsde \- W3C XML Schema to C++ Compiler for Embedded Systems
+.\"
+.\"
+.\"
+.\"--------------------------------------------------------------------
+.SH SYNOPSIS
+.\"--------------------------------------------------------------------
+.B xsde
+.I command
+.B [
+.I options
+.B ]
+.I file
+.B [
+.I file
+.B ...]
+.in
+.B xsde help
+.B [
+.I command
+.B ]
+.in
+.B xsde version
+.\"
+.\"
+.\"
+.\"--------------------------------------------------------------------
+.SH DESCRIPTION
+.\"--------------------------------------------------------------------
+.B xsde
+generates vocabulary-specific, statically-typed C++ mapping from W3C XML
+Schema definitions. Particular mapping to produce is selected by a
+.IR command .
+Each mapping has a number of mapping-specific
+.I options
+that should appear, if any, after the
+.IR command .
+Input files should be W3C XML Schema definitions. The exact set of the
+generated files depends on the selected mapping and options.
+.\"
+.\"
+.\"
+.\"--------------------------------------------------------------------
+.SH COMMANDS
+.\"--------------------------------------------------------------------
+.IP \fBcxx-hybrid\fR
+Generate the Embedded C++/Hybrid mapping. For each input file in the
+form
+.B name.xsd
+the following C++ files are generated:
+.B name.hxx
+(object model header file),
+.B name.ixx
+(object model inline file, generated only if the
+.B --generate-inline
+option is specified),
+.B name.cxx
+(object model source file), and
+.B name-fwd.hxx
+(object model forward declaration file, generated only if the
+.B --generate-forward
+option is specified).
+
+If the
+.B --generate-parser
+option is specified, the Embedded C++/Parser mapping is invoked and the
+.BR name-pskel.hxx ,
+.BR name-pskel.ixx ,
+and
+.B name-pskel.cxx
+parser skeleton files are generated, as described below. Additionally,
+the following parser implementation files are generated:
+.B name-pimpl.hxx
+(parser implementation header file) and
+.B name-pimpl.cxx
+(parser implementation source file).
+
+If the
+.B --generate-serializer
+option is specified, the Embedded C++/Serializer mapping is invoked and the
+.BR name-sskel.hxx ,
+.BR name-sskel.ixx ,
+and
+.B name-sskel.cxx
+serializer skeleton files are generated, as described below. Additionally,
+the following serializer implementation files are generated:
+.B name-simpl.hxx
+(serializer implementation header file) and
+.B name-simpl.cxx
+(serializer implementation source file).
+
+.IP \fBcxx-parser\fR
+Generate the Embedded C++/Parser mapping. For each input file in the form
+.B name.xsd
+the following C++ files are generated:
+.B name-pskel.hxx
+(parser skeleton header file),
+.B name-pskel.ixx
+(parser skeleton inline file, generated only if the
+.B --generate-inline
+option is specified), and
+.B name-pskel.cxx
+(parser skeleton source file). If the
+.B --generate-noop-impl
+or
+.B --generate-print-impl
+option is specified, the following additional sample implementation files
+are generated:
+.B name-pimpl.hxx
+(parser implementation header file) and
+.B name-pimpl.cxx
+(parser implementation source file). If the
+.B --generate-test-driver
+option is specified, the additional
+.B name-pdriver.cxx
+test driver file is generated.
+
+.IP \fBcxx-parser\fR
+Generate the Embedded C++/Serializer mapping. For each input file in the form
+.B name.xsd
+the following C++ files are generated:
+.B name-sskel.hxx
+(serializer skeleton header file),
+.B name-sskel.ixx
+(serializer skeleton inline file, generated only if the
+.B --generate-inline
+option is specified), and
+.B name-sskel.cxx
+(serializer skeleton source file). If the
+.B --generate-empty-impl
+option is specified, the following additional sample implementation files
+are generated:
+.B name-simpl.hxx
+(serializer implementation header file) and
+.B name-simpl.cxx
+(serializer implementation source file). If the
+.B --generate-test-driver
+option is specified, the additional
+.B name-sdriver.cxx
+test driver file is generated.
+
+.IP \fBhelp\fR
+Print usage information and exit. Use
+.PP
+.RS
+.RS 3
+.B xsde help
+.I command
+.RE
+.PP
+for command-specific help.
+.RE
+.IP \fBversion\fR
+Print version and exit.
+.\"--------------------------------------------------------------------
+.SH OPTIONS
+.\"--------------------------------------------------------------------
+Command-specific
+.IR options ,
+if any, should appear after the corresponding
+.IR command .
+
+.\"
+.\" Common options.
+.\"
+.SS common options
diff --git a/doc/xsde-prologue.xhtml b/doc/xsde-prologue.xhtml
new file mode 100644
index 0000000..c88f65b
--- /dev/null
+++ b/doc/xsde-prologue.xhtml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<head>
+ <title>XSD/e 3.3.0 Compiler Command Line Manual</title>
+
+ <meta name="copyright" content="&copy; 2005-2011 Code Synthesis Tools CC"/>
+ <meta name="keywords" content="xsd,xml,schema,c++,mapping,data,binding,code,generator,manual,man,page"/>
+ <meta name="description" content="XSD/e Compiler Command Line Manual"/>
+
+ <link rel="stylesheet" type="text/css" href="default.css" />
+
+<style type="text/css">
+
+ #synopsis {
+ list-style-type: none;
+ }
+
+ #synopsis li {
+ padding-top : 0.0em;
+ padding-bottom : 0.0em;
+ }
+
+ #commands dt {
+ padding-top : 0.4em;
+ }
+
+ #commands dd {
+ padding-bottom : 0.4em;
+ padding-left : 2em;
+ }
+
+ .options dt {
+ padding-top : 0.4em;
+ }
+
+ .options dd {
+ padding-top : 0.1em;
+ padding-bottom : 0.4em;
+ padding-left : 1.4em;
+ }
+
+</style>
+</head>
+
+<body>
+<div id="container">
+ <div id="content">
+
+ <h1>NAME</h1>
+
+ <p>xsde - W3C XML Schema to C++ Compiler for Embedded Systems</p>
+
+ <h1>SYNOPSIS</h1>
+
+ <dl id="synopsis">
+ <dt><code><b>xsde</b> <i>command</i> [<i>options</i>] <i>file</i> [<i>file</i> ...]</code></dt>
+ <dt><code><b>xsde help</b> [<i>command</i>]</code></dt>
+ <dt><code><b>xsde version</b></code></dt>
+ </dl>
+
+ <h1>DESCRIPTION</h1>
+
+ <p><code><b>xsde</b></code> generates vocabulary-specific, statically-typed
+ C++ mapping from W3C XML Schema definitions. Particular mapping to
+ produce is selected by a <code><i>command</i></code>. Each mapping has
+ a number of mapping-specific <code><i>options</i></code> that should
+ appear, if any, after the <code><i>command</i></code>. Input files should
+ be W3C XML Schema definitions. The exact set of the generated files
+ depends on the selected mapping and options.</p>
+
+ <h1>COMMANDS</h1>
+
+ <dl id="commands">
+ <dt><code><b>cxx-hybrid</b></code></dt>
+ <dd>Generate the Embedded C++/Hybrid mapping. For each input file in the
+ form <code><b>name.xsd</b></code> the following C++ files are generated:
+ <code><b>name.hxx</b></code> (object model header file),
+ <code><b>name.ixx</b></code> (object model inline file, generated only
+ if the <code><b>--generate-inline</b></code> option is specified),
+ <code><b>name.cxx</b></code> (object model source file), and
+ <code><b>name-fwd.hxx</b></code> (object model forward declaration
+ file, generated only if the <code><b>--generate-forward</b></code>
+ option is specified).
+
+ <p>If the <code><b>--generate-parser</b></code> option is specified,
+ the Embedded C++/Parser mapping is invoked and the
+ <code><b>name-pskel.hxx</b></code>,
+ <code><b>name-pskel.ixx</b></code>, and
+ <code><b>name-pskel.cxx</b></code> parser skeleton files are
+ generated, as described below. Additionally, the following parser
+ implementation files are generated:
+ <code><b>name-pimpl.hxx</b></code> (parser implementation header
+ file) and
+ <code><b>name-pimpl.cxx</b></code> (parser implementation source
+ file).</p>
+
+ <p>If the <code><b>--generate-serializer</b></code> option is
+ specified, the Embedded C++/Serializer mapping is invoked and the
+ <code><b>name-sskel.hxx</b></code>,
+ <code><b>name-sskel.ixx</b></code>, and
+ <code><b>name-sskel.cxx</b></code> serializer skeleton files are
+ generated, as described below. Additionally, the following serializer
+ implementation files are generated:
+ <code><b>name-simpl.hxx</b></code> (serializer implementation header
+ file) and
+ <code><b>name-simpl.cxx</b></code> (serializer implementation source
+ file).</p>
+ </dd>
+
+ <dt><code><b>cxx-parser</b></code></dt>
+ <dd>Generate the Embedded C++/Parser mapping. For each input file in the
+ form <code><b>name.xsd</b></code> the following C++ files are generated:
+ <code><b>name-pskel.hxx</b></code> (parser skeleton header file),
+ <code><b>name-pskel.ixx</b></code> (parser skeleton inline file,
+ generated only if the <code><b>--generate-inline</b></code>
+ option is specified), and
+ <code><b>name-pskel.cxx</b></code> (parser skeleton source file).
+ If the <code><b>--generate-noop-impl</b></code> or
+ <code><b>--generate-print-impl</b></code> option is specified,
+ the following additional sample implementation files are generated:
+ <code><b>name-pimpl.hxx</b></code> (parser implementation header
+ file) and
+ <code><b>name-pimpl.cxx</b></code> (parser implementation source
+ file). If the <code><b>--generate-test-driver</b></code> option
+ is specified, the additional <code><b>name-pdriver.cxx</b></code>
+ test driver file is generated.</dd>
+
+ <dt><code><b>cxx-serializer</b></code></dt>
+ <dd>Generate the Embedded C++/Serializer mapping. For each input file
+ in the form <code><b>name.xsd</b></code> the following C++ files
+ are generated: <code><b>name-sskel.hxx</b></code> (serializer
+ skeleton header file), <code><b>name-sskel.ixx</b></code> (serializer
+ skeleton inline file, generated only if the
+ <code><b>--generate-inline</b></code> option is specified), and
+ <code><b>name-sskel.cxx</b></code> (serializer skeleton source file).
+ If the <code><b>--generate-empty-impl</b></code> option is specified,
+ the following additional sample implementation files are generated:
+ <code><b>name-simpl.hxx</b></code> (serializer implementation header
+ file) and <code><b>name-simpl.cxx</b></code> (serializer
+ implementation source file). If the <code><b>--generate-test-driver</b></code>
+ option is specified, the additional <code><b>name-sdriver.cxx</b></code>
+ test driver file is generated.
+ </dd>
+
+ <dt><code><b>help</b></code></dt>
+ <dd>Print usage information and exit. Use
+ <p><code><b>xsde help</b> <i>command</i></code></p>
+ for command-specific help.
+ </dd>
+
+ <dt><code><b>version</b></code></dt>
+ <dd>Print version and exit.</dd>
+ </dl>
+
+ <h1>OPTIONS</h1>
+
+ <p>Command-specific <code><i>options</i></code>, if any, should appear
+ after the corresponding <code><i>command</i></code>.</p>
+
+ <h2>COMMON OPTIONS</h2>
diff --git a/doc/xsde-serializer-header.1 b/doc/xsde-serializer-header.1
new file mode 100644
index 0000000..e977500
--- /dev/null
+++ b/doc/xsde-serializer-header.1
@@ -0,0 +1,4 @@
+.\"
+.\" C++/Serializer options.
+.\"
+.SS cxx-serializer command options
diff --git a/doc/xsde-serializer-header.xhtml b/doc/xsde-serializer-header.xhtml
new file mode 100644
index 0000000..78988bd
--- /dev/null
+++ b/doc/xsde-serializer-header.xhtml
@@ -0,0 +1 @@
+ <h2>CXX-SERIALIZER COMMAND OPTIONS</h2>