OOFILE | Downloads | Purchasing | Press | Services | Company Information | Soapbox | References | F.A.Q. | HOME 

 

XML NESTING PARSERS via expatpp

The following discussion explains in more details the most powerful aspect of expatpp, taking it far beyond being a mere C++ wrapper for expat. It was written as a response to an email from an expatpp user asking there´s one important thing for what I can not find an easy solution: How can I determine the position of an element in the documents hierarchy?

The information hiding approach which expatpp was designed for assumes you will write a number of sub-parsers which are each as simple as possible, and know about the elements within. Think of it as writing subroutines. Each parser is as simple as it can possibly be.
This also facilitates reuse of parsers and reconfiguration of the document hierarchy. It fixes one of the biggest weaknesses in typical XML application parser designs (as discussed in: http://www.xml.com/pub/a/1999/09/expat/index.htm).

I designed expatppNesting as an extension of expatpp after turning loose an employee to start writing the parser for the report writer and seeing the kinds of assumptions he made and how quickly we could end up with a maintenance nightmare :-)

Try to get away from knowledge of the hierarchy. Typically, a caller supplies a newly created sub-parser with the location to which it should return data, usually a pointer or reference to some object and the destructor of the sub-parser will update that return value.

For example, in our report-writer parsers, an oofXMLdataParser just knows the database table to which it is adding data, not anything about the context. Similarly, OOF_XMLrepAdornerParser is passed in a dictionary to which it should add adorners (that could belong to any level of a report layout) and our most trivial, the OOF_XMLrepStyleParser, just returns a string.

Our report writer parses database schema, report layout and data to populate the report. Source is available at <http://www.oofile.com.au/downloads.html> and you can read more about the classes at <http://www.oofile.com.au/oofile_ref/html/group__oof_rep_read.html>


The OOF_XMLrepParser either does simple local actions or typically creates lower lever parsers, eg:

//Main procedure calls virtual functions, so this report parser can be customised. 

void
OOF_XMLrepParser::startElement(const char* name, const char** atts)
{
	if(strcmp(name,"report")==0)
		startElem_report(atts);
		
	else if(strcmp(name,"section")==0)
		startElem_section(atts);
		
	else if(strcmp(name,"style")==0)
		startElem_style(atts);

	else if(strcmp(name,"adorners")==0)
		startElem_adorners(atts);

	else if(strcmp(name,"layout")==0)
		startElem_layout(atts);

	else if(strcmp(name,"schema")==0)
		startElem_schema(atts);

	else
		startUnknownElem(name, atts);

}

// A simple default virtual function creates the next parser down
void
OOF_XMLrepParser::startElem_schema(const char** atts)
{
		new oofXMLschemaParser(this);  // self-deleting sub parser
}