Introduction
This guide shows how to integrate the C++/Tree mapping generated by CodeSynthesis XSD with Berkeley DB XML. Berkeley DB XML is an embedded XML database which allows efficient storage and query of XML instance documents. CodeSynthesis XSD is a W3C XML Schema to C++ data binding compiler. The C++/Tree mapping allows you to manipulate the data stored in XML using objects that semantically correspond to your application domain rather than dealing with direct representations of XML. For an introduction to the Berkeley DB XML refer to the Berkeley DB XML Getting Started Guide. For an introduction to the C++/Tree mapping refer to the C++/Tree Mapping Getting Started Guide.
This guide describes the following four operations:
- Create a new document in DB from an object model
- Create an object model from a document in DB
- Create an object model from a document fragment in DB
- Update a document fragment in DB from an object model
Our examples will be based on simple XML for book library. The XML
Schema definition for the library is in
library.xsd and is compiled by XSD
to obtain library.hxx
and library.cxx
.
All C++ code fragments that are presented in this guide are available
as a single program in driver.cxx.
The complete example is available in the
examples/cxx/tree/dbxml
directory of the XSD distribution.
Note that due to the incomplete DOM API implementation provided by DB
XML (as of version 2.3.10), the generated code and your application
should be compiled with the DBXML_DOM
macro defined in
order to avoid using unsupported parts of the API.
A sample XML document for the library schema is presented below:
<lib:catalog xmlns:lib="http://www.codesynthesis.com/library"> <book available="true" id="ES"> <isbn>20530902</isbn> <title>The Elements of Style</title> <genre>reference</genre> <author> <name>William Strunk, Jr.</name> <born>1869-07-01</born> <died>1946-09-26</died> </author> <author> <name>E.B. White</name> <born>1899-07-11</born> <died>1985-10-01</died> </author> </book> </lib:catalog>
Create Document from Object Model
In this step, we will programmatically create a book catalog
with one book, save it into an XmlDocument
object
using one of the serialization functions generated by XSD (
catalog_
in our case), and store the
XmlDocument
object as a new document in the
DB container:
XmlManager manager; XmlContainer container (manager.createContainer ("new.bdbxml")); XmlUpdateContext update_context (manager.createUpdateContext ()); XmlQueryContext context (manager.createQueryContext ()); context.setNamespace ("lib", "http://www.codesynthesis.com/library"); // Create a new catalog with one book. // catalog c; book b (20530902, // ISBN title ("The Elements of Style"), // Title genre::reference, // Genre "ES"); // ID author strunk ("William Strunk, Jr.", date (1869, 7, 1)); strunk.died (date (1946, 9, 26)); b.author ().push_back (strunk); c.book ().push_back (b); // Create a new XML document. // XmlDocument doc (manager.createDocument ()); doc.setName ("new.xml"); // Obtain its DOM representation and add the root element. // xercesc::DOMDocument& dom_doc (*doc.getContentAsDOM ()); dom_doc.appendChild ( dom_doc.createElementNS ( xml::string ("http://www.codesynthesis.com/library").c_str (), xml::string ("lib:catalog").c_str ())); // Serialize the object model to the XML document. Also avoid // re-initializing the Xerces-C++ runtime since XmlManager has // it initialized. // catalog_ (dom_doc, c, xml_schema::flags::dont_initialize); // Place the document into the container. // container.putDocument (doc, update_context);
If we now resolve the new.xml
in the container and
print its content, we will get:
<lib:catalog xmlns:lib="http://www.codesynthesis.com/library"> <book available="true" id="ES"> <isbn>20530902</isbn> <title>The Elements of Style</title> <genre>reference</genre> <author> <name>William Strunk, Jr.</name> <born>1869-07-01</born> <died>1946-09-26</died> </author> </book> </lib:catalog>
Create Object Model from Document
Creating an object model from a document is a matter
of obtaining XmlDocument
object and passing its DOM
representation to one of the parsing functions generated by XSD
(catalog_
in our case):
// Resolve the document in the container. // XmlDocument doc (container.getDocument ("new.xml")); // Create the object model from the document's DOM. Also avoid // re-initializing the Xerces-C++ runtime since XmlManager has // it initialized. // auto_ptr<catalog> c (catalog_ (*doc.getContentAsDOM (), xml_schema::flags::dont_initialize)); cerr << *c << endl;
This code fragment prints:
book: isbn: 20530902 title: The Elements of Style genre: reference author: name: William Strunk, Jr. born: 1869-07-01 died: 1946-09-26 available: 1 id: ES
Create Object Model from Document Fragment
The following code fragment looks up the book with id "ES"
using XQuery. It then creates a book
object from the
resulting XmlValue
:
string query ("collection('new.bdbxml')/lib:catalog/book[@id='ES']"); // Find "The Elements of Style". // XmlValue v; XmlResults results (manager.query (query, context)); if (results.next (v)) { // Create an object model from the document fragment. // auto_ptr<book> b ( new book ( *static_cast<xercesc::DOMElement*> (v.asNode ()))); cerr << *b << endl; }
This code fragment prints:
isbn: 20530902 title: The Elements of Style genre: reference author: name: William Strunk, Jr. born: 1869-07-01 died: 1946-09-26 available: 1 id: ES
Note that we had to perform a static_cast
from
xercesc::DOMNode
returned by the XmlValue::asNode
member function to
xercesc::DOMElement
. This is safe since we know
that in our schema books are represented as XML elements.
Update Document Fragment from Object Model
Analogous to the create case, the following code fragment looks
up the book with id "ES"
using XQuery. It then creates
a book
object from the resulting XmlValue
,
adds another author, changes the availability status, and saves
the changes back to the XmlValue
object:
string query ("collection('new.bdbxml')/lib:catalog/book[@id='ES']"); // Find "The Elements of Style". // XmlValue v; XmlResults results (manager.query (query, context)); if (results.next (v)) { // Create an object model from the document fragment. // auto_ptr<book> b ( new book ( *static_cast<xercesc::DOMElement*> (v.asNode ()))); // Add another author, change the availability status. // author white ("E.B. White", date (1899, 7, 11)); white.died (date (1985, 10, 1)); b->author ().push_back (white); b->available (false); // Update the document fragment from the object model. // *static_cast<xercesc::DOMElement*> (v.asNode ()) << *b; // Update the document in the container. // XmlDocument doc (v.asDocument ()); container.updateDocument (doc, update_context); }
If we now resolve the new.xml
in the container and
print its content, we will get:
<lib:catalog xmlns:lib="http://www.codesynthesis.com/library"> <book available="false" id="ES"> <isbn>20530902</isbn> <title>The Elements of Style</title> <genre>reference</genre> <author> <name>William Strunk, Jr.</name> <born>1869-07-01</born> <died>1946-09-26</died> </author> <author> <name>E.B. White</name> <born>1899-07-11</born> <died>1985-10-01</died> </author> </book> </lib:catalog>