diff options
Diffstat (limited to 'documentation')
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 Binary files differdeleted file mode 100644 index b89cec8..0000000 --- a/documentation/cxx/hybrid/guide/figure-1.png +++ /dev/null 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> </h1> - <h1> </h1> - <h1> </h1> - <h1> </h1> - <h1> </h1> - <h1> </h1> -</div> - <p>Copyright © 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="© 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 © 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"> -<?xml version="1.0"?> -<hello> - - <greeting>Hello</greeting> - - <name>sun</name> - <name>moon</name> - <name>world</name> - -</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"> -<?xml version="1.0"?> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:complexType name="hello"> - <xs:sequence> - <xs:element name="greeting" type="xs:string"/> - <xs:element name="name" type="xs:string" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:element name="hello" type="hello"/> - -</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& - greeting () const; - - std::string& - greeting (); - - void - greeting (const std::string&); - - // 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& - name () const; - - name_sequence& - 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 <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 << h->greeting () << ", " << *i << "!" << endl; - } - - delete h; - } - catch (const xml_schema::parser_exception& e) - { - cerr << argv[1] << ":" << e.line () << ":" << e.column () - << ": " << e.text () << 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 <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& e) - { - cerr << argv[1] << ":" << e.line () << ":" << e.column () - << ": " << e.text () << endl; - return 1; - } - catch (const xml_schema::serializer_exception& e) - { - cerr << "error: " << e.text () << 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"> -<hello> - <greeting>Hi</greeting> - <name>sun</name> - <name>moon</name> - <name>world</name> - <name>mars</name> -</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 <sstream> -#include <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& 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 << ostr.str () << endl; - } - catch (const xml_schema::serializer_exception& e) - { - cerr << "error: " << e.text () << 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"> -<hello> - <greeting>Hi</greeting> - <name>Jane</name> - <name>John</name> -</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 <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) && ferror (f)) - { - io_error = true; - break; - } - - doc_p.parse (buf, s, feof (f) != 0); - pe = doc_p._error (); - - } while (!pe && !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"> -<!-- base.xsd --> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:complexType name="base"> - <xs:sequence> - <xs:element name="b" type="xs:int"/> - </xs:sequence> - </xs:complexType> - - <!-- substitution group root --> - <xs:element name="base" type="base"/> - -</xs:schema> - </pre> - - <pre class="xml"> -<!-- derived.xsd --> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <include schemaLocation="base.xsd"/> - - <xs:complexType name="derived"> - <xs:complexContent> - <xs:extension base="base"> - <xs:sequence> - <xs:element name="d" type="xs:string"/> - </xs:sequence> - </xs:extension> - </xs:complexContent> - </xs:complexType> - - <xs:element name="derived" type="derived" substitutionGroup="base"/> - -</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"> -<!-- base.xsd --> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:complexType name="base"> - <xs:sequence> - <xs:element name="b" type="xs:int"/> - </xs:sequence> - </xs:complexType> - - <!-- substitution group root --> - <xs:element name="base" type="base"/> - - <xs:complexType name="root"> - <xs:sequence> - <xs:element ref="base" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <!-- document root --> - <xs:element name="root" type="root"/> - -</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"> -<?xml version="1.0"?> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:simpleType name="gender"> - <xs:restriction base="xs:string"> - <xs:enumeration value="male"/> - <xs:enumeration value="female"/> - </xs:restriction> - </xs:simpleType> - - <xs:complexType name="person"> - <xs:sequence> - <xs:element name="first-name" type="xs:string"/> - <xs:element name="middle-name" type="xs:string" minOccurs="0"/> - <xs:element name="last-name" type="xs:string"/> - <xs:element name="gender" type="gender"/> - <xs:element name="age" type="xs:unsignedShort"/> - </xs:sequence> - <xs:attribute name="id" type="xs:unsignedInt" use="required"/> - </xs:complexType> - - <xs:complexType name="people"> - <xs:sequence> - <xs:element name="person" type="person" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:element name="people" type="people"/> - -</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"> -<?xml version="1.0"?> -<people> - - <person id="1"> - <first-name>John</first-name> - <last-name>Doe</last-name> - <gender>male</gender> - <age>32</age> - </person> - - <person id="2"> - <first-name>Jane</first-name> - <middle-name>Mary</middle-name> - <last-name>Doe</last-name> - <gender>female</gender> - <age>28</age> - </person> - -</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&); - gender& operator= (const gender&); - - void - value (value_type); - - operator value_type () const; - - const char* - string () const; - -private: - ... -}; - -// person (fixed-length) -// -class person -{ -public: - person (); - person (const person&); - person& operator= (const person&); - - // id - // - unsigned int - id () const; - - unsigned int& - id (); - - void - id (unsigned int); - - // first-name - // - const std::string& - first_name () const; - - std::string& - first_name (); - - void - first_name (const std::string&); - - // middle-name - // - bool - middle_name_present () const; - - void - middle_name_present (bool); - - const std::string& - middle_name () const; - - std::string& - middle_name (); - - void - middle_name (const std::string&); - - // last-name - // - const std::string& - last_name () const; - - std::string& - last_name (); - - void - last_name (const std::string&); - - // gender - // - const ::gender& - gender () const; - - ::gender& - gender (); - - void - gender (const ::gender&); - - // age - // - unsigned short - age () const; - - unsigned short& - age (); - - void - age (unsigned short); - -private: - ... -}; - -// people (variable-length) -// -class people -{ -public: - people (); - -private: - people (const people&); - people& operator= (const people&); - -public: - // person - // - typedef xml_schema::fix_sequence<person> person_sequence; - typedef person_sequence::iterator person_iterator; - typedef person_sequence::const_iterator person_const_iterator; - - const person_sequence& - person () const; - - person_sequence& - 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"> -<xs:complexType name="staff"> - <xs:sequence> - <xs:element name="permanent" type="people"/> - <xs:element name="contract" type="people"/> - </xs:sequence> -</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&); - staff& operator= (const staff&); - -public: - // permanent - // - const people& - permanent () const; - - people& - permanent (); - - void - permanent (people*); - - people* - permanent_detach (); - - // contract - // - const people& - contract () const; - - people& - 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&); - gender& operator= (const gender&); - - 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 << g.string () << 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& - first_name () const; - - std::string& - first_name (); - - void - first_name (const std::string&); -}; - </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& - middle_name () const; - - std::string& - middle_name (); - - void - middle_name (const std::string&); -}; - </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& p = ... - -if (p.middle_name_present ()) -{ - cout << p.middle_name () << 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& p = ... - -if (p.middle_name_present ()) -{ - cout << *p.middle_name () << 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"> -<xs:complexType name="person"> - <xs:sequence> - <xs:element name="first-name" type="xs:string"/> - ... - </xs:sequence> - <xs:attribute name="id" type="xs:unsignedInt" use="required"/> - <xs:attribute name="verified" type="xs:boolean" default="false"/> -</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& - 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& x = ... - -if (x.foo_default ()) -{ - foo& 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"> -<xs:complexType name="person"> - ... - <xs:attribute name="verified" type="xs:boolean" fixed="true"/> -</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<person> person_sequence; - typedef person_sequence::iterator person_iterator; - typedef person_sequence::const_iterator person_const_iterator; - - const person_sequence& - person () const; - - person_sequence& - 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 <typename T> - class fix_sequence - { - public: - typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& 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&); - - private: - fix_sequence (const fix_sequence&); - - fix_sequence& - operator= (fix_sequence&); - - public: - iterator - begin (); - - const_iterator - begin () const; - - iterator - end (); - - const_iterator - end () const; - - T& - front (); - - const T& - front () const; - - T& - back (); - - const T& - back () const; - - T& - operator[] (size_t); - - const T& - 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&); - - iterator - insert (iterator, const T&); - - 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 <typename T> - class fix_sequence - { - public: - enum error - { - error_none, - error_no_memory - }; - - ... - - public: - error - push_back (const T&); - - error - insert (iterator, const T&); - - error - insert (iterator, const T&, iterator& 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 <typename T> - class var_sequence - { - public: - typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - - typedef size_t size_type; - typedef ptrdiff_t difference_type; - - typedef <implementation details> iterator; - typedef <implementation details> const_iterator; - - public: - var_sequence (); - - void - swap (var_sequence&); - - private: - var_sequence (const var_sequence&); - - var_sequence& - operator= (var_sequence&); - - public: - iterator - begin (); - - const_iterator - begin () const; - - iterator - end (); - - const_iterator - end () const; - - T& - front (); - - const T& - front () const; - - T& - back (); - - const T& - back () const; - - T& - operator[] (size_t); - - const T& - 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 <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& 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<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&); - - private: - string_sequence (string_sequence&); - - string_sequence& - operator= (string_sequence&); - - 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& 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"> -<complexType name="type"> - <sequence> - <sequence minOccurs="0"> - <element name="a" type="int"/> - <element name="b" type="string" maxOccurs="unbounded"/> - </sequence> - <sequence maxOccurs="unbounded"> - <element name="c" type="int"/> - <element name="d" type="string"/> - </sequence> - </sequence> -</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&); - type& operator= (const type&); - -public: - // sequence (variable-length) - // - class sequence_type - { - public: - sequence_type (); - - private: - sequence_type (const sequence_type&); - sequence_type& operator= (const sequence_type&); - - public: - // a - // - int - a () const; - - int& - 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& - b () const; - - b_sequence& - b (); - - private: - ... - }; - - bool - sequence_present () const; - - const sequence_type& - sequence () const; - - sequence_type& - sequence (); - - void - sequence (sequence_type*); - - // sequence1 (fixed-length) - // - class sequence1_type - { - public: - sequence1_type (); - sequence1_type (const sequence1_type&); - sequence1_type& operator= (const sequence1_type&); - - // c - // - int - c () const; - - int& - c (); - - void - c (int); - - // d - // - const std::string& - d () const; - - std::string& - d (); - - void - d (const std::string&); - - private: - ... - }; - - typedef xml_schema::fix_sequence<sequence1_type> sequence1_sequence; - typedef sequence1_sequence::iterator sequence1_iterator; - typedef sequence1_sequence::const_iterator sequence1_const_iterator; - - const sequence1_sequence& - sequence1 () const; - - sequence1_sequence& - 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"> -<complexType name="type"> - <choice> - <element name="a" type="int"/> - <element name="b" type="string"/> - <element name="c" type="boolean"/> - </choice> -</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&); - type& operator= (const type&); - - // 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& - a (); - - void - a (int); - - // b - // - const std::string& - b () const; - - std::string& - b (); - - void - b (const std::string&); - - // c - // - bool - c () const; - - bool& - 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& x = ... - -switch (x.choice_arm ()) -{ -case type::a_tag: - { - cout << "a: " << x.a () << endl; - break; - } -case type::b_tag: - { - cout << "b: " << x.b () << endl; - break; - } -case type::c_tag: - { - cout << "c: " << x.c () << 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"> -<complexType name="type"> - <choice maxOccurs="unbounded"> - <sequence> - <element name="a" type="int"/> - <element name="b" type="string"/> - </sequence> - <element name="c" type="boolean"/> - </choice> -</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&); - type& operator= (const type&); - -public: - // choice (fixed-length) - // - class choice_type - { - public: - choice_type (); - choice_type (const choice_type&); - choice_type& operator= (const choice_type&); - - 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&); - sequence_type& operator= (const sequence_type&); - - // a - // - int - a () const; - - int& - a (); - - void - a (int); - - // b - // - const std::string& - b () const; - - std::string& - b (); - - void - b (const std::string&); - - private: - ... - }; - - const sequence_type& - sequence () const; - - sequence_type& - sequence (); - - void - sequence (const sequence_type&); - - // c - // - bool - c () const; - - bool& - c (); - - void - c (bool); - - private: - ... - }; - - typedef xml_schema::fix_sequence<choice_type> choice_sequence; - typedef choice_sequence::iterator choice_iterator; - typedef choice_sequence::const_iterator choice_const_iterator; - - const choice_sequence& - choice () const; - - choice_sequence& - 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 <memory> -#include <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<people> ppl (people_p.post ()); - - // Iterate over individual person records. - // - people::person_sequence& ps = ppl->person (); - - for (people::person_iterator i = ps.begin (); i != ps.end (); ++i) - { - person& p = *i; - - // Print names: first-name and last-name are required elements, - // middle-name is optional. - // - cout << "name: " << p.first_name () << " "; - - if (p.middle_name_present ()) - cout << p.middle_name () << " "; - - cout << p.last_name () << endl; - - // Print gender, age, and id which are all required. - // - cout << "gender: " << p.gender ().string () << endl - << "age: " << p.age () << endl - << "id: " << p.id () << endl - << 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 <memory> -#include <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<people> ppl (people_p.post ()); - - // Iterate over individual person records and increment - // the age. - // - people::person_sequence& 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& john = ps[0]; - person& 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"> -<?xml version="1.0"?> -<people> - - <person id="1"> - <first-name>John</first-name> - <middle-name>Mary</middle-name> - <last-name>Doe</last-name> - <gender>male</gender> - <age>33</age> - </person> - - <person id="2"> - <first-name>Jane</first-name> - <last-name>Doe</last-name> - <gender>female</gender> - <age>29</age> - </person> - - <person id="1"> - <first-name>John</first-name> - <middle-name>Mary</middle-name> - <last-name>Doe</last-name> - <gender>male</gender> - <age>33</age> - </person> - -</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 <iostream> - -#include "people.hxx" -#include "people-simpl.hxx" - -using namespace std; - -int -main () -{ - people ppl; - people::person_sequence& 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"> -<?xml version="1.0" ?> -<people> - - <person id="1"> - <first-name>John</first-name> - <last-name>Doe</last-name> - <gender>male</gender> - <age>32</age> - </person> - - <person id="2"> - <first-name>Jane</first-name> - <middle-name>Mary</middle-name> - <last-name>Doe</last-name> - <gender>female</gender> - <age>28</age> - </person> - -</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& - custom_data () const; - - custom_data_sequence& - 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&); - - private: - data_sequence (const data_sequence&); - - data_sequence& - operator= (data_sequence&); - - 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& 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<data*> (p); -} - -person& = ...; -person::custom_data_sequence& cd = p.custom_data (); - -cd.destructor (&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<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<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<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<person> person_sequence; - typedef person_sequence::iterator person_iterator; - typedef person_sequence::const_iterator person_const_iterator; - - const person_sequence& - person () const; - - person_sequence& - 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& 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"> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:complexType name="person"> - <xs:sequence> - <xs:element name="name" type="xs:string"/> - </xs:sequence> - </xs:complexType> - - <!-- substitution group root --> - <xs:element name="person" type="person"/> - - <xs:complexType name="superman"> - <xs:complexContent> - <xs:extension base="person"> - <xs:attribute name="can-fly" type="xs:boolean"/> - </xs:extension> - </xs:complexContent> - </xs:complexType> - - <xs:element name="superman" - type="superman" - substitutionGroup="person"/> - - <xs:complexType name="batman"> - <xs:complexContent> - <xs:extension base="superman"> - <xs:attribute name="wing-span" type="xs:unsignedInt"/> - </xs:extension> - </xs:complexContent> - </xs:complexType> - - <xs:element name="batman" - type="batman" - substitutionGroup="superman"/> - - <xs:complexType name="supermen"> - <xs:sequence> - <xs:element ref="person" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:element name="supermen" type="supermen"/> - -</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"> -<supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - - <person> - <name>John Doe</name> - </person> - - <superman can-fly="false"> - <name>James "007" Bond</name> - </superman> - - <superman can-fly="true" wing-span="10" xsi:type="batman"> - <name>Bruce Wayne</name> - </superman> - -</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<supermen> sm (supermen_p.post ()); - -// Print what we've got. -// -for (supermen::person_iterator i = sm->person ().begin (); - i != sm->person ().end (); - ++i) -{ - person& p = *i; - - if (batman* b = dynamic_cast<batman*> (&p)) - { - cerr << b->name () << ", batman, wing span " << - b->wing_span () << endl; - } - else if (superman* s = dynamic_cast<superman*> (&p)) - { - cerr << s->name () << ", "; - - if (s->can_fly ()) - cerr << "flying "; - - cerr << "superman" << endl; - } - else - { - cerr << p.name () << ", ordinary person" << endl; - } -} - -// Add another superman entry. -// -auto_ptr<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& -_dynamic_type () const; - -static const std::string& -_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& p = *i; - const string& dt = p._dynamic_type (); - - if (dt == batman::_static_type ()) - { - batman& b = static_cast<batman&> (p) - cerr << b.name () << ", batman, wing span " << - b.wing_span () << endl; - } - else if (dt == superman::_static_type ()) - { - superman& s = static_cast<superman&> (p) - cerr << s.name () << ", "; - - if (s.can_fly ()) - cerr << "flying "; - - cerr << "superman" << endl; - } - else - { - cerr << p.name () << ", ordinary person" << 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 char</code></td> - </tr> - <tr> - <td><code>unsignedByte</code></td> - <td><code>unsigned_byte</code></td> - <td><code>unsigned 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 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 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 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 long</code> or - <code>unsigned long 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"> -<complexType name="measure"> - <simpleContent> - <extension base="int"> - <attribute name="unit" type="string" use="required"/> - </extension> - </simpleContent> -</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&); - measure& operator= (const measure&); - - // unit - // - const std::string& - unit () const; - - std::string& - unit (); - - void - unit (const std::string&); - -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& - operator= (int); - - public: - int - base_value () const; - - int& - base_value (); - - void - base_value (int); - - operator const int& () const; - operator int& (); - }; -} - </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& - 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& name); - qname (const std::string& prefix, const std::string& name); - - void - swap (qname&); - - const std::string& - prefix () const; - - std::string& - prefix (); - - void - prefix (const std::string&); - - const std::string& - name () const; - - std::string& - name (); - - void - name (const std::string&); - }; - - bool - operator== (const qname&, const qname&); - - bool - operator!= (const qname&, const qname&); -} - </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&); - - private: - qname (const qname&); - - qname& - operator= (const qname&); - - 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&, const qname&); - - bool - operator!= (const qname&, const qname&); -} -</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&); - - private: - qname (const qname&); - - qname& - operator= (const qname&); - - 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&, const qname&); - - bool - operator!= (const qname&, const qname&); -} - </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&); - - buffer& - operator= (const buffer&); - - public: - void - assign (void* data, size_t size); - - void - attach (void* data, size_t size, size_t capacity); - - void* - detach (); - - - void - swap (buffer&); - - 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&, const buffer&); - - bool - operator!= (const buffer&, const buffer&); -} - </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 <= 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&); - - buffer& - operator= (const buffer&); - - public: - error - assign (void* data, size_t size); - - error - attach (void* data, size_t size, size_t capacity); - - void* - detach (); - - void - swap (buffer&); - - public: - size_t - capacity () const; - - error - capacity (size_t); - - error - capacity (size_t, bool& moved); - - public: - size_t - size () const; - - error - size (size_t); - - error - size (size_t, bool& moved); - - public: - const char* - data () const; - - char* - data (); - - const char* - begin () const; - - char* - begin (); - - const char* - end () const; - - char* - end (); - }; - - bool - operator== (const buffer&, const buffer&); - - bool - operator!= (const buffer&, const buffer&); -} - </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&, const time_zone&); - - bool - operator!= (const time_zone&, const time_zone&); -} - </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&, const date&); - - bool - operator!= (const date&, const date&); -} - </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&, const date_time&); - - bool - operator!= (const date_time&, const date_time&); -} - </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&, const duration&); - - bool - operator!= (const duration&, const duration&); -} - </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&, const gday&); - - bool - operator!= (const gday&, const gday&); -} - </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&, const gmonth&); - - bool - operator!= (const gmonth&, const gmonth&); -} - </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&, const gmonth_day&); - - bool - operator!= (const gmonth_day&, const gmonth_day&); -} - </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&, const gyear&); - - bool - operator!= (const gyear&, const gyear&); -} - </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&, const gyear_month&); - - bool - operator!= (const gyear_month&, const gyear_month&); -} - </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&, const time&); - - bool - operator!= (const time&, const time&); -} - </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& - custom_data () const; - - custom_data_sequence& - 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& - custom_data () const; - - custom_data_sequence& - 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"> -<?xml version="1.0"?> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:complexType name="hello"> - <xs:sequence> - <xs:element name="greeting" type="xs:string"/> - <xs:element name="name" type="xs:string" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:element name="hello" type="hello"/> - -</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& - 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&); - - void - post (); - - hello_simpl& - 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& p) - { - // Check if the age constraints are met. - // - unsigned short age = p.age (); - - if (age >= min_age_ && age <= 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_ && age <= 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& i = people_base_simpl_state_.person_; - people::person_const_iterator& 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 <memory> -#include <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& 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<people> ppl (people_p.post ()); - - // Print what we've got. - // - people::person_sequence& ps = ppl->person (); - - for (people::person_iterator i = ps.begin (); i != ps.end (); ++i) - { - cerr << "first: " << i->first_name () << endl - << "last: " << i->last_name () << endl - << "gender: " << i->gender ().string () << endl - << "age: " << i->age () << endl - << endl; - } - - // Serialize. - // - people_saggr people_s; - people_simpl& 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"> -<?xml version="1.0"?> -<people> - - <person> - <first-name>John</first-name> - <last-name>Doe</last-name> - <gender>male</gender> - <age>32</age> - </person> - - <person> - <first-name>Jane</first-name> - <last-name>Doe</last-name> - <gender>female</gender> - <age>28</age> - </person> - - <person> - <first-name>Joe</first-name> - <last-name>Dirt</last-name> - <gender>male</gender> - <age>25</age> - </person> - -</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 - -<people> - <person> - <first-name>Jane</first-name> - <last-name>Doe</last-name> - <gender>female</gender> - <age>28</age> - </person> -</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<<</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<< (ostream&, const type&); - -void -operator>> (istream&, type&); - </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<< (ostream&, const type&); - -bool -operator>> (istream&, type&); - </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& x = ... // Object model. - - // Save to a CDR stream. - // - ACE_OutputCDR ace_ocdr; - xml_schema::ocdrstream ocdr (ace_ocdr); - - ocdr << 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&) -{ - cerr << "CDR operation failed" << endl; -} - </pre> - - <p>The same code fragment but when C++ exceptions are disabled:</p> - - <pre class="c++"> -const type& x = ... // Object model. - -// Save to a CDR stream. -// -ACE_OutputCDR ace_ocdr; -xml_schema::ocdrstream ocdr (ace_ocdr); - -if (!(ocdr << x)) -{ - cerr << "CDR operation failed" << endl; -} - -// Load from a CDR stream. -// -ACE_InputCDR ace_icdr (buf, size); -xml_schema::icdrstream icdr (ace_icdr); - -type copy; - -if (!(icdr >> copy)) -{ - cerr << "CDR operation failed" << 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& x = ... // Object model. - - // Save to a XDR stream. - // - XDR xdr; - xdrrec_create (&xdr, ...); - xml_schema::oxdrstream oxdr (xdr); - - oxdr << x; - - // Load from a XDR stream. - // - xdrrec_create (&xdr, ...); - xml_schema::ixdrstream ixdr (xdr); - - type copy; - ixdr >> copy; -} -catch (const xml_schema::xdr_exception&) -{ - cerr << "XDR operation failed" << endl; -} - </pre> - - <p>The same code fragment but when C++ exceptions are disabled:</p> - - <pre class="c++"> -const type& x = ... // Object model. - -// Save to a XDR stream. -// -XDR xdr; -xdrrec_create (&xdr, ...); -xml_schema::oxdrstream oxdr (xdr); - -if (!(oxdr << x)) -{ - cerr << "XDR operation failed" << endl; -} - -// Load from a XDR stream. -// -xdrrec_create (&xdr, ...); -xml_schema::ixdrstream ixdr (xdr); - -type copy; - -if (!(ixdr >> copy)) -{ - cerr << "XDR operation failed" << 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 Binary files differdeleted file mode 100644 index 15d1723..0000000 --- a/documentation/cxx/parser/guide/figure-1.png +++ /dev/null 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> </h1> - <h1> </h1> - <h1> </h1> - <h1> </h1> - <h1> </h1> - <h1> </h1> -</div> - <p>Copyright © 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="© 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 © 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 — 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"> -<?xml version="1.0"?> -<hello> - - <greeting>Hello</greeting> - - <name>sun</name> - <name>moon</name> - <name>world</name> - -</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"> -<?xml version="1.0"?> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:complexType name="hello"> - <xs:sequence> - <xs:element name="greeting" type="xs:string"/> - <xs:element name="name" type="xs:string" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:element name="hello" type="hello"/> - -</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&); - - virtual void - name (const std::string&); - - virtual void - post_hello (); - - // Parser construction API. - // - void - greeting_parser (xml_schema::string_pskel&); - - void - name_parser (xml_schema::string_pskel&); - - void - parsers (xml_schema::string_pskel& /* greeting */, - xml_schema::string_pskel& /* 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 <iostream> -#include "hello-pskel.hxx" - -class hello_pimpl: public hello_pskel -{ -public: - virtual void - greeting (const std::string& g) - { - greeting_ = g; - } - - virtual void - name (const std::string& n) - { - std::cout << greeting_ << ", " << n << "!" << 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& e) - { - cerr << argv[1] << ":" << e.line () << ":" << e.column () - << ": " << e.text () << 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"> -<?xml version="1.0"?> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:simpleType name="gender"> - <xs:restriction base="xs:string"> - <xs:enumeration value="male"/> - <xs:enumeration value="female"/> - </xs:restriction> - </xs:simpleType> - - <xs:complexType name="person"> - <xs:sequence> - <xs:element name="first-name" type="xs:string"/> - <xs:element name="last-name" type="xs:string"/> - <xs:element name="gender" type="gender"/> - <xs:element name="age" type="xs:short"/> - </xs:sequence> - </xs:complexType> - - <xs:complexType name="people"> - <xs:sequence> - <xs:element name="person" type="person" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:element name="people" type="people"/> - -</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"> -<?xml version="1.0"?> -<people> - <person> - <first-name>John</first-name> - <last-name>Doe</last-name> - <gender>male</gender> - <age>32</age> - </person> - <person> - <first-name>Jane</first-name> - <last-name>Doe</last-name> - <gender>female</gender> - <age>28</age> - </person> -</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 (&base_impl_) - { - } - - virtual void - post_gender () - { - std::string s = post_string (); - cout << "gender: " << s << 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&); - - 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—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&); - - virtual void - last_name (const std::string&); - - virtual void - gender (); - - virtual void - age (short); - - virtual void - post_person (); - - // Parser construction API. - // - void - first_name_parser (xml_schema::string_pskel&); - - void - last_name_parser (xml_schema::string_pskel&); - - void - gender_parser (gender_pskel&); - - void - age_parser (xml_schema::short_pskel&); - - void - parsers (xml_schema::string_pskel& /* first-name */, - xml_schema::string_pskel& /* last-name */, - gender_pskel& /* gender */, - xml_schema::short_pskel& /* 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& n) - { - cout << "first: " << f << endl; - } - - virtual void - last_name (const std::string& l) - { - cout << "last: " << l << endl; - } - - virtual void - age (short a) - { - cout << "age: " << a << 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&); - - void - parsers (person_pskel& /* 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 << 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&, - const std::string& root_element_name); - - document_pimpl (xml_schema::parser_base&, - const std::string& root_element_namespace, - const std::string& root_element_name); - - void - parse (const std::string& file); - - void - parse (std::istream&); - - 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"> -<?xml version="1.0"?> -<people> - <person> - <first-name>John</first-name> - <last-name>Doe</last-name> - <gender>male</gender> - <age>32</age> - </person> - <person> - <first-name>Jane</first-name> - <last-name>Doe</last-name> - <gender>female</gender> - <age>28</age> - </person> -</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 <string> -#include <vector> - -enum gender -{ - male, - female -}; - -class person -{ -public: - person (const std::string& first, - const std::string& last, - ::gender gender, - short age) - : first_ (first), last_ (last), - gender_ (gender), age_ (age) - { - } - - const std::string& - first () const - { - return first_; - } - - const std::string& - 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<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 <schema-namespace> [<cxx-namespace>] -{ - (include <file-name>;)* - ([type] <schema-type> <cxx-ret-type> [<cxx-arg-type>];)* -} - </pre> - - <p>Both <code><i><schema-namespace></i></code> and - <code><i><schema-type></i></code> are regex patterns while - <code><i><cxx-namespace></i></code>, - <code><i><cxx-ret-type></i></code>, and - <code><i><cxx-arg-type></i></code> are regex pattern - substitutions. All names can be optionally enclosed in - <code>" "</code>, for example, to include white-spaces.</p> - - <p><code><i><schema-namespace></i></code> determines XML - Schema namespace. Optional <code><i><cxx-namespace></i></code> - is prefixed to every C++ type name in this namespace declaration. - <code><i><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><cxx-arg-type></i></code> is an argument - type for callbacks corresponding to elements and attributes - of this type. If <code><i><cxx-arg-type></i></code> is not - specified, it defaults to <code><i><cxx-ret-type></i></code> - if <code><i><cxx-ret-type></i></code> ends with <code>*</code> or - <code>&</code> (that is, it is a pointer or a reference) and - <code>const <i><cxx-ret-type></i>&</code> - otherwise. - <code><i><file-name></i></code> is a file name either in the - <code>" "</code> or <code>< ></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>" "</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 <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 (&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& f) - { - first_ = f; - } - - virtual void - last_name (const std::string& 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& 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 <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 << "first: " << i->first () << endl - << "last: " << i->last () << endl - << "gender: " << (i->gender () == male ? "male" : "female") << endl - << "age: " << i->age () << endl - << 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& file); - - void - parse (std::istream&); - </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"> -<xs:complexType name="person"> - <xs:sequence> - <xs:element name="first-name" type="xs:string"/> - <xs:element name="last-name" type="xs:string"/> - <xs:element name="age" type="xs:short"/> - </xs:sequence> -</xs:complexType> - -<xs:complexType name="emplyee"> - <complexContent> - <extension base="person"> - <xs:sequence> - <xs:element name="position" type="xs:string"/> - <xs:element name="salary" type="xs:unsignedLong"/> - </xs:sequence> - </extension> - </complexContent> -</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 (&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 (&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<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"> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:complexType name="person"> - <xs:sequence> - <xs:element name="name" type="xs:string"/> - </xs:sequence> - </xs:complexType> - - <!-- substitution group root --> - <xs:element name="person" type="person"/> - - <xs:complexType name="superman"> - <xs:complexContent> - <xs:extension base="person"> - <xs:attribute name="can-fly" type="xs:boolean"/> - </xs:extension> - </xs:complexContent> - </xs:complexType> - - <xs:element name="superman" - type="superman" - substitutionGroup="person"/> - - <xs:complexType name="batman"> - <xs:complexContent> - <xs:extension base="superman"> - <xs:attribute name="wing-span" type="xs:unsignedInt"/> - </xs:extension> - </xs:complexContent> - </xs:complexType> - - <xs:element name="batman" - type="batman" - substitutionGroup="superman"/> - - <xs:complexType name="supermen"> - <xs:sequence> - <xs:element ref="person" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:element name="supermen" type="supermen"/> - -</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"> -<supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - - <person> - <name>John Doe</name> - </person> - - <superman can-fly="false"> - <name>James "007" Bond</name> - </superman> - - <superman can-fly="true" wing-span="10" xsi:type="batman"> - <name>Bruce Wayne</name> - </superman> - -</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 << "starting to parse person" << endl; - } - - virtual void - name (const std::string& v) - { - cout << "name: " << v << endl; - } - - virtual void - post_person () - { - cout << "finished parsing person" << endl; - } -}; - -class superman_pimpl: public superman_pskel -{ -public: - superman_pimpl () - : superman_pskel (&base_impl_) - { - } - - virtual void - pre () - { - cout << "starting to parse superman" << endl; - } - - virtual void - can_fly (bool v) - { - cout << "can-fly: " << v << endl; - } - - virtual void - post_person () - { - post_superman (); - } - - virtual void - post_superman () - { - cout << "finished parsing superman" << endl - } - -private: - person_pimpl base_impl_; -}; - -class batman_pimpl: public batman_pskel -{ -public: - batman_pimpl () - : batman_pskel (&base_impl_) - { - } - - virtual void - pre () - { - cout << "starting to parse batman" << endl; - } - - virtual void - wing_span (unsigned int v) - { - cout << "wing-span: " << v << endl; - } - - virtual void - post_person () - { - post_superman (); - } - - virtual void - post_superman () - { - post_batman (); - } - - virtual void - post_batman () - { - cout << "finished parsing batman" << 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&); - - // Individual element parsers. - // - void - person_parser (person_pskel&); - - void - person_parser (xml_schema::parser_map&); - - ... -}; - </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&); - - virtual parser_base* - find (const char* type) const; - - virtual void - reset () const; - - private: - parser_map_impl (const parser_map_impl&); - - parser_map_impl& - operator= (const parser_map_impl&); - - ... - }; -} - </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>"<name> <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 <map> -#include <string> - -class parser_map: public xml_schema::parser_map -{ -public: - void - insert (xml_schema::parser_base& p) - { - map_[p._dynamic_type ()] = &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<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 << "substitution hashmap load is " << load << endl; - cerr << "time to increase XSDE_PARSER_SMAP_BUCKETS" << endl; - } - - load = xml_schema::parser_imap_elements (); - load /= xml_schema::parser_imap_buckets (); - - if (load > 0.8) - { - cerr << "inheritance hashmap load is " << load << endl; - cerr << "time to increase XSDE_PARSER_IMAP_BUCKETS" << 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 <stdio.h> - -#include "people-pskel.hxx" - -class gender_pimpl: public gender_pskel -{ -public: - gender_pimpl () - : gender_pskel (&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) && ferror (f)) - { - io_error = true; - break; - } - - doc_p.parse (buf, s, feof (f) != 0); - e = doc_p._error (); - - } while (!e && !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 char</code></td> - </tr> - <tr> - <td><code>unsignedByte</code></td> - <td><code>unsigned_byte_pimpl</code></td> - <td><code>unsigned 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 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 int</code></td> - </tr> - - <!-- 64-bit --> - <tr> - <td><code>long</code></td> - <td><code>long_pimpl</code></td> - <td><code>long 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 long long</code> or - <code>unsigned 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 long</code></td> - </tr> - <tr> - <td><code>positiveInteger</code></td> - <td><code>positive_integer_pimpl</code></td> - <td><code>unsigned 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& name); - qname (const std::string& prefix, const std::string& name); - - void - swap (qname&); - - const std::string& - prefix () const; - - std::string& - prefix (); - - void - prefix (const std::string&); - - const std::string& - name () const; - - std::string& - name (); - - void - name (const std::string&); - }; - - bool - operator== (const qname&, const qname&); - - bool - operator!= (const qname&, const qname&); -} - </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&); - - private: - qname (const qname&); - - qname& - operator= (const qname&); - - 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&, const qname&); - - bool - operator!= (const qname&, const qname&); -} -</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&); - - private: - qname (const qname&); - - qname& - operator= (const qname&); - - 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&, const qname&); - - bool - operator!= (const qname&, const qname&); -} - </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& reference; - typedef const std::string& 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&); - - private: - string_sequence (string_sequence&); - - string_sequence& - operator= (string_sequence&); - - public: - iterator - begin (); - - const_iterator - begin () const; - - iterator - end (); - - const_iterator - end () const; - - std::string& - front (); - - const std::string& - front () const; - - std::string& - back (); - - const std::string& - back () const; - - std::string& - operator[] (size_t); - - const std::string& - 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&); - - iterator - insert (iterator, const std::string&); - - void - reserve (size_t); - }; - - bool - operator== (const string_sequence&, const string_sequence&); - - bool - operator!= (const string_sequence&, const string_sequence&); -} - </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&); - - error - insert (iterator, const std::string&); - - error - insert (iterator, const std::string&, iterator& 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&); - - private: - string_sequence (string_sequence&); - - string_sequence& - operator= (string_sequence&); - - 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&, const string_sequence&); - - bool - operator!= (const string_sequence&, const string_sequence&); -} - </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& 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&); - - buffer& - operator= (const buffer&); - - public: - void - attach (void* data, size_t size, size_t capacity); - - void* - detach (); - - void - swap (buffer&); - - 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&, const buffer&); - - bool - operator!= (const buffer&, const buffer&); -} - </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 <= 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&); - - buffer& - operator= (const buffer&); - - public: - error - attach (void* data, size_t size, size_t capacity); - - void* - detach (); - - void - swap (buffer&); - - public: - size_t - capacity () const; - - error - capacity (size_t); - - error - capacity (size_t, bool& moved); - - public: - size_t - size () const; - - error - size (size_t); - - error - size (size_t, bool& moved); - - public: - const char* - data () const; - - char* - data (); - - const char* - begin () const; - - char* - begin (); - - const char* - end () const; - - char* - end (); - }; - - bool - operator== (const buffer&, const buffer&); - - bool - operator!= (const buffer&, const buffer&); -} - </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&, const time_zone&); - - bool - operator!= (const time_zone&, const time_zone&); -} - </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&, const date&); - - bool - operator!= (const date&, const date&); -} - </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&, const date_time&); - - bool - operator!= (const date_time&, const date_time&); -} - </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&, const duration&); - - bool - operator!= (const duration&, const duration&); -} - </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&, const gday&); - - bool - operator!= (const gday&, const gday&); -} - </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&, const gmonth&); - - bool - operator!= (const gmonth&, const gmonth&); -} - </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&, const gmonth_day&); - - bool - operator!= (const gmonth_day&, const gmonth_day&); -} - </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&, const gyear&); - - bool - operator!= (const gyear&, const gyear&); -} - </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&, const gyear_month&); - - bool - operator!= (const gyear_month&, const gyear_month&); -} - </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&, const time&); - - bool - operator!= (const time&, const time&); -} - </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&, - const char* root_element_name); - - document_pimpl (parser_base&, - const char* root_element_namespace, - const char* root_element_name); - - document_pimpl (parser_base&, - const std::string& root_element_name); - - document_pimpl (parser_base&, - const std::string& root_element_namespace, - const std::string& 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& 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&); - - // 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& - operator<< (std::ostream&, const parser_exception&); - - - typedef <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 <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<<</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& e) - { - cout << argv[1] << ":" << e.line () << ":" << e.column () - << ": error: " << e.text () << 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 <implementation-details> parser_xml_error; - typedef <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 << argv[1] << ": error: " << e.sys_text () << endl; - break; - } - case parser_error::xml: - { - cerr << argv[1] << ":" << e.line () << ":" << e.column () - << ": error: " << e.xml_text () << endl; - break; - } - case parser_error::schema: - { - cerr << argv[1] << ":" << e.line () << ":" << e.column () - << ": error: " << e.schema_text () << endl; - break; - } - case parser_error::app: - { - cerr << argv[1] << ":" << e.line () << ":" << e.column () - << ": application error " << e.app_code () << 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 < 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<std::string> files = ... - - xml_schema::document_pimpl doc_p (people_p, "people"); - - for (size_t i = 0; i < files.size (); ++i) - { - try - { - people_p.pre (); - doc_p.parse (files[i]); - people_p.post_people (); - } - catch (const xml_schema::parser_exception&) - { - 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 — 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 Binary files differdeleted file mode 100644 index 8700758..0000000 --- a/documentation/cxx/serializer/guide/figure-1.png +++ /dev/null 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> </h1> - <h1> </h1> - <h1> </h1> - <h1> </h1> - <h1> </h1> - <h1> </h1> -</div> - <p>Copyright © 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="© 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 © 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 — 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"> -<hello> - - <greeting>Hello</greeting> - - <name>sun</name> - <name>moon</name> - <name>world</name> - -</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"> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:complexType name="hello"> - <xs:sequence> - <xs:element name="greeting" type="xs:string"/> - <xs:element name="name" type="xs:string" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:element name="hello" type="hello"/> - -</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&); - - void - name_serializer (xml_schema::string_sskel&); - - void - serializers (xml_schema::string_sskel& /* greeting */, - xml_schema::string_sskel& /* 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 <string> -#include <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<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 <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& e) - { - cerr << "error: " << e.text () << 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 -<hello> - <greeting>Hello</greeting> - <name>sun</name> - <name>moon</name> - <name>world</name> -</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"> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:simpleType name="gender"> - <xs:restriction base="xs:string"> - <xs:enumeration value="male"/> - <xs:enumeration value="female"/> - </xs:restriction> - </xs:simpleType> - - <xs:complexType name="person"> - <xs:sequence> - <xs:element name="first-name" type="xs:string"/> - <xs:element name="last-name" type="xs:string"/> - <xs:element name="gender" type="gender"/> - <xs:element name="age" type="xs:short"/> - </xs:sequence> - </xs:complexType> - - <xs:complexType name="people"> - <xs:sequence> - <xs:element name="person" type="person" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:element name="people" type="people"/> - -</xs:schema> - </pre> - - <p>A sample XML instance to go along with this schema could look like - this:</p> - - <pre class="xml"> -<people> - <person> - <first-name>John</first-name> - <last-name>Doe</last-name> - <gender>male</gender> - <age>32</age> - </person> - <person> - <first-name>Jane</first-name> - <last-name>Doe</last-name> - <gender>female</gender> - <age>28</age> - </person> -</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 <string> -#include <iostream> - -using namespace std; - -class gender_simpl: public gender_sskel -{ -public: - gender_simpl () - : gender_sskel (&base_impl_) - { - } - - virtual void - pre () - { - string g; - cerr << "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&) = 0; - }; - - class string_simpl: public string_sskel - { - public: - virtual void - pre (const std::string&); - - 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—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&); - - void - last_name_serializer (xml_schema::string_sskel&); - - void - gender_serializer (gender_sskel&); - - void - age_serializer (xml_schema::short_sskel&); - - void - serializers (xml_schema::string_sskel& /* first-name */, - xml_schema::string_sskel& /* last-name */, - gender_sskel& /* gender */, - xml_schema::short_sskel& /* 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 << "first name: "; - getline (cin, fn); - return fn; - } - - virtual std::string - last_name () - { - string ln; - cerr << "last name: "; - getline (cin, ln); - return ln; - } - - virtual short - age () - { - short a; - cerr << "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&); - - void - serializers (person_sskel& /* 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 << "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 << 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&, - const std::string& root_element_name); - - document_simpl (xml_schema::serializer_base&, - const std::string& root_element_namespace, - const std::string& root_element_name); - - typedef unsigned short flags; - static const flags pretty_print; - - void - serialize (std::ostream&, 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"> -<people> - <person> - <first-name>John</first-name> - <last-name>Doe</last-name> - <gender>male</gender> - <age>32</age> - </person> -</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><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><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><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></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></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></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 <string> -#include <vector> - -enum gender -{ - male, - female -}; - -class person -{ -public: - person (const std::string& first, - const std::string& last, - ::gender gender, - short age) - : first_ (first), last_ (last), - gender_ (gender), age_ (age) - { - } - - const std::string& - first () const - { - return first_; - } - - const std::string& - 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<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 <schema-namespace> [<cxx-namespace>] -{ - (include <file-name>;)* - ([type] <schema-type> <cxx-ret-type> [<cxx-arg-type>];)* -} - </pre> - - <p>Both <code><i><schema-namespace></i></code> and - <code><i><schema-type></i></code> are regex patterns while - <code><i><cxx-namespace></i></code>, - <code><i><cxx-ret-type></i></code>, and - <code><i><cxx-arg-type></i></code> are regex pattern - substitutions. All names can be optionally enclosed in - <code>" "</code>, for example, to include white-spaces.</p> - - <p><code><i><schema-namespace></i></code> determines XML - Schema namespace. Optional <code><i><cxx-namespace></i></code> - is prefixed to every C++ type name in this namespace declaration. - <code><i><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><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><cxx-arg-type></i></code> - is not specified, it defaults to <code><i><cxx-ret-type></i></code> - if <code><i><cxx-ret-type></i></code> ends with <code>*</code> or - <code>&</code> (that is, it is a pointer or a reference) and - <code>const <i><cxx-ret-type></i>&</code> - otherwise. - <code><i><file-name></i></code> is a file name either in the - <code>" "</code> or <code>< ></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>" "</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 <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&"; -people "const ::people&"; - </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 (&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& p) - { - p_ = &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& p) - { - p_ = &p; - i_ = p_->begin (); - } - - virtual bool - person_next () - { - return i_ != p_->end (); - } - - virtual const ::person& - 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 <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 -<people> - <person> - <first-name>John</first-name> - <last-name>Doe</last-name> - <gender>male</gender> - <age>32</age> - </person> - <person> - <first-name>Jane</first-name> - <last-name>Doe</last-name> - <gender>female</gender> - <age>28</age> - </person> -</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 -<name>_next (); - </pre> - - <p>Where <code><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> -<xs:complexType name="coordinates"> - <xs:sequence maxOccurs="unbounded"> - <xs:element name="lat" type="xs:float"/> - <xs:element name="lon" type="xs:float"/> - </xs:sequence> -</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 -<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> -<xs:complexType name="name"> - <xs:sequence minOccurs="0"> - <xs:element name="first" type="xs:string"/> - <xs:element name="initial" type="xs:string" minOccurs="0"/> - <xs:element name="last" type="xs:string"/> - </xs:sequence> - <xs:attribute name="lang" type="xs:language"/> -</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 -<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> -<xs:complexType name="names"> - <xs:sequence maxOccurs="unbounded"> - <xs:element name="first" type="xs:string"/> - <xs:element name="last" type="xs:string"/> - <xs:element name="pseudonym" type="xs:string" maxOccurs="3"/> - </xs:sequence> -</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> -<xs:complexType name="name"> - <xs:choice> - <xs:element name="full-name" type="xs:string"/> - <xs:sequence> - <xs:element name="first-name" type="xs:string"/> - <xs:element name="last-name" type="xs:string"/> - </xs:sequence> - </xs:choice> -</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> -<xs:complexType name="name"> - <xs:sequence> - <xs:element name="first" type="xs:string"/> - <xs:element name="last" type="xs:string"/> - <xs:any namespace="##other" processContents="skip" minOccurs="0"/> - </xs:sequence> -</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& ns, std::string& 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& ns, std::string& 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> -<xs:complexType name="name"> - <xs:sequence> - <xs:element name="first" type="xs:string"/> - <xs:element name="last" type="xs:string"/> - </xs:sequence> - <xs:anyAttribute namespace="##any" processContents="skip"/> -</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& ns, std::string& 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& ns, std::string& 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&, 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"> -<xs:complexType name="person"> - <xs:sequence> - <xs:element name="first-name" type="xs:string"/> - <xs:element name="last-name" type="xs:string"/> - <xs:element name="age" type="xs:short"/> - </xs:sequence> -</xs:complexType> - -<xs:complexType name="emplyee"> - <complexContent> - <extension base="person"> - <xs:sequence> - <xs:element name="position" type="xs:string"/> - <xs:element name="salary" type="xs:unsignedLong"/> - </xs:sequence> - </extension> - </complexContent> -</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 (&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 (&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<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<employee*> (person_)->position (); - } - - virtual unsigned int - salary () - { - return static_cast<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"> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - - <xs:complexType name="person"> - <xs:sequence> - <xs:element name="name" type="xs:string"/> - </xs:sequence> - </xs:complexType> - - <!-- substitution group root --> - <xs:element name="person" type="person"/> - - <xs:complexType name="superman"> - <xs:complexContent> - <xs:extension base="person"> - <xs:attribute name="can-fly" type="xs:boolean"/> - </xs:extension> - </xs:complexContent> - </xs:complexType> - - <xs:element name="superman" - type="superman" - substitutionGroup="person"/> - - <xs:complexType name="batman"> - <xs:complexContent> - <xs:extension base="superman"> - <xs:attribute name="wing-span" type="xs:unsignedInt"/> - </xs:extension> - </xs:complexContent> - </xs:complexType> - - <xs:complexType name="supermen"> - <xs:sequence> - <xs:element ref="person" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - - <xs:element name="supermen" type="supermen"/> - -</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"> -<supermen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - - <person> - <name>John Doe</name> - </person> - - <superman can-fly="false"> - <name>James "007" Bond</name> - </superman> - - <person can-fly="true" wing-span="10" xsi:type="batman"> - <name>Bruce Wayne</name> - </person> - -</supermen> - </pre> - - <p>The C++ object model for this vocabulary might look as follows:</p> - - <pre class="c++"> -#include <string> -#include <vector> - -enum type_id -{ - person_type, - superman_type, - batman_type -}; - -class person -{ -public: - virtual - ~person () {} - - person (const std::string& name) - : name_ (name) - { - } - - const std::string& - name () const - { - return name_; - } - - void - name (const std::string& n) - { - name_ = n; - } - - virtual type_id - type () const - { - return person_type; - } - -private: - std::string name_; -}; - -class superman: public person -{ -public: - superman (const std::string& 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& 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<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&"; -superman "const ::person&"; -batman "const ::person&"; -supermen "const ::supermen&"; - </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& p) - { - person_ = &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 (&base_impl_) - { - } - - virtual bool - can_fly () - { - return superman_ ().can_fly (); - } - - const superman& - superman_ () - { - return *static_cast<const superman*> (base_impl_.person_); - } - -private: - person_simpl base_impl_; -}; - -class batman_simpl: public batman_sskel -{ -public: - batman_simpl () - : batman_sskel (&base_impl_) - { - } - - virtual unsigned int - wing_span () - { - return batman_ ().wing_span (); - } - - const batman& - batman_ () - { - return static_cast<const batman&> (base_impl_.superman_ ()); - } - -private: - superman_simpl base_impl_; -}; - -class supermen_simpl: public supermen_sskel -{ -public: - virtual void - pre (const supermen& s) - { - supermen_ = &s; - i_ = s.begin (); - } - - virtual bool - person_next () - { - return i_ != supermen_->end (); - } - - virtual const ::person& - person () - { - const ::person& p = **i_++; - xml_schema::serializer_context& 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&); - - // Individual element serializers. - // - void - person_serializer (person_sskel&); - - void - person_serializer (xml_schema::serializer_map&); - - ... -}; - </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&); - - // This version of insert is a shortcut that uses the string - // returned by the serializer's _dynamic_type() function. - // - void - insert (serializer_base&); - - virtual serializer_base* - find (const void* type_id) const; - - virtual void - reset () const; - - private: - serializer_map_impl (const serializer_map_impl&); - - serializer_map_impl& - operator= (const serializer_map_impl&); - - ... - }; -} - </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>"<name> <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 <map> - -class person_serializer_map: public xml_schema::serializer_map -{ -public: - void - insert (person_sskel& 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] = &p; - } - - virtual xml_schema::serializer_base* - find (const char* x) const - { - const person* p = static_cast<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<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& - person () - { - const ::person& p = **i_++; - _context ().type_id (&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 << "substitution hashmap load is " << load << endl; - cerr << "time to increase XSDE_SERIALIZER_SMAP_BUCKETS" << endl; - } - - load = xml_schema::serializer_smap_bucket_elements (); - load /= xml_schema::serializer_smap_bucket_buckets (); - - if (load > 0.8) - { - cerr << "substitution inner hashmap load is " << load << endl; - cerr << "time to increase XSDE_SERIALIZER_SMAP_BUCKET_BUCKETS" << endl; - } - - load = xml_schema::serializer_imap_elements (); - load /= xml_schema::serializer_imap_buckets (); - - if (load > 0.8) - { - cerr << "inheritance hashmap load is " << load << endl; - cerr << "time to increase XSDE_SERIALIZER_IMAP_BUCKETS" << 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 <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 <stdio.h> -#include "people-sskel.hxx" - -const char* gender_strings[] = {"male", "female"}; - -class gender_simpl: public gender_sskel -{ -public: - gender_simpl () - : gender_sskel (&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& p) - { - person_ = &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& p) - { - i_ = 0; - people_ = &p; - } - - virtual bool - person_next () - { - return i_ < people_->size_; - } - - virtual const ::person& - 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&</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 char</code></td> - </tr> - <tr> - <td><code>unsignedByte</code></td> - <td><code>unsigned_byte_simpl</code></td> - <td><code>unsigned 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 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 int</code></td> - </tr> - - <!-- 64-bit --> - <tr> - <td><code>long</code></td> - <td><code>long_simpl</code></td> - <td><code>long 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 long long</code> or - <code>unsigned 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 long</code></td> - </tr> - <tr> - <td><code>positiveInteger</code></td> - <td><code>positive_integer_simpl</code></td> - <td><code>unsigned 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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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&</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& name); - qname (const std::string& prefix, const std::string& name); - - void - swap (qname&); - - const std::string& - prefix () const; - - std::string& - prefix (); - - void - prefix (const std::string&); - - const std::string& - name () const; - - std::string& - name (); - - void - name (const std::string&); - }; - - bool - operator== (const qname&, const qname&); - - bool - operator!= (const qname&, const qname&); -} - </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&); - - private: - qname (const qname&); - - qname& - operator= (const qname&); - - 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&, const qname&); - - bool - operator!= (const qname&, const qname&); -} -</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&); - - private: - qname (const qname&); - - qname& - operator= (const qname&); - - 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&, const qname&); - - bool - operator!= (const qname&, const qname&); -} - </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& reference; - typedef const std::string& 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&); - - private: - string_sequence (string_sequence&); - - string_sequence& - operator= (string_sequence&); - - public: - iterator - begin (); - - const_iterator - begin () const; - - iterator - end (); - - const_iterator - end () const; - - std::string& - front (); - - const std::string& - front () const; - - std::string& - back (); - - const std::string& - back () const; - - std::string& - operator[] (size_t); - - const std::string& - 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&); - - iterator - insert (iterator, const std::string&); - - void - reserve (size_t); - }; - - bool - operator== (const string_sequence&, const string_sequence&); - - bool - operator!= (const string_sequence&, const string_sequence&); -} - </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&); - - error - insert (iterator, const std::string&); - - error - insert (iterator, const std::string&, iterator& 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&); - - private: - string_sequence (string_sequence&); - - string_sequence& - operator= (string_sequence&); - - 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&, const string_sequence&); - - bool - operator!= (const string_sequence&, const string_sequence&); -} - </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& 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&); - - buffer& - operator= (const buffer&); - - public: - void - attach (void* data, size_t size, size_t capacity); - - void* - detach (); - - void - swap (buffer&); - - 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&, const buffer&); - - bool - operator!= (const buffer&, const buffer&); -} - </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 <= 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&); - - buffer& - operator= (const buffer&); - - public: - error - attach (void* data, size_t size, size_t capacity); - - void* - detach (); - - void - swap (buffer&); - - public: - size_t - capacity () const; - - error - capacity (size_t); - - error - capacity (size_t, bool& moved); - - public: - size_t - size () const; - - error - size (size_t); - - error - size (size_t, bool& moved); - - public: - const char* - data () const; - - char* - data (); - - const char* - begin () const; - - char* - begin (); - - const char* - end () const; - - char* - end (); - }; - - bool - operator== (const buffer&, const buffer&); - - bool - operator!= (const buffer&, const buffer&); -} - </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&, const time_zone&); - - bool - operator!= (const time_zone&, const time_zone&); -} - </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&</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&, const date&); - - bool - operator!= (const date&, const date&); -} - </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&</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&, const date_time&); - - bool - operator!= (const date_time&, const date_time&); -} - </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&</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&, const duration&); - - bool - operator!= (const duration&, const duration&); -} - </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&</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&, const gday&); - - bool - operator!= (const gday&, const gday&); -} - </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&</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&, const gmonth&); - - bool - operator!= (const gmonth&, const gmonth&); -} - </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&</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&, const gmonth_day&); - - bool - operator!= (const gmonth_day&, const gmonth_day&); -} - </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&</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&, const gyear&); - - bool - operator!= (const gyear&, const gyear&); -} - </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&</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&, const gyear_month&); - - bool - operator!= (const gyear_month&, const gyear_month&); -} - </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&</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&, const time&); - - bool - operator!= (const time&, const time&); -} - </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&, - const char* root_element_name); - - document_simpl (serializer_base&, - const char* root_element_namespace, - const char* root_element_name); - - document_simpl (serializer_base&, - const std::string& root_element_name); - - document_simpl (serializer_base&, - const std::string& root_element_namespace, - const std::string& 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& prefix, - const std::string& namespace_); - - void - add_default_prefix (const std::string& namespace_); - - void - add_schema (const std::string& namespace_, - const std::string& location); - - void - add_no_namespace_schema (const std::string& 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&, flags = 0); - - public: - // Serialize by calling writer::write() and writer::flush() to - // output XML. - // - void - serialize (writer&, 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& - _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"> -<ex:root xmlns:ex="http://www.example.com/example" ...> - ... -</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"> -<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" ...> - ... -</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& - operator<< (std::ostream&, const serializer_exception&); - - - typedef <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 <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<<</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& e) - { - cout << "error: " << e.text () << 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 <implementation-details> serializer_xml_error; - typedef <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 << "system error: " << e.sys_text () << endl; - break; - } - case serializer_error::xml: - { - cerr << "xml error: " << e.xml_text () << endl; - break; - } - case serializer_error::schema: - { - cerr << "schema error: " << e.schema_text () << endl; - break; - } - case serializer_error::app: - { - cerr << "application error: " << e.app_code () << 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 < 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 < 4; ++i) - { - try - { - people_s.pre (); - doc_s.serialize (cout); - people_s.post (); - } - catch (const xml_schema::serializer_exception&) - { - 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 — 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 <schema-namespace> [<cxx-namespace>] -{ - (include <file-name>;)* - ([type] <schema-type> <cxx-ret-type> [<cxx-arg-type>];)* -} - </pre> - - <p>Both <code><i><schema-namespace></i></code> and - <code><i><schema-type></i></code> are regex patterns while - <code><i><cxx-namespace></i></code>, - <code><i><cxx-ret-type></i></code>, and - <code><i><cxx-arg-type></i></code> are regex pattern - substitutions. All names can be optionally enclosed in - <code><b>" "</b></code>, for example, to include white-spaces.</p> - - <p><code><i><schema-namespace></i></code> determines XML - Schema namespace. Optional <code><i><cxx-namespace></i></code> - is prefixed to every C++ type name in this namespace declaration. - <code><i><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><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><cxx-arg-type></i></code> is not specified, it defaults - to <code><i><cxx-ret-type></i></code> if <code><i><cxx-ret-type></i></code> - ends with <code><b>*</b></code> or <code><b>&</b></code> (that is, - it is a pointer or a reference) and - <code><b>const</b> <i><cxx-ret-type></i><b>&</b></code> - otherwise. - <code><i><file-name></i></code> is a file name either in the - <code><b>" "</b></code> or <code><b>< ></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>" "</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 <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 <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>" "</b></code> or - <code><b>' '</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>" "</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>' '</b></code> instead. - Unfortunately, Windows shell does not remove <code><b>' '</b></code> - from arguments when they are passed to applications. As a result you - may have to use <code><b>' '</b></code> for POSIX and - <code><b>" "</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"> - ©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="© 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> |