See Handling elements: startElement See Handling elements: endElement See Handling non-element data: charData XML * xml_read (FILE * file) { XML_Parser parser; char buf[BUFSIZ]; int done; XML * ret; ret = NULL; parser = XML_ParserCreate(NULL); XML_SetUserData (parser, (void *) &ret); XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, charData); done = 0; do { size_t len = fread(buf, 1, sizeof(buf), file); done = len < sizeof(buf); if (!XML_Parse(parser, buf, len, done)) { output ('E', "XML error: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); xml_free (ret); return NULL; } } while (!done); XML_ParserFree(parser); return (ret); } |
startElement
handler, then, does a great deal of the work of creating
XML data structures. The userData
parameter points to the immediate parent
of the node being encountered. When we open a new node, we allocate the data structure
and copy attributes, append the new node to its parent, then we set userData to point to the
new node -- when the element closes, we move userData up the chain back to the parent.
In the case of an empty element, expat fortunately calls first the open handler, then the
close handler, so whether we have an explicitly empty element or not doesn't matter.
It's astounding how much simpler this startElement
is than the corresponding
handler in xmltools!
void startElement(void *userData, const char *name, const char **atts) { XML ** parent; XML * element; element = xml_create (name); while (*atts) { xml_set(element, *atts++, *atts++); } parent = (XML **) userData; if (*parent != NULL) xml_append (*parent, element); *parent = element; } |
void endElement(void *userData, const char *name) { XML ** element; element = (XML **) userData; if ((*element)->parent != NULL) *element = (*element)->parent; } |
void charData (void *userData, const XML_Char *s, int len) { XML ** parent; parent = (XML **) userData; xml_append (*parent, xml_createtextlen ((char *) s, len)); } |
This code and documentation are released under the terms of the GNU license. They are additionally copyright (c) 2000, Vivtek. All rights reserved except those explicitly granted under the terms of the GNU license. |