aboutsummaryrefslogtreecommitdiff
path: root/examples/cxx/hybrid/evolution/ignore
diff options
context:
space:
mode:
Diffstat (limited to 'examples/cxx/hybrid/evolution/ignore')
-rw-r--r--examples/cxx/hybrid/evolution/ignore/README61
-rw-r--r--examples/cxx/hybrid/evolution/ignore/driver.cxx131
-rw-r--r--examples/cxx/hybrid/evolution/ignore/makefile103
-rw-r--r--examples/cxx/hybrid/evolution/ignore/transform-v2.xsd93
-rw-r--r--examples/cxx/hybrid/evolution/ignore/transform.xml32
-rw-r--r--examples/cxx/hybrid/evolution/ignore/transform.xsd69
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>