Objective Grid : PART II Programmer’s Guide : Chapter 23 XML Read/Write Library : Macros and Tools Ease Development
Macros and Tools Ease Development
There are two sets of macros. One set of macros populate the XML_ENTRY_MAP structures. With these macros the most important issue is that the nesting of these has to be just right. Shown below is a set of these macros that describe an XML schema to store addresses.
 
BEGIN_XML_MAP(CAddressXMLMap)
XML_ROOT_ENTRY()
SEC_XML_NEST()
SEC_XML_START()
XML_ELEMENT_ENTRY(ADDRESSES, eAddresses)
SEC_XML_NEST()
SEC_XML_START()
XML_ELEMENT_ENTRY(ADDRESS, eAddress)
SEC_XML_NEST()
WRAP(XML_TEXT_ENTRY(FIRST, eFirst))
SEC_XML_START()
XML_TEXT_ENTRY_NS(s:LAST, eLast, _T("stingray.com"))
SEC_XML_NEST()
WRAP(XML_ATTRIBUTE_ENTRY(SALUTATION,
eSalutation))
END_SEC_XML_NEST()
SEC_XML_END()
WRAP(XML_TEXT_ENTRY_NS(s:OFFICECODE, eOfficeCode,
_T("stingray.com")))
WRAP(XML_TEXT_ENTRY(PHONE, ePhone))
SEC_XML_START()
XML_TEXT_ENTRY(EMAIL, eEmail)
SEC_XML_NEST()
WRAP(XML_COMMENT_ENTRY(EMAILCOMMENT, eEmailComment))
END_SEC_XML_NEST()
SEC_XML_END()
END_SEC_XML_NEST()
SEC_XML_END()
END_SEC_XML_NEST()
SEC_XML_END()
END_SEC_XML_NEST()
END_XML_MAP()
Some important points to be noted:
All XML_MAP definitions have to start with XML_ROOT_ENTRY(). This cannot be changed in this version. If you wish to have additional data written as part of the root you can add these on completion of the write operation.
When a node has child nodes, these have to be listed within SEC_XML_NEST() and END_SEC_XML_NEST() macros.
When a node has no children, then it can be completely wrapped within the WRAP(…) macro.
When a node does have children, it has to be bounded by SEC_XML_START() and SEC_XML_END() macros.
While composing the XML_MAP using this set of macros is not hard, it is quite tedious. Just the kind of work that begs for automation. We supply a tool (xml_tool.exe, located in the bin folder of your Objective Grid installation) that automates this step. This tool takes a valid schema and generates this map, as well as some other defines that are essential, notably the unique defines and an enum.
Writing the second map, the WRITE_MAP, is a lot easier. This has no hierarchy. A sample map is shown below. Each unique id is mapped to a handler function. Internally these macros map the resolver interfaces to this handler. Each of the resolver call backs maps to a different context value when the handler is called.
Please refer to the help file discussion of eTypeRWContext for a description of the various context values.
The resolver that is used along with the macros is to be derived from IXMLRWResolver and CentryValueHolder.
Sample WRITE_MAP
 
BEGIN_WRITE_MAP(CAddressResolver)
WRITE_MAP_ENTRY(eAddresses, AddressesHandler)
WRITE_MAP_ENTRY(eAddress, AddressHandler)
WRITE_MAP_ENTRY(eFirst, FirstHandler)
WRITE_MAP_ENTRY(eLast, LastHandler)
WRITE_MAP_ENTRY(eSalutation, SalutationHandler)
WRITE_MAP_ENTRY(eOfficeCode, OfficeCodeHandler)
WRITE_MAP_ENTRY(ePhone, PhoneHandler)
WRITE_MAP_ENTRY(eExt, ExtHandler)
WRITE_MAP_ENTRY(eEmail, MailHandler)
WRITE_MAP_ENTRY(eEmailComment, eMailCommentHandler)
END_WRITE_MAP()
This map is not generated by the tool. This has to be written by hand. Each handler is defined as:
 
void Handler(XML_ENTRY_PARAM& pParam, eTypeRWContext context,
bool& bRetval, XMLVALUE& value)
XML_ENTRY_PARAM is just a wrapper around XM_ENTRY_MAP and other essential data. Refer to the help file for information on eTypeRWContext and XMLVALUE. Looking at the resolver interfaces you can easily map to one of the eTypeRWContext values.