diff options
Diffstat (limited to 'examples/cxx/hybrid/evolution/ignore')
-rw-r--r-- | examples/cxx/hybrid/evolution/ignore/README | 61 | ||||
-rw-r--r-- | examples/cxx/hybrid/evolution/ignore/driver.cxx | 131 | ||||
-rw-r--r-- | examples/cxx/hybrid/evolution/ignore/makefile | 103 | ||||
-rw-r--r-- | examples/cxx/hybrid/evolution/ignore/transform-v2.xsd | 93 | ||||
-rw-r--r-- | examples/cxx/hybrid/evolution/ignore/transform.xml | 32 | ||||
-rw-r--r-- | examples/cxx/hybrid/evolution/ignore/transform.xsd | 69 |
6 files changed, 489 insertions, 0 deletions
diff --git a/examples/cxx/hybrid/evolution/ignore/README b/examples/cxx/hybrid/evolution/ignore/README new file mode 100644 index 0000000..fb7272d --- /dev/null +++ b/examples/cxx/hybrid/evolution/ignore/README @@ -0,0 +1,61 @@ +This example shows how to handle schema evolution using substitution groups. +The general idea is as follows: the initial version of the schema defines +extension points using the XML Schema substitution group mechanism. The +subsequent versions of the schema add new elements to the substitution +groups. The goal here is for applications that were built using earlier +versions of the schema to be able to handle documents corresponding to the +newer versions without validation errors or any other failures. This example +shows how to ignore such new elements. The 'passthrough' example shows how +to pass the unknown content through parsing and serialization so that the +output XML contains all the unknown elements. + +This example uses XML Schema polymorphism in the form of substitution groups. +If you are not familiar with how to work with polymorphic object models, +refer to the C++/Hybrid Mapping Getting Started Guide as well as the +'polymorphism' example in the examples/cxx/hybrid/ directory. + +The example consists of the following files: + +transform.xsd + The initial version of the schema that describes simple transformations, + such as move and rotate. The schema makes it possible to add new + transformations in subsequent versions of the schema. Our example is built + using this schema. + +transform-v2.xsd + The second version of the schema which adds the scale transformation. This + schema is provided as an example. + +transform.xml + Sample XML document corresponding to the second version of the schema. In + particular, it contains the scale transformation which is unknown in + transform.xsd. + +transform.hxx +transform.cxx + +transform-pskel.hxx +transform-pskel.cxx + +transform-pimpl.hxx +transform-pimpl.cxx + Object model (the first pair of files), parser skeletons (the second pair) + and parser implementations (the third pair). These files are generated by + the XSD/e compiler from transform.xsd. The --generate-parser and + --generate-aggregate options were used to request the generation of the + parsing code. The --generate-polymorphic option was used to request the + generation of the polymorphism-aware code. + +driver.cxx + Driver for the example. It first sets the substitution map callback that + is used to tell the parser which elements should be ignored. The driver + then calls the parser that constructs the object model from the input XML + file. Finally, it prints the content of the object model to STDERR. + +To run the example on the sample XML instance document simply execute: + +$ ./driver transform.xml + +The example reads from STDIN if input file is not specified: + +$ ./driver <transform.xml diff --git a/examples/cxx/hybrid/evolution/ignore/driver.cxx b/examples/cxx/hybrid/evolution/ignore/driver.cxx new file mode 100644 index 0000000..6c1c45f --- /dev/null +++ b/examples/cxx/hybrid/evolution/ignore/driver.cxx @@ -0,0 +1,131 @@ +// file : examples/cxx/hybrid/evolution/ignore/driver.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : not copyrighted - public domain + +#include <memory> // std::auto_ptr +#include <string> +#include <iostream> + +#include "transform.hxx" +#include "transform-pimpl.hxx" + +using namespace std; +using namespace transform; + +// Parser substitution map callback. This callback is called when the +// parser needs to check whether an element belongs to a substitution +// group. We use this callback to return a special ignored type marker +// for unknown transformations. +// +static bool +parser_callback (const xml_schema::ro_string& root_ns, + const xml_schema::ro_string& root_name, + const xml_schema::ro_string& /*member_ns*/, + const xml_schema::ro_string& member_name, + const char*& type) +{ + // Check that the root of the substitution group is 'transformation'. + // + if (root_name == "transformation" && + root_ns == "http://www.codesynthesis.com/transform") + { + // Check that the element's name has the '-transformation' suffix. This + // is the convention we use in our schema to minimize the chance of + // treating any unknown elements as a transformation. + // + // + string s ("-transformation"); + string n (member_name); + + if (n.size () > s.size () && + string (n, n.size () - s.size (), s.size ()) == s) + { + // Set type to the special ignore marker. + // + type = "*"; + return true; + } + } + + return false; +} + +int +main (int argc, char* argv[]) +{ + const char* input; + + if (argc < 2) + { + input = "STDIN"; + cerr << "XML file not specified, reading from STDIN" << endl; + } + else + input = argv[1]; + + try + { + // Set the substitution map callback. + // + xml_schema::parser_smap_callback (&parser_callback); + + // Parse. + // + transformations_paggr transformations_p; + + // The last argument to the document's constructor indicates that we + // are parsing polymorphic XML documents. + // + xml_schema::document_pimpl doc_p ( + transformations_p.root_parser (), + transformations_p.root_namespace (), + transformations_p.root_name (), + true); + + transformations_p.pre (); + + if (argc < 2) + doc_p.parse (cin); + else + doc_p.parse (argv[1]); + + auto_ptr<transformations_type> tf (transformations_p.post ()); + + // Print what we've got. + // + for (transformations_type::transformation_iterator i = + tf->transformation ().begin (); + i != tf->transformation ().end (); + ++i) + { + transformation_type& t = *i; + + if (move_type* m = dynamic_cast<move_type*> (&t)) + { + cout << m->name () << ": " << m->description () << endl + << "\tx: " << m->x () << endl + << "\ty: " << m->y () << endl + << endl; + } + else if (rotate_type* r = dynamic_cast<rotate_type*> (&t)) + { + cout << r->name () << ": " << r->description () << endl + << "\tangle: " << r->angle () << endl + << endl; + } + } + } + catch (const xml_schema::parser_exception& e) + { + cerr << input << ":" << e.line () << ":" << e.column () << ": " + << e.text () << endl; + return 1; + } + catch (const std::ios_base::failure&) + { + cerr << input << ": unable to open or read/write failure" << endl; + return 1; + } + + return 0; +} diff --git a/examples/cxx/hybrid/evolution/ignore/makefile b/examples/cxx/hybrid/evolution/ignore/makefile new file mode 100644 index 0000000..cde32fb --- /dev/null +++ b/examples/cxx/hybrid/evolution/ignore/makefile @@ -0,0 +1,103 @@ +# file : examples/cxx/hybrid/evolution/ignore/makefile +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +# license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../../build/bootstrap.make + +xsd := transform.xsd +cxx := driver.cxx + +obj := $(addprefix $(out_base)/,\ +$(cxx:.cxx=.o) \ +$(xsd:.xsd=.o) \ +$(xsd:.xsd=-pskel.o) \ +$(xsd:.xsd=-pimpl.o)) + +dep := $(obj:.o=.o.d) + +xsde.l := $(out_root)/libxsde/xsde/xsde.l +xsde.l.cpp-options := $(out_root)/libxsde/xsde/xsde.l.cpp-options + +driver := $(out_base)/driver +dist := $(out_base)/.dist +dist-win := $(out_base)/.dist-win +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(obj) $(xsde.l) + +$(obj) $(dep): $(xsde.l.cpp-options) + +genf := $(xsd:.xsd=.hxx) $(xsd:.xsd=.cxx) \ + $(xsd:.xsd=-pskel.hxx) $(xsd:.xsd=-pskel.cxx) \ + $(xsd:.xsd=-pimpl.hxx) $(xsd:.xsd=-pimpl.cxx) + +gen := $(addprefix $(out_base)/,$(genf)) + +$(gen): $(out_root)/xsde/xsde +$(gen): xsde := $(out_root)/xsde/xsde +$(gen): xsde_options += --generate-parser --generate-aggregate \ +--root-element transformations --generate-polymorphic + +$(call include-dep,$(dep)) + +# Convenience alias for default target. +# +$(out_base)/: $(driver) + + +# Dist. +# +dist-common := $(out_base)/.dist-common +$(dist) $(dist-win) $(dist-common): path := $(subst $(src_root)/,,$(src_base)) + +$(dist-common): + $(call install-data,$(src_base)/driver.cxx,$(dist_prefix)/$(path)/driver.cxx) + $(call install-data,$(src_base)/transform.xsd,$(dist_prefix)/$(path)/transform.xsd) + $(call install-data,$(src_base)/transform-v2.xsd,$(dist_prefix)/$(path)/transform-v2.xsd) + $(call install-data,$(src_base)/transform.xml,$(dist_prefix)/$(path)/transform.xml) + +$(dist): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README) + +$(dist-win): $(dist-common) + $(call install-data,$(src_base)/README,$(dist_prefix)/$(path)/README.txt) + $(call message,,unix2dos $(dist_prefix)/$(path)/README.txt) + + +# Clean. +# +$(clean): $(driver).o.clean \ + $(addsuffix .cxx.clean,$(obj)) \ + $(addsuffix .cxx.clean,$(dep)) \ + $(addprefix $(out_base)/,$(xsd:.xsd=.cxx.xsd.clean)) + + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(gen): | $(out_base)/.gitignore +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver $(genf) +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) +$(call include,$(bld_root)/install.make) +$(call include,$(scf_root)/xsde/hybrid/xsd-cxx.make) + + +# Dependencies. +# +$(call import,$(src_root)/xsde/makefile) +$(call import,$(src_root)/libxsde/xsde/makefile) diff --git a/examples/cxx/hybrid/evolution/ignore/transform-v2.xsd b/examples/cxx/hybrid/evolution/ignore/transform-v2.xsd new file mode 100644 index 0000000..d9ceaec --- /dev/null +++ b/examples/cxx/hybrid/evolution/ignore/transform-v2.xsd @@ -0,0 +1,93 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/hybrid/evolution/ignore/transform-v2.xsd +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:tf="http://www.codesynthesis.com/transform" + targetNamespace="http://www.codesynthesis.com/transform" + elementFormDefault="qualified"> + + <xsd:complexType name="transformation_type" abstract="true"> + <xsd:sequence> + <xsd:element name="description" type="xsd:string"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required"/> + </xsd:complexType> + + <xsd:element name="transformation" type="tf:transformation_type"/> + + <!-- Document root. --> + + <xsd:complexType name="transformations_type"> + <xsd:sequence> + <xsd:element ref="tf:transformation" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + + <xsd:element name="transformations" type="tf:transformations_type"/> + + <!-- Move. --> + + <xsd:complexType name="move_type"> + <xsd:complexContent> + <xsd:extension base="tf:transformation_type"> + <xsd:sequence> + <xsd:element name="x" type="xsd:float"/> + <xsd:element name="y" type="xsd:float"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + + <xsd:element name="move-transformation" + type="tf:move_type" + substitutionGroup="tf:transformation"/> + + <!-- Rotate. --> + + <xsd:complexType name="rotate_type"> + <xsd:complexContent> + <xsd:extension base="tf:transformation_type"> + <xsd:sequence> + <xsd:element name="angle" type="xsd:float"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + + <xsd:element name="rotate-transformation" + type="tf:rotate_type" + substitutionGroup="tf:transformation"/> + + <!-- Scale. --> + + <xsd:complexType name="ratio_type"> + <xsd:sequence> + <xsd:element name="x" type="xsd:float"/> + <xsd:element name="y" type="xsd:float"/> + </xsd:sequence> + <xsd:attribute name="unit" type="xsd:string"/> + </xsd:complexType> + + <xsd:complexType name="scale_type"> + <xsd:complexContent> + <xsd:extension base="tf:transformation_type"> + <xsd:sequence> + <xsd:element name="ratios" type="tf:ratio_type"/> + </xsd:sequence> + <xsd:attribute name="proportional" type="xsd:boolean"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + + <xsd:element name="scale-transformation" + type="tf:scale_type" + substitutionGroup="tf:transformation"/> + +</xsd:schema> diff --git a/examples/cxx/hybrid/evolution/ignore/transform.xml b/examples/cxx/hybrid/evolution/ignore/transform.xml new file mode 100644 index 0000000..d7e8cef --- /dev/null +++ b/examples/cxx/hybrid/evolution/ignore/transform.xml @@ -0,0 +1,32 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/hybrid/evolution/ignore/transform.xml +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<transformations xmlns="http://www.codesynthesis.com/transform"> + + <move-transformation name="move"> + <description>Move an object.</description> + <x>1.1</x> + <y>2.1</y> + </move-transformation> + + <rotate-transformation name="rotate"> + <description>Rotate an object.</description> + <angle>90</angle> + </rotate-transformation> + + <scale-transformation name="scale" proportional="true"> + <description>Scale an object.</description> + <ratios unit="percent"> + <x>210</x> + <y>210</y> + </ratios> + </scale-transformation> + +</transformations> diff --git a/examples/cxx/hybrid/evolution/ignore/transform.xsd b/examples/cxx/hybrid/evolution/ignore/transform.xsd new file mode 100644 index 0000000..59cf48f --- /dev/null +++ b/examples/cxx/hybrid/evolution/ignore/transform.xsd @@ -0,0 +1,69 @@ +<?xml version="1.0"?> + +<!-- + +file : examples/cxx/hybrid/evolution/ignore/transform.xsd +author : Boris Kolpackov <boris@codesynthesis.com> +copyright : not copyrighted - public domain + +--> + +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:tf="http://www.codesynthesis.com/transform" + targetNamespace="http://www.codesynthesis.com/transform" + elementFormDefault="qualified"> + + <xsd:complexType name="transformation_type" abstract="true"> + <xsd:sequence> + <xsd:element name="description" type="xsd:string"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required"/> + </xsd:complexType> + + <xsd:element name="transformation" type="tf:transformation_type"/> + + <!-- Document root. --> + + <xsd:complexType name="transformations_type"> + <xsd:sequence> + <xsd:element ref="tf:transformation" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + + <xsd:element name="transformations" type="tf:transformations_type"/> + + <!-- Move. --> + + <xsd:complexType name="move_type"> + <xsd:complexContent> + <xsd:extension base="tf:transformation_type"> + <xsd:sequence> + <xsd:element name="x" type="xsd:float"/> + <xsd:element name="y" type="xsd:float"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + + <xsd:element name="move-transformation" + type="tf:move_type" + substitutionGroup="tf:transformation"/> + + <!-- Rotate. --> + + <xsd:complexType name="rotate_type"> + <xsd:complexContent> + <xsd:extension base="tf:transformation_type"> + <xsd:sequence> + <xsd:element name="angle" type="xsd:float"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + + <xsd:element name="rotate-transformation" + type="tf:rotate_type" + substitutionGroup="tf:transformation"/> + + +</xsd:schema> |