Adding Documents

To add a document to a container, you use XmlContainer::putDocument(). When you use this method, you must:

  1. Somehow obtain the document that you want to put into the container. To do this, you can create an input stream to the content or load the XML document into a string object. Alternatively, you can load the document into an XmlDocument object and then provide the XmlDocument object to XmlContainer::putDocument(). When you do this, you can provide the document to the XmlDocument object using an input stream or string, or you can construct the document using an event writer.

  2. Provide a name for the document. This name must be unique or BDB XML will throw XmlException::UNIQUE_ERROR.

    If you are using an XmlDocument object to add the document, use XmlDocument::setName() to set the document's name. Otherwise, you can set the name directly on the call to XmlContainer::putDocument().

    Note that if you do not want to explicitly set a name for the document, you can set a flag, DBXML_GEN_NAME, on the call to XmlContainer::putDocument(). This causes BDB XML to generate a unique name for you. The name that it generates is a concatenation of a unique value, an underscore, and the value that you provide for the document's name, if any. For example:

    myDocName_a

    where myDocName is the name that you set for the document and a is the unique value generated by BDB XML.

    If you do not set a name for the document, but you do specify that a unique name is to be generated, then dbxml is used as the name's prefix.

    dbxml_b

    If you do not set a name for the document and if you do not use DBXML_GEN_NAME, then BDB XML throws XmlException::UNIQUE_ERROR.

  3. Create an XmlUpdateContext object. This object encapsulates the context within which the container is updated. Reusing the same object for a series of puts against the same container can improve your container's write performance.

Note that the content that you supply to XmlContainer::putDocument() is read and validated. By default, this includes any schema or DTDs that the document might reference. Since this can cause you some performance issues, you can cause BDB XML to only examine the document body itself by passng the DBXML_WELL_FORMED_ONLY flag to XmlContainer::putDocument(). However, using this flag cause parsing errors if the document references information that might have come from a schema or DTD.

Further, note that while your documents are stored in the container with their shared text entities (if any) as-is, the underlying XML parser does attempt to expand them for indexing purposes. Therefore, you must make sure that any entities contained in your documents are resolvable at load time.

For example, to add a document that is held in a string:

#include "DbXml.hpp"
...

using namespace DbXml;
int main(void)
{
    // The document
    std::string docString = "<a_node><b_node>Some text</b_node></a_node>";

    // The document's name.
    std::string docName = "testDoc1";

    // Get a manager object.
    XmlManager myManager;   // The manager is closed when 
                            // it goes out of scope.

    // Load the document in its entirety. The document's formatting is 
    // preserved.
    myManager.setDefaultContainerType(XmlContainer::WholedocContainer);

    // Open the container. The container is closed when it goes
    // out of scope.
    XmlContainer myContainer = 
        myManager.openContainer("container.bdbxml");

    // Need an update context for the put.
    XmlUpdateContext theContext = myManager.createUpdateContext();

    // Put the document
    try {
        myContainer.putDocument(docName,      // The document's name
                                 docString,   // The actual document, 
                                              // in a string.
                                 theContext,  // The update context 
                                              // (required).
                                 0);          // Put flags.
    } catch (XmlException &e) {
        // Error handling goes here. You may want to check
        // for XmlException::UNIQUE_ERROR, which is raised
        // if a document with that name already exists in
        // the container. If this exception is thrown, 
        // try the put again with a different name.
    }

    return(0);
} 

To load the document from an input stream, the code is identical except that you use the appropriate method on XmlManager to obtain the stream. For example, to load an XmlDocument directly from a file on disk:

#include "DbXml.hpp"
...

using namespace DbXml;
int main(void)
{
    // The document
    std::string fileName = "/export/testdoc1.xml";

    // The document's name.
    std::string docName = "testDoc1";

    // Get a manager object.
    XmlManager myManager;   // The manager is closed when
                            // it goes out of scope.

    // Load the document in its entirety. The document's formatting is 
    // preserved.
    myManager.setDefaultContainerType(XmlContainer::WholedocContainer);

    // Open the container. The container is closed when it goes
    // out of scope.
    XmlContainer myContainer = 
        myManager.openContainer("container.bdbxml");

    // Need an update context for the put.
    XmlUpdateContext theContext = myManager.createUpdateContext();

    try {
        // Get the input stream.
        XmlInputStream *theStream = 
            myManager.createLocalFileInputStream(fileName);

        // Put the document
        myContainer.putDocument(docName,      // The document's name
                                 theStream,   // The actual document. 
                                 theContext,  // The update context 
                                              // (required).
                                 0);          // Put flags.
    } catch (XmlException &e) {
        // Error handling goes here. You may want to check
        // for XmlException::UNIQUE_ERROR, which is raised
        // if a document with that name already exists in
        // the container. If this exception is thrown, 
        // try the put again with a different name.
    }

    return(0);
}