aboutsummaryrefslogtreecommitdiff
path: root/documentation
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 /documentation
parent7f2876d1fb227951bf2531847a4f540df7fcbb78 (diff)
Rename documentation/ to doc/
Diffstat (limited to 'documentation')
-rw-r--r--documentation/cxx/hybrid/guide/figure-1.pngbin11933 -> 0 bytes
-rw-r--r--documentation/cxx/hybrid/guide/figure-1.svg217
-rw-r--r--documentation/cxx/hybrid/guide/guide.html2ps65
-rw-r--r--documentation/cxx/hybrid/guide/index.xhtml6521
-rw-r--r--documentation/cxx/hybrid/guide/makefile48
-rw-r--r--documentation/cxx/makefile20
-rw-r--r--documentation/cxx/parser/guide/figure-1.pngbin34195 -> 0 bytes
-rw-r--r--documentation/cxx/parser/guide/figure-1.svg373
-rw-r--r--documentation/cxx/parser/guide/guide.html2ps65
-rw-r--r--documentation/cxx/parser/guide/index.xhtml5383
-rw-r--r--documentation/cxx/parser/guide/makefile48
-rw-r--r--documentation/cxx/serializer/guide/figure-1.pngbin30198 -> 0 bytes
-rw-r--r--documentation/cxx/serializer/guide/figure-1.svg372
-rw-r--r--documentation/cxx/serializer/guide/guide.html2ps65
-rw-r--r--documentation/cxx/serializer/guide/index.xhtml6542
-rw-r--r--documentation/cxx/serializer/guide/makefile48
-rw-r--r--documentation/default.css319
-rw-r--r--documentation/makefile158
-rw-r--r--documentation/xsde-epilogue.1540
-rw-r--r--documentation/xsde-epilogue.xhtml365
-rw-r--r--documentation/xsde-hybrid-header.14
-rw-r--r--documentation/xsde-hybrid-header.xhtml1
-rw-r--r--documentation/xsde-parser-header.14
-rw-r--r--documentation/xsde-parser-header.xhtml1
-rw-r--r--documentation/xsde-prologue.1171
-rw-r--r--documentation/xsde-prologue.xhtml162
-rw-r--r--documentation/xsde-serializer-header.14
-rw-r--r--documentation/xsde-serializer-header.xhtml1
28 files changed, 0 insertions, 21497 deletions
diff --git a/documentation/cxx/hybrid/guide/figure-1.png b/documentation/cxx/hybrid/guide/figure-1.png
deleted file mode 100644
index b89cec8..0000000
--- a/documentation/cxx/hybrid/guide/figure-1.png
+++ /dev/null
Binary files differ
diff --git a/documentation/cxx/hybrid/guide/figure-1.svg b/documentation/cxx/hybrid/guide/figure-1.svg
deleted file mode 100644
index ccc79cd..0000000
--- a/documentation/cxx/hybrid/guide/figure-1.svg
+++ /dev/null
@@ -1,217 +0,0 @@
-<?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/documentation/cxx/hybrid/guide/guide.html2ps b/documentation/cxx/hybrid/guide/guide.html2ps
deleted file mode 100644
index 92ef95d..0000000
--- a/documentation/cxx/hybrid/guide/guide.html2ps
+++ /dev/null
@@ -1,65 +0,0 @@
-@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/documentation/cxx/hybrid/guide/index.xhtml b/documentation/cxx/hybrid/guide/index.xhtml
deleted file mode 100644
index 9bf3df1..0000000
--- a/documentation/cxx/hybrid/guide/index.xhtml
+++ /dev/null
@@ -1,6521 +0,0 @@
-<?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/documentation/cxx/hybrid/guide/makefile b/documentation/cxx/hybrid/guide/makefile
deleted file mode 100644
index 9644150..0000000
--- a/documentation/cxx/hybrid/guide/makefile
+++ /dev/null
@@ -1,48 +0,0 @@
-# file : documentation/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/documentation/cxx/makefile b/documentation/cxx/makefile
deleted file mode 100644
index 3dce01d..0000000
--- a/documentation/cxx/makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# file : documentation/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/documentation/cxx/parser/guide/figure-1.png b/documentation/cxx/parser/guide/figure-1.png
deleted file mode 100644
index 15d1723..0000000
--- a/documentation/cxx/parser/guide/figure-1.png
+++ /dev/null
Binary files differ
diff --git a/documentation/cxx/parser/guide/figure-1.svg b/documentation/cxx/parser/guide/figure-1.svg
deleted file mode 100644
index d994a79..0000000
--- a/documentation/cxx/parser/guide/figure-1.svg
+++ /dev/null
@@ -1,373 +0,0 @@
-<?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/documentation/cxx/parser/guide/guide.html2ps b/documentation/cxx/parser/guide/guide.html2ps
deleted file mode 100644
index bfeca9e..0000000
--- a/documentation/cxx/parser/guide/guide.html2ps
+++ /dev/null
@@ -1,65 +0,0 @@
-@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/documentation/cxx/parser/guide/index.xhtml b/documentation/cxx/parser/guide/index.xhtml
deleted file mode 100644
index d070c5a..0000000
--- a/documentation/cxx/parser/guide/index.xhtml
+++ /dev/null
@@ -1,5383 +0,0 @@
-<?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/documentation/cxx/parser/guide/makefile b/documentation/cxx/parser/guide/makefile
deleted file mode 100644
index c4b0821..0000000
--- a/documentation/cxx/parser/guide/makefile
+++ /dev/null
@@ -1,48 +0,0 @@
-# file : documentation/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/documentation/cxx/serializer/guide/figure-1.png b/documentation/cxx/serializer/guide/figure-1.png
deleted file mode 100644
index 8700758..0000000
--- a/documentation/cxx/serializer/guide/figure-1.png
+++ /dev/null
Binary files differ
diff --git a/documentation/cxx/serializer/guide/figure-1.svg b/documentation/cxx/serializer/guide/figure-1.svg
deleted file mode 100644
index 68790f9..0000000
--- a/documentation/cxx/serializer/guide/figure-1.svg
+++ /dev/null
@@ -1,372 +0,0 @@
-<?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/documentation/cxx/serializer/guide/guide.html2ps b/documentation/cxx/serializer/guide/guide.html2ps
deleted file mode 100644
index 9e5fc78..0000000
--- a/documentation/cxx/serializer/guide/guide.html2ps
+++ /dev/null
@@ -1,65 +0,0 @@
-@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/documentation/cxx/serializer/guide/index.xhtml b/documentation/cxx/serializer/guide/index.xhtml
deleted file mode 100644
index 34ddbe1..0000000
--- a/documentation/cxx/serializer/guide/index.xhtml
+++ /dev/null
@@ -1,6542 +0,0 @@
-<?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/documentation/cxx/serializer/guide/makefile b/documentation/cxx/serializer/guide/makefile
deleted file mode 100644
index 4fb8c2a..0000000
--- a/documentation/cxx/serializer/guide/makefile
+++ /dev/null
@@ -1,48 +0,0 @@
-# file : documentation/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/documentation/default.css b/documentation/default.css
deleted file mode 100644
index bb3805b..0000000
--- a/documentation/default.css
+++ /dev/null
@@ -1,319 +0,0 @@
-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/documentation/makefile b/documentation/makefile
deleted file mode 100644
index 1b49042..0000000
--- a/documentation/makefile
+++ /dev/null
@@ -1,158 +0,0 @@
-# file : documentation/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)/documentation/default.css)
- $(call install-data,$(out_base)/xsde.xhtml,$(dist_prefix)/documentation/xsde.xhtml)
- $(call install-data,$(out_base)/xsde.1,$(dist_prefix)/documentation/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/documentation/xsde-epilogue.1 b/documentation/xsde-epilogue.1
deleted file mode 100644
index 3049ab0..0000000
--- a/documentation/xsde-epilogue.1
+++ /dev/null
@@ -1,540 +0,0 @@
-.\"
-.\" 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/documentation/xsde-epilogue.xhtml b/documentation/xsde-epilogue.xhtml
deleted file mode 100644
index 93701c0..0000000
--- a/documentation/xsde-epilogue.xhtml
+++ /dev/null
@@ -1,365 +0,0 @@
- <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/documentation/xsde-hybrid-header.1 b/documentation/xsde-hybrid-header.1
deleted file mode 100644
index 2853956..0000000
--- a/documentation/xsde-hybrid-header.1
+++ /dev/null
@@ -1,4 +0,0 @@
-.\"
-.\" C++/Hybrid options.
-.\"
-.SS cxx-hybrid command options
diff --git a/documentation/xsde-hybrid-header.xhtml b/documentation/xsde-hybrid-header.xhtml
deleted file mode 100644
index b208c2a..0000000
--- a/documentation/xsde-hybrid-header.xhtml
+++ /dev/null
@@ -1 +0,0 @@
- <h2>CXX-HYBRID COMMAND OPTIONS</h2>
diff --git a/documentation/xsde-parser-header.1 b/documentation/xsde-parser-header.1
deleted file mode 100644
index b9785f1..0000000
--- a/documentation/xsde-parser-header.1
+++ /dev/null
@@ -1,4 +0,0 @@
-.\"
-.\" C++/Parser options.
-.\"
-.SS cxx-parser command options
diff --git a/documentation/xsde-parser-header.xhtml b/documentation/xsde-parser-header.xhtml
deleted file mode 100644
index 94fa2c1..0000000
--- a/documentation/xsde-parser-header.xhtml
+++ /dev/null
@@ -1 +0,0 @@
- <h2>CXX-PARSER COMMAND OPTIONS</h2>
diff --git a/documentation/xsde-prologue.1 b/documentation/xsde-prologue.1
deleted file mode 100644
index e03f9e5..0000000
--- a/documentation/xsde-prologue.1
+++ /dev/null
@@ -1,171 +0,0 @@
-.\" 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/documentation/xsde-prologue.xhtml b/documentation/xsde-prologue.xhtml
deleted file mode 100644
index c88f65b..0000000
--- a/documentation/xsde-prologue.xhtml
+++ /dev/null
@@ -1,162 +0,0 @@
-<?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/documentation/xsde-serializer-header.1 b/documentation/xsde-serializer-header.1
deleted file mode 100644
index e977500..0000000
--- a/documentation/xsde-serializer-header.1
+++ /dev/null
@@ -1,4 +0,0 @@
-.\"
-.\" C++/Serializer options.
-.\"
-.SS cxx-serializer command options
diff --git a/documentation/xsde-serializer-header.xhtml b/documentation/xsde-serializer-header.xhtml
deleted file mode 100644
index 78988bd..0000000
--- a/documentation/xsde-serializer-header.xhtml
+++ /dev/null
@@ -1 +0,0 @@
- <h2>CXX-SERIALIZER COMMAND OPTIONS</h2>