The Document/View With Bakery page explains how to derive a Document class for your application. But Bakery::Document doesn't help you to organise or parse the data in the file. And f you achieve that by using a custom data format then other applications will not be able to easily use the same document. To solve this problem, the Bakery::Document_XML class helps you to use an XML format to store your data. This has the following advantages:
- You don't need to write complex document-parsing-and-building code - just use the XML parser's API. This means less code and more readable code.
- Instead of checking the document's structure with complicated code, you can validate it with a DTD.
- Other applications can work with your document.
- The file is human-readable, so you can investigate problems in the file.
Derive a Document class from Bakery::Document_XML. You don't need to override load_after() and save_after(), because Document_XML can do that for XML documents in general.
e.g.
class DocExample : public Bakery::Document_XML { public: DocExample(); virtual ~DocExample(); void set_something(const std::string& strSomething); std::string get_something(); protected: xmlpp::Node* get_node_something(); //Gets}; As in the other examples, you should specify the file extension in the constructor. But you should also specify the name of the XML file's DTD, and the name of the top-level XML node. These will be used to create new empty Documents.
DocExample::DocExample() { set_file_extension("bakery_example_xml"); set_DTD_Name("example_xml_doc.dtd"); set_DTD_RootNodeName("example_xml_doc"); }As in the other examples, when you implement methods like set_something(), which changes data in your document, you should call Document::set_modified(true).
In this example there is also a get_node_something() convenience method, just to reduce code duplication. Notice that we use the libxml++ Node class from the xmlpp namespace.
void DocExample::set_something(const std::string& strSomething) { try { set_node_attribute_value(get_node_something(), "someval", strSomething); set_modified(); } catch(const std::exception& ex) { //HandleError(ex); } } std::string DocExample::get_something() { std::string strValue; try { strValue = get_node_attribute_value(get_node_something(), "someval"); } catch(const std::exception& ex) { //HandleError(ex); } return strValue; } xmlpp::Node* DocExample::get_node_something() { try { xmlpp::Node* nodeRoot = get_node_document(); return get_node_child_named_with_add(nodeRoot, "something"); } catch(const std::exception& ex) { //HandleError(ex); return 0; } }You just need to use the libxml++ xmlpp::DomParser API, along with some convenience methods in Bakery::Document_XML, to navigate, read, and build your document. Bakery::Document_XML will take care of actually reading the XML into memory and writing it back to disk at the appropriate time.
Copyright © 2001, Murray Cumming. Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved.