The Example Code
As in the previous chapter, examine the code to gain a better understanding of how HydraExpress manipulates the XML.
C++ Namespaces
If the schema has a target namespace and a prefix associated with the target namespace URI, then a C++ namespace that matches the prefix is used. Note that, in the provided po1_main.cpp sample application, HydraExpress includes the C++ types that HydraExpress created from the po namespace:
using namespace po;
For more information about C++ namespaces in code generated by HydraExpress, see
“Namespaces.” Unmarshaling
HydraExpress generated a C++ API that unmarshaled the XML above. Once the data is unmarshaled, you can then analyze and manipulate the data using the type-safe C++ API. Finally, you can generate the XML that conforms to the above schema by taking the modified tree and marshaling it to XML.
Before unmarshaling the XML document, you must create an instance of the C++ type that corresponds with the root element of the XML document. In the purchase order example, this element is the purchaseOrder element, which is namespace qualified. Without the using statement, you would need to qualify the element name when creating an instance:
po::PurchaseOrder po;
But with the using statement, you can simply declare:
PurchaseOrder po;
To unmarshal an XML document, read it into the implementation and invoke the unmarshal() method on the instance.
try {
std::ifstream istrm("po1.xml"); //1
RWCString xmlContents;
xmlContents.readFile(istrm);
po.unmarshal(xmlContents); //2
} catch (const rwsf::XmlParseException &e) {
std::cerr << "Parse error when unmashaling : " << e.what()
<< std::endl;
std::cerr << "Line number: " << e.getLineNumber() << std::endl;
std::cerr << "Column number: " << e.getColumnNumber()
<< std::endl;
return 1;
} catch (const rwsf::Exception &x) {
std::cerr << "Error : " << x.what() << std::endl;
return 1;
}
Note that the code above is nearly identical to that in the basic example, except that it uses RWCString from SourcePro C++ rather than a standard library string. Adding the XML namespace qualification does not affect the use of the generated API. HydraExpress takes care of the underlying details.
Manipulating XML Content in C++
This example adds a new item to the purchase order instance that was unmarshaled before marshaling it back out.
The purchase order schema defines a type called Items which has a child element named item of type Item, which can occur an unlimited number of times. HydraExpress maps this definition to an std::vector of the type Item. A typedef on the Items class is generated with the type name concatenated with the word Vector, which can be used to reference the vector type.
The code below illustrates how this collection can be used to add a new toaster to the purchase order. First get the old list and store a copy of it to the local variable named itemVector, as shown here:
// Manipulate the object hierarchy by adding an additional item
// to the existing list of items
Items::ItemsItemVector & itemVector = po.getItems().getItemsItemVector();
Then create a new item that represents a toaster to purchase, and set the details that correspond to that toaster:
// Create the new toaster item
ItemsItem toaster;
toaster.setUSPrice(RWDecimalPortable("24.98"));
toaster.setProductName("Toaster Oven");
toaster.setShipDate(RWDate(19, 5, 1999));
toaster.setQuantity(1);
toaster.setPartNum("930-AA");
toaster.setComment("Four slice model");
Append this new item to the item vector before creating the new Items instance that was defined in the purchase order schema. The only member on the Items instance is an item vector, which you set to the modified vector instance, as shown here:
// Add it to the vector
itemVector.push_back(toaster);
Marshaling
You can then call the marshal() method on the root object. The code below illustrates this step and prints the result to standard out.
// Invoke the marshal method on the object
// to create XML from tree and print the result to standard out
std::cout << po.marshal() << std::endl;