XML Schema
There are several ways to define a schema for an XML document. HydraExpress supports the W3C XML Schema definition language. XML Schema documents are themselves XML. XML Schema offers the ability to express complex document structures. The language includes a large set of primitive datatypes and allows schema designers to create new datatypes based on the primitive datatypes. The XML Schema specifications are available online at the W3C web site.
Classes in a HydraExpress XML binding closely follow the definitions in the schema. For example, given the XML Schema document below:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="greeting" type="GreetingType"/>
<xsd:complexType name="GreetingType">
<xsd:sequence>
<xsd:element name="message" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
The default configuration of the HydraExpress code generator creates a C++ XML binding with the structure shown in
Figure 2:
HydraExpress creates classes that closely correspond to the definitions in the schema.
The schema defines a type
GreetingType that contains a single element of type
xsd:string. HydraExpress creates a class
GreetingType that contains a single
std::string. Since class
GreetingType represents a datatype rather than a specific element, the default name of a
GreetingType object is "GreetingType" in the default namespace.
The message element is accessed by the getMessage() and setMessage() functions of this class. The class also provides a pair of marshal() methods that produce XML, and a pair of unmarshal() methods that populate an instance of the class from XML.
The schema defines a top level element named
Greeting of type
GreetingType. HydraExpress creates a class
Greeting that derives from class
GreetingType.
The default name of a Greeting object is "greeting". The Greeting class overrides the marshal() methods and one of the unmarshal() methods of GreetingType so that these methods use the name of the element, "greeting", when writing and reading XML rather than the type name.
Creating an XML document from the generated classes is simple. The code sample below is a complete program that creates an XML document that follows the schema above:
#include "Greeting.h"
#include <iostream>
int main(void)
{
Greeting greeting;
greeting.setMessage("Hello! "
"Thank you for using HydraExpress.");
try {
std::cout << greeting.marshal() << std::endl;
}
catch (const rwsf::Exception& e) {
std::cerr << "Error marshaling document : " << e.what()
<< std::endl;
return 1;
}
return 0;
}
The program produces the output shown below:
<greeting>
<message>Hello! Thank you for using HydraExpress.</message>
</greeting>
Reading an XML document with HydraExpress is equally simple. The code sample below unmarshals an XML document into a Greeting object, modifies the contents of the object, and then writes the object to the standard output:
#include "Greeting.h"
#include <iostream>
int main(void)
{
std::string document = "<greeting>\n"
"<message></message>\n"
"</greeting>";
Greeting greeting;
try {
greeting.unmarshal(document);
greeting.setMessage("Good day!");
std::cout << greeting.marshal() << std::endl;
}
catch (const rwsf::XmlParseException& e) {
std::cerr << "Error parsing document: " << 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& e) {
std::cerr << "Error : " << e.what()
<< std::endl;
return 1;
}
return 0;
}
The program produces the output shown below:
<greeting>
<message>Good day!</message>
</greeting>