Design Patterns in XML Applications
by Fabio Arciniegas A.
|
Pages: 1, 2, 3, 4, 5, 6
Synopsis
|
Contents |
|
Design Patterns in XML Applications |
Wrapper is a structural pattern used to allow an existing piece of software to interact in an environment different from its originally intended one. Wrapper is very similar to the famous Adapter pattern. The difference between the patterns is not predominantly structural, but rather in their intentions: Adapter seeks to make an existing object work with other known objects that expect something, while Wrapper is focused on providing a different interface (without knowing in advance its clients) and solving platform/language issues.
Structure
|
| Figure 7. Wrapper Pattern Structure |
XML Context
Wrapper is one of the most easily identifiable patterns in the XML world. Even though its explanation is very simple, it is worth mentioning because of its frequency.
A wrapper pattern is used every time an existing parser is adapted to work in another language. A new interface that uses constructs of the new language is defined, yet little or no change in the functionality takes place.
One common source of wrappers in XML is James Clark's expat. Wrappers for expat (developed in C) have been written in numerous languages. Several wrappers are available for C++ (including expatpp), Perl, and other languages.
In the example, we will look at the original C interface of expat, and the C++ wrapper that adapts it for object-oriented manipulation. See also the end of the example section for pointers to complete wrappers of expat.
Example
Expat works by calling functions, called handlers, when certain events occur (for more about expat, refer to Clark Cooper's XML.com article on expat). The following is a small part of the original expat interface, defining the type of a handler, and a function to register handlers for listening to "start element" and "end element" events:
...
/* atts is array of name/value pairs, terminated by 0;
names and values are 0 terminated. */
typedef void (*XML_StartElementHandler)(void *userData,
const XML_Char *name,
const XML_Char **atts);
...
void XMLPARSEAPI
XML_SetElementHandler(XML_Parser parser,
XML_StartElementHandler start,
XML_EndElementHandler end);
Expat can be used directly in a C++ project, however, several wrappers have been devised to take advantage of C++ syntax. A good example is Andy Dent's expatpp.
All expatpp does is simplify the interface for C++ programmers by wrapping an expat parser in a class:
class expatpp {
public:
expatpp();
~expatpp();
operator XML_Parser() const;
// overrideable callbacks
virtual void startElement(const XML_Char* name, const XML_Char** atts);
virtual void endElement(const XML_Char* name);
virtual void charData(const XML_Char *s, int len);
virtual void processingInstruction(const XML_Char*
target, const XML_Char* data);
...
In order to adapt the expat interface for the new object-oriented calls, the constructor binds the expat callbacks to the corresponding method. Thus, all you have to do in order to handle a particular kind of event is to override the method in a subclass. If you have never worked with expat, this could be a little confusing, but don't worry. The key to understanding it is to look at the code itself: wrapper.zip
Summary of Common XML Uses
The wrapper pattern is useful in XML applications when:
-
You want to reuse a piece of XML software in an environment different from the one initially intended.
In this section we reviewed Wrapper, a structural pattern useful for adapting XML applications and processors. In the next and final section, we will see Iterator, a behavioral pattern that is very useful in object-model-based contexts.