When you perform a query against BDB XML, you receive a results set in the form of an XmlResults object. To examine the results, you iterate over this result set, retrieving each element of the set as an XmlValue object.
Once you have an individual result element, you can obtain the data encapsulated in the XmlValue object in a number of ways. For example, you can obtain the information as a string object using XmlValue::asString(). Alternatively, you could obtain the data as an XmlDocument object using XmlValue::asDocument().
It is also possible to use DOM-like navigation on the XmlValue object since that class offers navigational methods such as XmlValue::getFirstChild(), XmlValue::getNextSibling(), XmlValue::getAttributes(), and so forth. For details on these and other XmlValue attributes, see the BDB XML C++ API Reference documentation.
For example, the following code fragment performs a query and then loops over the result set, obtaining and displaying the document's name from an XmlDocument object before displaying the document itself.
#include "DbXml.hpp" ... using namespace DbXml; ... // Get a manager object. XmlManager myManager(); // Open a container XmlContainer myContainer = myManager.openContainer("exampleData.dbxml"); // Get a query context XmlQueryContext context = myManager.createQueryContext(); // Declare a namespace context.setNamespace("fruits", "http://groceryItem.dbxml/fruits"); // Declare the query string. Find all the product documents // in the fruits namespace. std::string myQuery = "collection('exampleData.dbxml')/fruits:product"; // Perform the query. XmlResult results = myManager.query(myQuery, context); // Show the size of the result set std::cout << "Found " << results.size() << " documents for query: '" << myQuery << "'" << std::endl; // Display the result set XmlValue value; while (results.next(value)) { XmlDocument theDoc = value.asDocument(); std::string docName = theDoc.getName(); std::string docString = value.asString(); std::cout << "Document " << docName << ":" << std::endl; std::cout << docString << std::endl; std::cout << "===============================\n" << std::endl; }
It is frequently useful to retrieve a document from BDB XML and then perform follow-on queries to retrieve individual values from the document itself. You do this by creating and executing a query, except that you pass the specific XmlValue object that you want to query to the XmlQueryExpression::execute() method. You must then iterate over a result set exactly as you would when retrieving information from a container.
For example, suppose you have an address book product that manages individual contacts using XML documents such as:
<contact> <familiarName>John</familiarName> <surname>Doe</surname> <phone work="555 555 5555" home="555 666 777" /> <address> <street>1122 Somewhere Lane</street> <city>Nowhere</city> <state>Minnesota</state> <zipcode>11111</zipcode> </address> </contact>
Then you could retrieve individual documents and pull data off of them like this:
#include "DbXml.hpp" ... using namespace DbXml; ... // Get a manager object. XmlManager myManager(); // Open a container XmlContainer myContainer = myManager.openContainer("exampleData.dbxml"); // Declare the query string. Retrieves all the documents // for people with the last name 'Doe'. std::string myQuery = "collection('exampleData.dbxml')/contact"; // Query to get the familiar name from the // document. std::string fn = "distinct-values(/contact/familiarName)"; // Query to get the surname from the // document. std::string sn = "distinct-values(/contact/surname)"; // Work phone number std::string wrkPhone = "distinct-values(/contact/phone/@work)"; // Get the context for the XmlManager query XmlQueryContext managerContext = myManager.createQueryContext(); // Get a context for the document queries XmlQueryContext documentContext = myManager.createQueryContext(); // documentContext can be DeadValue documentContext.setReturnType(XmlQueryContext::DeadValues); // Prepare the XmlManager query XmlQueryExpression managerQuery = myManager.prepare(myQuery, managerContext); // Prepare the individual document queries XmlQueryExpression fnExpr = myManager.prepare(fn, documentContext); XmlQueryExpression snExpr = myManager.prepare(sn, documentContext); XmlQueryExpression wrkPhoneExpr = myManager.prepare(wrkPhone, documentContext); // Perform the query. XmlResults results = managerQuery.execute(managerContext, 0); // Display the result set XmlValue value; while (results.next(value)) { // Get the individual values XmlResults fnResults = fnExpr.execute(value, documentContext); XmlResults snResults = snExpr.execute(value, documentContext); XmlResults phoneResults = wrkPhoneExpr.execute(value, documentContext); std::string fnString; XmlValue fnValue; if (fnResults.size() > 0) { fnResults.next(fnValue); fnString = fnValue.asString(); } else { continue; } std::string snString; XmlValue snValue; if (snResults.size() > 0) { snResults.next(snValue); snString = snValue.asString(); } else { continue; } std::string phoneString; XmlValue phoneValue; if (phoneResults.size() > 0) { phoneResults.next(phoneValue); phoneString = phoneValue.asString(); } else { continue; } std::cout << fnString << " " << snString << ": " << phoneString << std::endl; }
When you retrieve a document from BDB XML, there are two ways to examine the metadata associated with that document. The first is to use XmlDocument::getMetaData(). Use this form if you want to examine the value for a specific metadata value.
The second way to examine metadata is to obtain an XmlMetaDataIterator object using XmlDocument::getMetaDataIterator(). You can use this mechanism to loop over and display every piece of metadata associated with the document.
For example:
#include "DbXml.hpp" ... using namespace DbXml; ... // Get a manager object. XmlManager myManager(); // Open a container XmlContainer myContainer = myManager.openContainer("exampleData.dbxml"); // Get a query context XmlQueryContext context = myManager.createQueryContext(); // Declare a namespace context.setNamespace("fruits", "http://groceryItem.dbxml/fruits"); // Declare the query string. Find all the product documents // in the fruits namespace. std::string myQuery = "collection('exampleData.dbxml')/fruits:product"; // Perform the query. XmlResult results = myManager.query(myQuery, context); // Display the result set XmlValue value; while (results.next(value)) { XmlDocument theDoc = value.asDocument(); // Display all of the metadata set for this document XmlMetaDataIterator mdi = theDoc.getMetaDataIterator(); std::string returnedURI; std::string returnedName; XmlValue returnedValue; std::cout << "For document '" << theDoc.getName() << "' found metadata:" << std::endl; while (mdi.next(returnedURI, returnedName, returnedValue)) { std::cout << "\tURI: " << returnedURI << ", attribute name: " << returnedName << ", value: " << returnedValue << std::endl; } // Display a single metadata value: std::string URI = "http://dbxmlExamples/timestamp"; std::string attrName = "timeStamp"; XmlValue newRetValue; bool gotResult = theDoc.getMetaData(URI, attrName, newRetValue); if (gotResult) { std::cout << "For URI: " << URI << ", and attribute " << attrName << ", found: " << newRetValue << std::endl; } std::cout << "===============================\n" << std::endl; }