# XML-Formatted Bakery Documents

## Contents

- Introduction
- Create the Document class

## Introduction

> 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.

## Create the Document class

> 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 <something>
> >     };

> 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.