Definitions

Previous: index ] [ Top: index ] [ Next: Functions except for xml_read ]

I define three basic datastructures for dealing with XML: the element, the attribute, and the element list. Each of these has a struct definition (_element, _attr, and _list respectively) and a pointer typedef (XML, ATTR, and ELEMENTLIST). My apologies that the names don't match up, but it makes sense to me: the struct names reflect a lower-level appreciation for what the objects are, while the typedefs relect a higher-level view of what they're to be used for. Yeah. Anyway, that's my left-brain rationalization for an essentially right-brained nomenclature.

July 18, 2001: I've included a valsize in the attribute structure; this will allow us to make use of dynamic allocation to do things like xml_attrcat, which will concatenate a string onto the attribute value. If valsize is zero, then we can't assume anything about the allocated piece; if we're asked to concatenate onto it, we'll just realloc on the spot.

December 16, 2001: I hadn't really realized the impact of my linked-list implementation of the children list until I needed to append 9000 children to a list repeatedly. The overhead of scanning for that is 9000 * 9000 / 2 = 4.5 million operations. Not scalable! So since the list is doubly linked anyway, the _element struct now points to the last child as well as the first.
 
#include <stdio.h>
#include <stdarg.h>
#ifndef XMLAPI_H
#define XMLAPI_H
#ifdef __cplusplus
extern "C" {
#endif

typedef struct _element XML;
typedef struct _attr ATTR;
typedef ATTR XML_ATTR;
typedef struct _list ELEMENTLIST;

struct _element {
   char * name;
   ATTR * attrs;
   XML * parent;
   ELEMENTLIST * children;
   ELEMENTLIST * lastchild; /* For quicker append. */
   void * extra;
   void (*cleanup) (void *);
};

struct _attr {
   char * name;
   char * value;
   int valsize; /* For dynamic allocation; we track the buffer. */
   ATTR * next;
};

struct _list {
   XML * element;
   ELEMENTLIST * next;
   ELEMENTLIST * prev;
};
Those datastructures suffice to represent an XML file in memory, semi-efficiently (although hash lookup for element and attribute names will be a nice feature at some later date) and completely.

Note the "extra" and "cleanup" members of each element; these provide a handy way to attach arbitrary binary data to any element, and clean it up automatically when the element is cleaned up. If the cleanup pointer is NULL, no cleanup will be done; if the extra pointer is NULL, obviously no cleanup can be done. The cleanup function returns nothing and takes a single void pointer; thus it matches malloc, for instance.

In Windows, the XMLAPI compiles to a DLL (well, optionally). Since you need to specify which functions should be exported from a DLL (that is, visible to linkers), we need to define a special API spec XMLAPI. If told nothing else, we'll assume that the XMLAPI spec should simply be ignored:
 
#ifndef XMLAPI
#define XMLAPI
#endif
But we can define XMLAPI on the compiler's command line to export API functions from the DLL.

Anyway, the XML API itself consists of quite a little list of functions, as follows. (The comment headers are an attempt to break things up into manageable chunks, since this same API is now reflected in at least four wrappers -- raw Python, OO Python, AOLserver/Tcl, and Java JNI. It's getting harder to keep them all in synch, which has been rather irritating during JNI development, especially.)
 
/* API as of 2003-08-12 */
/* ------------------------------------------------------
   Incidental stuff
   ------------------------------------------------------ */
typedef void (XML_SETBIN_FREE_FN) (void *);
XMLAPI char * xml_strdup (const char * str);
XMLAPI void   xml_strfree (char * str);

/* ------------------------------------------------------
   Formatting XML strings
   ------------------------------------------------------ */
XMLAPI char * xml_string (XML * xml);
XMLAPI char * xml_stringcontent (XML * xml);
XMLAPI char * xml_stringhtml (XML * xml);
XMLAPI char * xml_stringcontenthtml (XML * xml);

/* ------------------------------------------------------
   File I/O: writing to files
   ------------------------------------------------------ */
XMLAPI void xml_write            (FILE * file, XML * xml);
XMLAPI void xml_writecontent     (FILE * file, XML * xml);
XMLAPI void xml_writehtml        (FILE * file, XML * xml);
XMLAPI void xml_writecontenthtml (FILE * file, XML * xml);
XMLAPI int  xml_output (char * file, XML * xml, int mode);
XMLAPI int  xml_save (XML * xml, const char * spec, ...);
typedef size_t (*XMLAPI_DATAWRITE) (char * buf, size_t num, size_t chunkc, void*);
XMLAPI void xml_write_general            (void * data, XMLAPI_DATAWRITE write_data, XML * xml);
XMLAPI void xml_writecontent_general     (void * data, XMLAPI_DATAWRITE write_data, XML * xml);
XMLAPI void xml_writehtml_general        (void * data, XMLAPI_DATAWRITE write_data, XML * xml);
XMLAPI void xml_writecontenthtml_general (void * data, XMLAPI_DATAWRITE write_data, XML * xml);

/* ------------------------------------------------------
   File I/O and parsing: reading XML from files/strings
   ------------------------------------------------------ */
XMLAPI XML * xml_read (FILE * file);
XMLAPI XML * xml_read_error (FILE * file);
XMLAPI XML * xml_parse (const char * buf);
XMLAPI XML * xml_load (const char * spec, ...);
typedef size_t (*XMLAPI_DATARETRIEVE) (char *buf, size_t num, size_t chunk, void *);
XMLAPI XML * xml_parse_general (void * data, XMLAPI_DATARETRIEVE get_data);

/* ------------------------------------------------------
   Attribute access
   ------------------------------------------------------ */
XMLAPI const char * xml_attrval (XML * element,const char * name);
XMLAPI int xml_attrvalnum (XML * element,const char * name);
XMLAPI XML_ATTR * xml_attrfirst (XML * element);
XMLAPI XML_ATTR * xml_attrnext  (XML_ATTR * attr);
XMLAPI const char * xml_attrname (XML_ATTR * attr);
XMLAPI const char * xml_attrvalue (XML_ATTR * attr);
XMLAPI void xml_attrcat (XML * xml, const char *name, const char *value);
XMLAPI void xml_attrncat (XML * xml, const char *name, const char *value, int len);
/* xml_attrs: implemented in Py as dictionary return? */
/* xml_attrlist: string list of attr names: Py low-level/OO, JNI */

XMLAPI char * xml_string_format (const char * format, ...);  /* Doesn't really fit into the "attribute access" category, but it's too useful not to export. */
XMLAPI char * xml_string_formatv (const char * format, va_list args);
XMLAPI void xml_set (XML * xml, const char * name, const char * value);
XMLAPI void xml_setf (XML * xml, const char * name, const char * format, ...);
XMLAPI void xml_setnum (XML * xml, const char *attr, int number);
XMLAPI void xml_unset (XML * xml, const char * name);
XMLAPI void xml_set_nodup (XML * xml, const char * name, char * value);

/* -----------------------------------------------------
   Subelement identification and iteration
   ----------------------------------------------------- */
/* xml_elements: implemented in Py OO as list return */
XMLAPI const char * xml_name (XML * xml);
XMLAPI void  xml_rename (XML * xml, const char * newname);
XMLAPI XML * xml_parent (XML * xml);
XMLAPI int   xml_is_element (XML * xml);
XMLAPI int   xml_is (XML * xml, const char * name); /* is_a in Py OO */
XMLAPI XML * xml_first (XML * xml);
XMLAPI XML * xml_firstelem (XML * xml);
XMLAPI XML * xml_last (XML * xml);
XMLAPI XML * xml_lastelem (XML * xml);
XMLAPI XML * xml_next (XML * xml);
XMLAPI XML * xml_nextelem (XML * xml);
XMLAPI XML * xml_prev (XML * xml);
XMLAPI XML * xml_prevelem (XML * xml);
/* iterate, iterator, rewind, advance in Py OO */

/* -----------------------------------------------------
   Element manipulation
   ----------------------------------------------------- */
XMLAPI XML * xml_create (const char * name);
XMLAPI XML * xml_createtext (const char * value);
XMLAPI XML * xml_createtextf (const char * format, ...);
XMLAPI XML * xml_createtextlen (const char * value, int len);
XMLAPI XML * xml_createtext_nodup (char * value);
XMLAPI void xml_textcat (XML * xml, const char * value);
XMLAPI void xml_textncat (XML * xml, const char * value, int len);

XMLAPI void xml_delete(XML * piece);
XMLAPI void xml_delete_pretty(XML * piece);
XMLAPI void xml_free (XML * xml);

XMLAPI XML * xml_copy (XML * xml);
XMLAPI XML * xml_copyinto (XML * target, XML * source);
XMLAPI XML * xml_copyattrs (XML * target, XML * source);

XMLAPI void xml_replace (XML * xml, XML * newxml);
XMLAPI void xml_replacecontent (XML * parent, XML * child);
XMLAPI void xml_replacewithcontent (XML * xml, XML * source);

XMLAPI void xml_prepend (XML * parent, XML * child);
XMLAPI void xml_prepend_pretty (XML * parent, XML * child);
XMLAPI void xml_append (XML * parent, XML * child);
XMLAPI void xml_append_pretty (XML * parent, XML * child);
XMLAPI XML * xml_insertafter (XML * parent, XML * child);
XMLAPI XML * xml_insertbefore (XML * parent, XML * child);

/* ----------------------------------------------------
   Finding pieces of XML
   ---------------------------------------------------- */
XMLAPI XML * xml_loc (XML * start, const char * loc);
XMLAPI XML * xml_locf (XML * start, const char * loc, ...);
XMLAPI void xml_getloc (XML * xml, char *loc, int len);
XMLAPI char * xml_getlocbuf (XML * xml);

XMLAPI XML * xml_search (XML * start, const char * element, const char * attr, const char * value);
XMLAPI XML * xml_searchf (XML * start, const char * element, const char * attr, const char * format, ...);
XMLAPI XML * xml_search_next (XML * top, XML * start, const char * element, const char * attr, const char * value);
XMLAPI XML * xml_searchf_next (XML * top, XML * start, const char * element, const char * attr, const char * format, ...);
/* xml_search_all: Py OO list return */
XMLAPI XML * xml_search_all (XML * start, const char * element, const char * attr, const char * value);
XMLAPI XML * xml_searchf_all (XML * start, const char * element, const char * attr, const char * format, ...);

/* ----------------------------------------------------
   Binary pointer access
   ---------------------------------------------------- */
XMLAPI void  xml_setbin (XML * xml, void * bin, XML_SETBIN_FREE_FN *cleanup);
XMLAPI void * xml_getbin (XML * xml);

/* ----------------------------------------------------
   UTF8 stuff
   ---------------------------------------------------- */
XMLAPI int   xml_toutf8_attr (XML * xml, const char * attrname);
XMLAPI int   xml_toutf8_text (XML * xml);
XMLAPI int   xml_toraw_str (char * buffer, const char * utf8);

/* ----------------------------------------------------
   Sorting
   ---------------------------------------------------- */
XMLAPI XML * xml_sort (XML * list, XML * sort);

/* ----------------------------------------------------
   Misc useful stuff
   ---------------------------------------------------- */
XMLAPI XML * xml_assemble (XML * start, XML * src);

#ifdef __cplusplus
}
#endif
#endif
Previous: index ] [ Top: index ] [ Next: Functions except for xml_read ]


This code and documentation are released under the terms of the GNU license. They are copyright (c) 2000-2003, Vivtek. All rights reserved except those explicitly granted under the terms of the GNU license. This presentation was created using LPML.